计算机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();
}
如何精确到小数点后两位








失望····
