간단한 계산기 프로그램
글쓴이: WanTheMagician / 작성시간: 토, 2006/01/07 - 8:43오후
간단한 계산기 프로그램을 만들어 봤는데요.
우분투 리눅스 gcc 4.0에서 컴파일 하였음.
사용한 함수는 오로지 printf, gets뿐이며, gets는 바꿀예정임. 경고 발생...
나머지 함수는 직접 제작해 보았습니다.
한번에입력가능 문자 128개 정도이며, 빈 칸은 빈칸을 없애므로 사용가능...
계산 가능 연산 +,-,*,/과 ( )모두 사용가능함.
한 번 써 보시고 무슨 문제가 있는지 테스트를 부탁드립니다.
차후 sin, cos, exp 등을 제공하면 제대로 된 버전 1.0이 될 겁니다.
그리고 디버그하기 위해 변수의 내용을 출력하는 부분이 들어있어요, 즉, 아직 최적화
된 상태는 아닙니다.
/* This program is calculation program for all Made by dooseon.choi date 2006.01.06. 16:40 version 0.1.1 */ #include <stdio.h> #define MAX_STRING (128) #define ST_MAX (50) char input[MAX_STRING]; int errornum; double calculate(char str[],double ans); double tonumber(char str[]); double tonumericonechar(char str); double power(int base,int sub); int notnumeric(char str[]); int main(int argc,char *argv,char *env[]) { int i,j=0; double result=0.; char temp[MAX_STRING]; printf("This program is calculation program for all\n"); printf("It can only translate ONLY integer\n"); printf(" NOT exponential expression!\n"); printf("It can read ONLY %d characters! first put number!\n",MAX_STRING); printf("EXIT is Q\n"); do { printf("enter expression :"); gets(temp); /* IT will be change because it cause warning */ if (temp[0]=='Q') return 0; /* delete blank */ for (i=0,j=0;temp[i] != '\0';i++) { if (temp[i]!=' ') { input[j]=temp[i]; printf("%c \n", input[j]); j++; } } input[j] = '\0'; result = calculate(input,result); printf("result : %f\n", result); } while (input[0] != 'Q'); return 1; } /* This calculates string form to double */ double calculate(char str[],double ans) { int i, j,n; int strlen=0,token1=0,token2=0; char str1[MAX_STRING],str2[MAX_STRING]; double stack[ST_MAX]; int st_pointer=0; double temp1,temp2; double ret=0; strlen=stringlength(str); do { token2=get_token(str,token1); printf("token %d, %d \n",token1, token2); for (i=token1;i<=token2-1;i++) str1[i-token1]=str[i]; str1[i-token1]='\0'; token1=token2; printf("first token is %s \n",str1); switch (str1[0]) { case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : case '-' : case '+' : /*push */ if (st_pointer >=ST_MAX) { printf("Stack over flow!\n"); return 0; } if (str1[1]=='(') { for(i=0;i<=stringlength(str1)-1;i++) str2[i]=str1[i+2]; str2[i]='\0'; if (str1[0]=='-') stack[st_pointer]=-calculate(str2,0); else stack[st_pointer]=calculate(str2,0); } else stack[st_pointer]=tonumber(str1); printf("%f of %d\n",stack[st_pointer],st_pointer); st_pointer++; break; case '*' : /* pop and multiply it and push it */ if (st_pointer <=0) { printf("Stack under flow!\n"); return 0; } st_pointer--; temp1 = stack[st_pointer]; if (str1[1]=='(') { for(i=0;i<=stringlength(str1)-1;i++) str2[i]=str1[i+2]; str2[i]='\0'; if (str1[0]=='-') temp2=-calculate(str2,0); else temp2=calculate(str2,0); } else { for (i=0;str1[i] != '\0';i++) str2[i]=str1[i+1]; str2[i]='\0'; temp2 = tonumber(str2); } if (st_pointer >=ST_MAX) { printf("Stack over flow!\n"); return 0; } stack[st_pointer]=temp1*temp2; printf("%f of %d\n",stack[st_pointer],st_pointer); st_pointer++; break; case '/' : /* pop and divide it and push it */ if (st_pointer <=0) { printf("Stack under flow!\n"); return 0; } st_pointer--; temp1 = stack[st_pointer]; if (str1[1]=='(') { for(i=0;i<=stringlength(str1)-1;i++) str2[i]=str1[i+2]; str2[i]='\0'; if (str1[0]=='-') temp2=-calculate(str2,0); else temp2=calculate(str2,0); } else { for (i=0;str1[i] != '\0';i++) str2[i]=str1[i+1]; str2[i]='\0'; temp2 = tonumber(str2); } if (st_pointer >=ST_MAX) { printf("Stack over flow!\n"); return 0; } stack[st_pointer]=temp1/temp2; printf("%f of %d\n",stack[st_pointer],st_pointer); st_pointer++; break; case '(' : if (st_pointer >=ST_MAX) { printf("Stack over flow!\n"); return 0; } for(i=0;i<=stringlength(str1)-2;i++) str1[i]=str1[i+1]; str1[i]='\0'; stack[st_pointer]= calculate(str1,0); st_pointer++; break; } } while (token1<strlen-1); for (i = 0 ; i < st_pointer;i++) ret = ret + stack[i]; return ret; } /* return number of string */ int get_token(char str[],int ftoken) { int reti, n=0; for (reti=ftoken;;) switch (str[reti]) { case '.' : case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : case 'e' : case 'E' : reti++; break; case '-' : if (reti==ftoken || str[reti-1] == 'e' || str[reti-1] =='E') reti++; else return reti; break; case '+' : if (reti==ftoken) reti++; else return reti; break; case '*' : if (reti==ftoken) reti++; else return reti; break; case '/' : if (reti==ftoken) reti++; else return reti; break; case '(' : n++; for (reti=reti+1;n>0;reti++) { if (str[reti]=='(') n++; if (str[reti]==')') n--; } return reti; break; case '\0' : return reti; default : return reti; } } int stringlength(char str[]) { int reti = 0; for (reti=0;str[reti]!='\0';reti++) ; return reti; } /* This return double number from string */ double tonumber(char str[]) { int i=0,j; int negati=0; double ret=0; char str1[MAX_STRING]; if (str[0]=='\0') return ret; if (str[0]=='-') { negati = 1; i += 1; } if (str[0]=='+') { negati =0; i += 1; } ret = (double) tonumericonechar(str[i]); i++; for (;str[i]!='\0'&&str[i]!='.'&&str[i]!='e'&&str[i]!='E';i++) { ret = ret*10.; ret = ret + tonumericonechar(str[i]); } i++; if ((str[i-1]=='.')&&(str[i]>='0')&&(str[i]<='9')) for(j=1;str[i]!='\0'&&(str[i]!='e'||str[i]!='E');i++,j++) ret= ret+tonumericonechar(str[i])*power(10,-j); if (str[i-1]=='e' || str[i-1]=='E') { for(j=0;str[i]!='\0';i++,j++) str1[j]=str[i]; str1[j]='\0'; ret = ret*power(10,(int) tonumber(str1)); printf("%f\n",tonumber(str1)); } if (negati==1) return -ret; else return ret; } double power(int base, int super) { int i; double ret=1; if (super >=0) for (i=1;i<=super;i++) ret =ret*(double)base; if (super <0){ for (i=1;i<=-super;i++) ret = ret*(double)base; ret = 1/ret; } return ret; } double tonumericonechar(char str) { return str-'0'; }
Forums:
자세히 읽은 것은 아니지만double tonumericonechar(
자세히 읽은 것은 아니지만
double tonumericonechar(char str)
함수는 이렇게 바꾸면 어떨까요?
return str - '0';
아니면 atof 같은...
일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.
Code BBCode를 사용해주는 센스~http://bbs.kld
Code BBCode를 사용해주는 센스~
http://bbs.kldp.org/faq.php?mode=bbcode#5
C에서 제공하는 함수는 최소한 으로 줄이고짜 보려구요...si
C에서 제공하는 함수는 최소한 으로 줄이고
짜 보려구요...
sin, cos, tan, exp도 제가 직접 해보려고 합니다.
Have a nice day!
[quote="WanTheMagician"]C에서 제공하는 함수는 최소한
설마 모든 함수를 시스템 콜로 돌리시려고요? (예를 들어서 윈도우라면 fopen 대신 CreateFile... 등등등) sin, cos, tan, exp 같은 건 그대로 쓰는 게 정신 건강에 이로울 겁니다. 정 구현하고 싶으시면 glibc 소스를 잘 뒤져 보시면 있긴 한데 읽기는 힘들 겁니다.
(물론 IEEE-754 arithmetic을 안 쓰신다면 직접 하셔야 겠지만... 그 정도까지 필요할까요?)
- 토끼군
내장 함수를 쓰시는 게 성능에 더 도움이 될 지 모릅니다. :)
내장 함수를 쓰시는 게 성능에 더 도움이 될 지 모릅니다. :)
* 오차한계/유효자리수를 검토하고, 글로벌 테이블로 미리 값을 생성하여
* 오차한계/유효자리수를 검토하고, 글로벌 테이블로 미리 값을 생성하여 값을 찾는 방법도(테일러시리즈등 안쓰고...) 성능개선에 도움이 됩니다. 마치, 수학책 부록에 있는 테이블처럼 말이지요.
정 sin, cos, tan, exp를 직접 쓰시고 싶지 않으시다면...
정 sin, cos, tan, exp를 직접 쓰시고 싶지 않으시다면...
여러분의 친구 어셈블리
FPU에 직접 접근하세요! (자매품 : 기계어)
Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.
[quote="Anonymous"]* 오차한계/유효자리수를 검토하고, 글
간단한 계산기 수준에서 그 정도의 optimization이 필요할 것 같지는 않습니다. 그리고 보통 유효자리가 네 자리만 넘어 가도 글로벌 테이블을 쓰기는 힘들지 않나요? (물론 interpolation을 쓸 수는 있긴 하지만)
- 토끼군
sdgf
sdt
대학교에서도 간단한 계산기 프로그램은 다루는 것으로 알고 있습니다.
대학교에서도 간단한 계산기 프로그램은 다루는 것으로 알고 있습니다.
제가 다루려는 것은 직접 짜보려는 것입니다. 그래야 프로그래밍 실력이 향상될 것 같아서요.
그리고 시스템콜이란 것은 잘 모르겠구요.
수학함수는 시리즈 전개로 간단히 해결되는 것 같더군요. 5번 전개하면 거의 95%는 맞는다고 들었습니다. 다른 방법이 또 있는지는 잘 모르겠어요.
위에 다시 소수와 지수표현의 숫자계산이 되는 프로그램을 올려 놓았습니다.
아까 말한 수학함수만 완성되면 이 프로그램은 거의 완성이구요.
그 다음은 이 계산기프로그램으로 여러함수의 조합을 그래프로 그리는 것입니다.
Xlib(??)사용
Have a nice day!
댓글 달기