간단한 계산기 프로그램

WanTheMagician의 이미지

간단한 계산기 프로그램을 만들어 봤는데요.

우분투 리눅스 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';
}
쌀밥의 이미지

자세히 읽은 것은 아니지만
double tonumericonechar(char str)
함수는 이렇게 바꾸면 어떨까요?

return str - '0';

아니면 atof 같은...

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

나는오리의 이미지

Code BBCode를 사용해주는 센스~

http://bbs.kldp.org/faq.php?mode=bbcode#5

WanTheMagician의 이미지

C에서 제공하는 함수는 최소한 으로 줄이고
짜 보려구요...

sin, cos, tan, exp도 제가 직접 해보려고 합니다.

Have a nice day!

lifthrasiir의 이미지

WanTheMagician wrote:
C에서 제공하는 함수는 최소한 으로 줄이고
짜 보려구요...

sin, cos, tan, exp도 제가 직접 해보려고 합니다.

설마 모든 함수를 시스템 콜로 돌리시려고요? (예를 들어서 윈도우라면 fopen 대신 CreateFile... 등등등) sin, cos, tan, exp 같은 건 그대로 쓰는 게 정신 건강에 이로울 겁니다. 정 구현하고 싶으시면 glibc 소스를 잘 뒤져 보시면 있긴 한데 읽기는 힘들 겁니다.

(물론 IEEE-754 arithmetic을 안 쓰신다면 직접 하셔야 겠지만... 그 정도까지 필요할까요?)

- 토끼군

7339989b62a014c4ce6e31b3540bc7b5f06455024f22753f6235c935e8e5의 이미지

내장 함수를 쓰시는 게 성능에 더 도움이 될 지 모릅니다. :)

익명 사용자의 이미지

* 오차한계/유효자리수를 검토하고, 글로벌 테이블로 미리 값을 생성하여 값을 찾는 방법도(테일러시리즈등 안쓰고...) 성능개선에 도움이 됩니다. 마치, 수학책 부록에 있는 테이블처럼 말이지요.

cppig1995의 이미지

정 sin, cos, tan, exp를 직접 쓰시고 싶지 않으시다면...

asm FSIN ...
asm FCOS ...
asm FTAN ...
asm FEXP ...

여러분의 친구 어셈블리
FPU에 직접 접근하세요! (자매품 : 기계어)

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

lifthrasiir의 이미지

Anonymous wrote:
* 오차한계/유효자리수를 검토하고, 글로벌 테이블로 미리 값을 생성하여 값을 찾는 방법도(테일러시리즈등 안쓰고...) 성능개선에 도움이 됩니다. 마치, 수학책 부록에 있는 테이블처럼 말이지요.

간단한 계산기 수준에서 그 정도의 optimization이 필요할 것 같지는 않습니다. 그리고 보통 유효자리가 네 자리만 넘어 가도 글로벌 테이블을 쓰기는 힘들지 않나요? (물론 interpolation을 쓸 수는 있긴 하지만)

- 토끼군

익명 사용자의 이미지

sdt

WanTheMagician의 이미지

대학교에서도 간단한 계산기 프로그램은 다루는 것으로 알고 있습니다.

제가 다루려는 것은 직접 짜보려는 것입니다. 그래야 프로그래밍 실력이 향상될 것 같아서요.
그리고 시스템콜이란 것은 잘 모르겠구요.

수학함수는 시리즈 전개로 간단히 해결되는 것 같더군요. 5번 전개하면 거의 95%는 맞는다고 들었습니다. 다른 방법이 또 있는지는 잘 모르겠어요.

위에 다시 소수와 지수표현의 숫자계산이 되는 프로그램을 올려 놓았습니다.

아까 말한 수학함수만 완성되면 이 프로그램은 거의 완성이구요.

그 다음은 이 계산기프로그램으로 여러함수의 조합을 그래프로 그리는 것입니다.
Xlib(??)사용

Have a nice day!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.