学完栈写了一个计算器小程序,
基本功能如下:
1.支持基本的+ - * / % 运算
2.支持sin、cos、tan、ln、log、乘方(^)、开方(sqrt)、指数(exp) 求值
3.支持括号及括号嵌套
4.支持由以上运算符组和成的长表达式求值
5.支持小数及负数
6.支持多位数运算
7.支持省略最右边的")":例如“2*(1+2/(1+2”可补全")"并正确求值
8.支持省略"*",例如(1+2)(3+4) 、10sin30、sin30cos60可以正确求值
9.满足各种用户的操作习惯:空格在任何位置都可以出现,,出现个数任意,也可以不出现,,如"sin30",,,"sin 30",,"1 + 2 "
10.如果表达式错误不能求值会给出提示而不是退出程序,例如“2-sin*7/+”不能计算会给出提示
11.如果除数为0或者被开方数小于零或者ln,log,tan等的操作数不合理会给出相应错误提示
12.如果结果为整数就用整数表示,,如果有小数就保留6为有效数字
13.支持连续计算,即算完后接着进行下一次计算
14.支持用户输入pi代替3.1415926
15.三角函数用角度不用弧度
16.输入"q或Q"键退出
代码公开,欢迎指正
View Code
/****************************************
*******模拟计算器||表达式求值*********
**********designed by ma6174**********
*************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
typedef struct s
{//操作数栈
float data;
struct s *next;
}NUM;
typedef struct ss
{//运算符栈
char data;
struct ss *next;
}OPRT;
//声明main(),以便在出现错误表达式后调用main()而不退出函数
int main();
//操作数进栈
void Push_Num(NUM *l,float n)
{
// printf("Push_Num %f\n",n);
NUM *p;
p=(NUM *)malloc(sizeof(NUM));
p->data=n;
p->next=l->next;
l->next=p;
}
//运算符进栈
void Push_Oprt(OPRT *l,char n)
{
// printf("Push_Oprt %c\n",n);
OPRT *p;
p=(OPRT *)malloc(sizeof(OPRT));
p->data=n;
p->next=l->next;
l->next=p;
}
//操作数出栈
float Pop_Num(NUM *l)
{
float a;
NUM *p;
/*当栈为空时即运算符个数与数字个数相等
或者运算符个数比数字个数多,
肯定是表达式错误*/
if(l->next==NULL)
{
printf("\n表达式错误!!!\n\n");
int i=300000000;
while(i--);
main();
}
a=l->next->data;
p=l->next;
l->next=p->next;
free(p);
// printf("Pop_Num %f\n",a);
return a;
}
//运算符出栈
void Pop_Oprt(OPRT *l)
{
OPRT *p;
p=l->next;
l->next=p->next;
// printf("Pop_Oprt %c\n",p->data);
free(p);
}
//取得栈顶运算符
char Get_Top_Oprt(OPRT *l)
{
// printf("Get_Top_Oprt %c\n",l->next->data);
return l->next->data;
}
//将运算符转换为对应的优先级
int change(char c)
{
if(c=='(')return 1;
if(c=='+'||c=='-')return 2;
if(c=='*'||c=='/'||c=='%')return 3;
//S=sin,C=cos,T=tan,L=ln,G=log,@=sqrt,E=exp
if(c=='S'||c=='C'||c=='T'||c=='L'||c=='G'||c=='@'||c=='E')return 4;
if(c=='^')return 5;
return 0;
}
//将原串处理,例如sin ->S
int deal(char *a)
{
int i,len=strlen(a),l=0,r=0;
for(i=0;i<len;i++)
{
//删除表达式中的空格
if(a[i]==' ')
{
int j=i+1;
for(;j<len;j++)
a[j-1]=a[j];
a[len-1]='#';
len--;
i--;
}
//sin
if(a[i]=='s'&&a[i+1]=='i'&&a[i+2]=='n')
{//将sin转换为S
a[i]='S';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';//防止最后atof误判
len-=2;
}
//cos
if(a[i]=='c'&&a[i+1]=='o'&&a[i+2]=='s')
{
a[i]='C';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//tan
if(a[i]=='t'&&a[i+1]=='a'&&a[i+2]=='n')
{
a[i]='T';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//ln
if(a[i]=='l'&&a[i+1]=='n')
{
a[i]='L';
int j=i+2;
for(;j<len;j++)
a[j-1]=a[j];
a[len-1]='#';
len-=1;
}
//log
if(a[i]=='l'&&a[i+1]=='o'&&a[i+2]=='g')
{
a[i]='G';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//sqrt
if(a[i]=='s'&&a[i+1]=='q'&&a[i+2]=='r'&&a[i+3]=='t')
{
a[i]='@';
int j=i+4;
for(;j<len;j++)
a[j-3]=a[j];
a[len-1]=a[len-2]=a[len-3]='#';
len-=3;
}
//exp
if(a[i]=='e'&&a[i+1]=='x'&&a[i+2]=='p')
{
a[i]='E';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//在sin30sin30,,,,(1+2)sin30,,,,sin30(1+2),,,,(1+2)(1+2)这样的表达式之间添加 "*"
if(((a[i-1]>='0'&&a[i-1]<='9')||a[i-1]==')')&&
(a[i]=='S'||a[i]=='C'||a[i]=='T'||a[i]=='L'||a[i]=='G'||a[i]=='@'||a[i]=='E'||a[i]=='('))
{
int j=len;
for(;j>i;j--)
a[j]=a[j-1];
a[i]='*';
len++;
}
if(a[i]=='(')l++;
if(a[i]==')')r++;
}
//在表达式右边加 ")"来使括号匹配
if(l-r>0)
{
int n=l-r;
while(n--)
{
a[len]=')';
len++;
}
}
return len;
}
int main()
{
char a[1000];
int n,i,len;
system("cls");//清屏
printf("\t\t\t模拟计算器&&表达式求值\n\n");
printf("\t\t支持 + - * / % ^ sqrt log ln sin cos tan exp ()\n\n");
printf("请输入表达式: ");
while(gets(a)!=NULL)
{
len=deal(a);
// printf("%s\n",a);
int i=0;
//各种错误标志
int zero_tag=0,tan_tag=0,sqrt_tag=0,ln_tag=0,log_tag=0;
NUM *num;
num=(NUM *)malloc(sizeof(NUM));
num->next=NULL;
OPRT *oprt;
oprt=(OPRT *)malloc(sizeof(OPRT));
oprt->next=NULL;
if(len==0)
{
printf("请输入表达式: ");
continue;
}
if(len==1&&(a[i]=='q'||a[i]=='Q'))
exit(0);
Push_Oprt(oprt,'#');//作为栈底运算符
if(a[0]=='-')//第一个字符为‘-’时默认为负号
{
i=0;
while(a[i]=='-')//删除所有多余前导负号
i++;
float s=atof(&a[i]);
if(i%2==1)//奇数个负号
s=-s;
Push_Num(num,s);
i++;
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')
i++;
}
if(a[0]=='+')
{//前面多余的加号(正号)全部忽略
i=0;
while(a[i]=='+')
i++;
}
//开始处理表达式
for(;i<len;i++)
{
if(a[i]>='0'&&a[i]<='9')
{//操作数直接进栈
Push_Num(num,atof(&a[i]));
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')//寻找下一个运算符
i++;
i--;
continue;
}
if(a[i]=='p'&&a[i+1]=='i')
{//pi转换为3.1415926再进栈
Push_Num(num,3.1415926);
i++;
continue;
}
//‘-’前面不是数字时肯定是负号而不是运算符 ,‘-’为负号时单独计算
if(a[i]=='-'&&(a[i-1]>'9'||a[i-1]<'0'))
{
float s=atof(&a[i+1]);
s=-s;
Push_Num(num,s);
i++;
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')
i++;
i--;
continue;
}
// “+”直接忽视
if(a[i]=='+'&&(a[i-1]>'9'||a[i-1]<'0'))
{
i++;
continue;
}
if(change(a[i])>change(Get_Top_Oprt(oprt)))
{//表达式中优先级高的运算符进栈
Push_Oprt(oprt,a[i]);
continue;
}
else{
if(a[i]=='('){// '('直接进栈
Push_Oprt(oprt,'(');
continue;
}
if(a[i]==')'){//无条件出栈
while(Get_Top_Oprt(oprt)!='(')
{
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)//除数为0
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
s=log10(aa);
if(aa<=0)
log_tag=1;
else
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
Pop_Oprt(oprt);
Push_Num(num,s);
}
Pop_Oprt(oprt);
continue;
}
//栈里的优先级高的运算符出栈
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
if(aa<=0)
log_tag=1;
else
s=log10(aa);
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
c=Get_Top_Oprt(oprt);
Push_Num(num,s);
Pop_Oprt(oprt);
Push_Oprt(oprt,a[i]);
}
}
//表达式遍历完毕,栈里的运算符依次出栈
while(Get_Top_Oprt(oprt)!='#')
{
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
if(cos(aa/180*3.1415926)<=0.000001)
tan_tag=1;
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
if(aa<=0)
log_tag=1;
else
s=log10(aa);
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
Pop_Oprt(oprt);
Push_Num(num,s);
}
if(zero_tag)
printf("\n除以0!!!\n\n");
else if(tan_tag)
printf("\ntan的数值不合法!!!!!!\n\n");
else if(ln_tag)
printf("\nln的数值不合法!!!!\n\n");
else if(log_tag)
printf("\nlog的数值不合法!!!!\n\n");
else if(sqrt_tag)
printf("\nsqrt的数值不合法!!!!!\n\n");
else{
float ans=Pop_Num(num);//结果在栈底
if(ans-(int)ans==0)
printf("计算结果: %d\n\n",(int)ans);
else
printf("计算结果: %f\n\n",ans);
}
printf("请输入表达式: "); //继续计算
}
return 0;
}