计算机2
程序代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<conio.h> #define N 14 int kk,s; /* 将运算符+ - * /左右两边的字符数字转换成双精度形,再运算出结果,并将结果连接存回原字符串 */ char* convert(char *str,char ch) { char a[20],b[20],c[20],d[20],e[100],*p,*q,*t,*endptr; int i,j,l; double x,y,z; i=j=l=0; x=y=z=0; q=str-1; p=str+1; memset(a,'\0',20); memset(b,'\0',20); memset(c,'\0',20); memset(d,'\0',20); memset(e,'\0',100); if(*str<48||*str>57) { /* 是数字或小数点或负号存入a.如果被存的第一个字符是‘-’则为负号,非第一个则为减号*/ while(*p<58&&*p>47||*p=='.'||*p=='-'&&i==0) { a[i++]=*p; p++; } /* 同上,为什么(q-1)=='\0'时‘-’就为负号,参考str来源,来自bracket_match中的数组a*/ while(*q<58&&*q>47||*q=='.'||*q=='-'&&*(q-1)=='\0') { b[j++]=*q; /* 因为是由后向前存,数据是颠倒的*/ q--; } *(q+1)='\0'; strrev(b); /* 将b颠倒过来使之成为对应字符数字 */ x=strtod(a,&endptr); /* 将a,b转换成浮点数进行下面运算 */ y=strtod(b,&endptr); switch(ch) /* 根据传进来的运算符进行相应操作 */ { case '+':z=x+y;break; case '-':z=y-x;break; case '*':z=x*y;break; case '/':z=y/x;break; case '^':z=pow(y,x);break; } } else /* 计算输入函数最终结果 */ { z=strtod(str,&endptr); *str='\0'; switch(kk) { case 0:z=sin(z);break; case 1:z=cos(z);break; case 2:z=tan(z);break; case 3:z=sqrt(z);break; case 4:z=asin(z);break; case 5:z=acos(z);break; case 6:z=atan(z);break; case 7:z=log10(z);break; case 8:z=log(z);break; case 9:z=exp(z);break; case 10:z=fabs(z);break; case 11:z=ceil(z);break; case 12:z=cosh(z);break; case 13:z=floor(z);break; } } gcvt(z,10,d); /* 将浮点型运算结果转换成字符串 */ t=d+strlen(d)-1; if(*t=='.') /* 将转换后数的最后一个小数点去掉 */ *t='\0'; strcat(c,d); /* 下面为重新链接字符串,之后将之拷贝回str中*/ strcat(e,c); strcat(e,p); strcat(q+1,e); l=strlen(c); return (q+l); /* 返回调用此函数时接着的下一个字符 */ } /* 计算顺序,先算乘除,再算加减 */ void cal_order(char *str) { char *p; p=str; while(*p!='\0') { if(*p=='*'||*p=='/'||*p=='^') /* 先算乘除平方 */ p=convert(p,*p); p++; } p=str; while(*p!='\0') { if(*p=='+'||*p=='-'&&p!=str) /* 后算加减 */ p=convert(p,*p); p++; } if(kk<N&&s==0) /* kk<N表示计算函数内表达式,s==0表示计算出函数括号内的最终结果 调用函数计算出函数的最终结果 */ convert(str,*str); } /* 括号匹配,再运算…… */ int bracket_match(char *str) { char a[100],b[200],*p,*q; p=str; memset(a,'\0',100); memset(b,'\0',200); while(*p!='\0') { s=0; /* 控制括号用的 */ if(*p=='(') { q=p; while(*q!=')') { if(*q=='(') { p=q; s++; /* 遇一个左括号加1 */ } q++; } if(*q==')') /* 从第一个while循环到此为寻找到最里层括号*/ { s--; /* 遇右括号减1 再去掉左右括号,当括号数为0时,即s==0,执行cal_order函数中s控制的if语句 */ /* 去掉括号,再原括号中的字符作为参数传给cal_order函数,同时分割字符串,且在convert中也用到*q=='\0'作结束标志*/ *p='\0'; *q='\0'; strcat(a,p+1); /* 将括号中要运算的数拷贝到a中,再作为参数传给cal_order函数进行运算*/ cal_order(a); /* if(kk<10) { *str='\0'; strcat(str,a); return 0; }*/ strcat(b,a); /* 把括号中结果和原括号外的字符链接 */ strcat(b,q+1); if(p!=str) strcat(p-1,b); else strcat(p,b); memset(b,'\0',200); memset(a,'\0',50); p=q=str; /* 从头开始寻找最里层括号 */ continue; } } p++; } p=str; while(*p!='\0') { if(*p=='('||*p==')') /* 看是否还有未匹配的括号,有的话表示输入语法错误 */ { printf("\nthe bracket mismatch\n"); exit(1); } p++; } return 0; } /* 系统函数匹配,检查是否调用系统库函数 及运算最后结果 */ void calc(char *str) { char a[10],b[100],*p,*q,*r; static char *index[]={"sin","cos","tan","sqrt","asin","acos","atan","lg","ln","exp","fabs","ceil","cosh","floor",NULL}; int i,j,k,l; i=j=k=l=0; kk=99; p=str; memset(a,'\0',10); memset(b,'\0',100); while(*p!='\0') { if(*p>96&&*p<123) /* 字母进 */ { q=p; while(*q!='('&&i<10) /* 将可能的函数名存入a*/ { a[i++]=*q; q++; } if(*q=='(') /* 函数名后存在(的话,说明可能是函数,进,否则输入表达式错误 */ { r=q; while((*(r-1)!=')'||k!=0||q==r)&&*r!='\0') /* 将可能函数括号中的表达式存入b */ { if(*r=='(') k++; if(*r==')') k--; b[j++]=*r; r++; } if(*(r-1)!=')') /* 如果最后没函数没有右括号结尾,说明函数括号不匹配 */ { printf("\nthe bracket mismatch\n"); exit(1); } b[j]='\0'; for(kk=0;index[kk]!=NULL;kk++) /* 匹配函数 */ { if(!strcmp(index[kk],a)) { bracket_match(b); /* 计算出所有函数的运算结果后重新组成运算表达式字符串 */ *p='\0'; *(r-1)='\0'; l=strlen(b); strcat(b,r); strcat(p,b); break; } } if(kk==N) /* 输入函数不存在 */ { printf("\nerror,input again please!\n"); exit(1); } p=p+l-1; i=j=0; kk=99; memset(a,'\0',10); memset(b,'\0',100); } else /* 输入了无用字符 */ { printf("\nerror,input again please!\n"); exit(1); } } p++; } bracket_match(str); /* 计算所有函数计算后的表达式 */ *(str-1)='\0'; cal_order(str); /* 去掉所有括号后进行最后一步运算 */ } void main() { char str[200]; memset(str,'\0',200); printf("\n计算函数表达式的值:\n\n支持(),+,-,*,/,^\n\nsin,cos,tan,asin,acos,atan,cosh,sqrt,exp,lg,ln,fabs,ceil,floor\n\n请输入函数表达式:"); gets(str); calc(str); printf("%s\n",str); getch(); }
如何精确到小数点后两位