用C语言实现对算术表达式求值
功能: 输入一个整数算术表达式字符串,分解出数值及运算符,并计算输出结果。
要求: 利用菜单可以循环实现求出加法、减法、乘法、除法算术表达式。
(1) 能够实现连续运算; 比如:123+233+555+666=
(2) 能够实现混合运算; 比如:120-23*5-20/4=
(3) 能够实现带括号的混合运算运算。 比如:12*(234-5)+(23+7)=
(4) 能够实现实数的各类运算。 比如:12.23*(12-3.7)+12.56=
(5) 能够实现多层括号嵌套运算 …(….(..)….(..(…))…)…
具体代码如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char a[10000];
typedef struct
{
char singal;
double number;
}stark;
void menu();
void add(char a[10000]);
void sub(char a[10000]);
void div(char a[10000]);
void mul(char a[10000]);
void mix(char a[10000]);
void bra(char a[10000]);
int main()
{
int num=0;
while(1)//保证计算能多次运算
{
menu();
scanf("%d",&num);
if(num==0)
{
printf("感谢您此次使用,再见。");
break;
}
else if(num==1)
add(a);
else if(num==2)
sub(a);
else if(num==3)
div(a);
else if(num==4)
mul(a);
else if(num==5)
{
printf("请输入算术表达式:");
scanf("%s",a);
mix(a);
}
else if(num==6)
{
printf("请输入算数表达式:");
scanf("%s",a);
bra(a);
}
else
{
printf("输入数字错误,请重新输入\n");
}
}
return 0;
}
void menu()
{
printf("|===============================================|\n");
printf("|==================四则运算操作=================|\n");
printf("|===================1.加法运算==================|\n");
printf("|===================2.减法运算==================|\n");
printf("|===================3.除法运算==================|\n");
printf("|===================4.乘法运算==================|\n");
printf("|=============5.不含括号四则混合运算============|\n");
printf("|===============6.含有括号四则运算==============|\n");
printf("|===请输入对应的数字执行对应的功能(输入0退出)===|\n");
printf("|===========算数表达式请以‘= ’结尾============|\n");
printf("|===============================================|\n");//菜单内容
}
void add(char a[10000])
{
printf("请输入加法表达式:");
scanf("%s",a);
double sum=0,x=0;
int i=0;
int is_dec=0;//判断是否为小数
double temp_dec=0.1;//处理小数位数
while(a[i]!='=')
{
x=0;
while((a[i]>='0'&&a[i]<='9')||(a[i]=='.'))
{
if(a[i]=='.')
{
is_dec=1;
i++;
}
else if(is_dec==0)//处理小数点前的数字
{
x=x*10+a[i]-'0';
i++;
}
else if(is_dec==1)//处理小数点后的数字
{
x+=(a[i]-'0')*temp_dec;
temp_dec*=0.1;
i++;
}
}//剥离出来实数存于x中
sum+=x;
temp_dec=0.1;//还原
is_dec=0;//还原进行下次运算
if(a[i]=='=')
break;//遇到等号退出
else
i++;
}
printf("%s=%.3lf\n",a,sum);
}
void sub(char a[10000])
{
printf("请输入减法表达式:");
scanf("%s",a);
double s=0,x=0;
int i=0;
int flag=1;
int is_dec=0;
double temp_dec=0.1;
while(a[i]!='=')
{
x=0;
while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
{
if(a[i]=='.')
{
is_dec=1;
i++;
}
else if(is_dec==0)
{
x=x*10+a[i]-'0';
i++;
}
else if(is_dec==1)
{
x+=(a[i]-'0')*temp_dec;
temp_dec*=0.1;
i++;
}
}//同上 剥离实数
if(flag==1)//存储第一个数
{
s=x;
flag=0;
}
else
s-=x;
temp_dec=0.1;
is_dec=0;
if(a[i]=='=')
break;
else
i++;
}
printf("%s=%.3lf\n",a,s);
}
void div(char a[10000])
{
printf("请输入除法表达式:");
scanf("%s",a);
double s=0,x=0;
int i=0;
int flag=1;
int is_dec=0;
double temp_dec=0.1;
while(a[i]!='=')
{
x=0;
while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
{
if(a[i]=='.')
{
is_dec=1;
i++;
}
else if(is_dec==0)
{
x=x*10+a[i]-'0';
i++;
}
else if(is_dec==1)
{
x+=(a[i]-'0')*temp_dec;
temp_dec*=0.1;
i++;
}
}
if(flag==1)//同上 存储第一个数
{
s=x;
flag=0;
if(s==0)
{
break;
}
}
else
{
if(x==0)//筛除被除数为0的情况
{
printf("表达式错误,请返回菜单重新输入\n");
return ;
}
else
s/=x;
}
temp_dec=0.1;
is_dec=0;
if(a[i]=='=')
break;
else
i++;
}
printf("%s=%.3lf\n",a,s);
}
void mul(char a[10000])
{
printf("请输入乘法表达式:");
scanf("%s",a);
double s=0,x=0;
int i=0;
int flag=1;
int is_dec=0;
double temp_dec=0.1;
while(a[i]!='=')
{
x=0;
while(a[i]>='0'&&a[i]<='9')
{
if(a[i]=='.')
{
is_dec=1;
i++;
}
else if(is_dec==0)
{
x=x*10+a[i]-'0';
i++;
}
else if(is_dec==1)
{
x+=(a[i]-'0')*temp_dec;
i++;
temp_dec*=0.1;
}
}
if(x==0)//如果存在一个乘数为0,直接退出得0,减少运算量
{
s=0;
break;
}
if(flag==1)//存储第一个数
{
s=x;
flag=0;
}
else
s*=x;
temp_dec=0.1;
is_dec=0;
if(a[i]=='=')
break;
else
i++;
}
printf("%s=%.3lf\n",a,s);
}
void mix(char a[10000])//混合运算
{
/*
本函数算法思想为对于输入进来的表达式先进行乘除运算,将运算后的数值
与没有参与乘除运算的数值记录下来,再进行加减运算,最后得出结论
*/
int i=0;
double s=0,x=0;
double b[1001]={0};//用来存储没有参加乘除混合运算与乘除混合运算后的值
int flag=1,temp=1;//flag负责判断被除数是否为0,还可以判断在乘除混合运算中x是不是第一个数
char second[1000]={0};//用来存储加减号以用来后续运算
int j=1, k=1;
int is_dec=0;
double temp_dec=0.1;
while(a[i]!='=')
{
x=0;
while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
{
if(a[i]=='.')
{
is_dec=1;
i++;
temp++;
}
else if(is_dec==0)
{
x=x*10+a[i]-'0';
i++;
temp++;
}
else if(is_dec==1)
{
x+=(a[i]-'0')*temp_dec;
temp_dec*=0.1;
temp++;
i++;
}//记录实数
}
if(a[i]=='-'||a[i]=='+'||a[i]=='=')
{
if(flag==0)
{
if(a[i-temp-1]=='/')
{
if(x==0)
{
printf("表达式错误,请返回菜单重新输入\n");
return ;
}
else
b[j]=s/x;
}
else if(a[i-temp-1]=='*')
{
b[j]=s*x;
}
j++;
}
else
{
b[j]=x;
j++;
}
second[k]=a[i];
k++;
flag=1;
if(a[i]=='=')
{
break;
}
i++;
}//记录乘除运算后的数值
else if(a[i]=='/'||a[i]=='*')
{
if(flag==1)
{
s=x;
flag=0;
}
else if(flag==0)
{
if(a[i-temp-1]=='/')
{
if(x==0)
{
printf("表达式错误,请返回菜单重新输入\n");
return ;
}
else
{
s/=x;
}
}
if(a[i-temp-1]=='*')
{
s*=x;
}
}
i++;
}//逐步计算乘除运算
temp_dec=0.1;
is_dec=0;
if(a[i]=='=')
break;
temp=0;
}
// for(int v=1;v<=j;v++)
// {
// printf("%.3lf ",b[v]);
// printf("%c ",second[v]);
// }
j=1,s=0,k=1;
flag=1;
while(second[k]!='=')
{
if(flag==1)
{
s=b[j];
j++;
flag=0;
}//第一个数不进行处理
else
{
if(second[k]=='-')
s-=b[j];
else if(second[k]=='+')
s+=b[j];
j++;
k++;
}
// printf("%.3lf ",s);
// printf("%c ",second[k]);
if(second[k]=='=')
break;
}
printf("%s=%.3lf\n",a,s);
}
void bra(char a[10000])
{
/*
此函数用到逆波兰算法,即运用栈的思想将普通的中序表达式转换为逆波兰表达式,
便于对含有括号的表达式进行计算
其主要分为两大步:
一、 将普通的中序表达式转换为逆波兰表达式
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入stark_num栈
(2)若取出的字符是运算符,则将该运算符与stark_s栈栈顶元素比较,如果该运算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入stark_num栈顶。
(4)若取出的字符是“)”,则将距离stark_num栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
二、运用栈的思想再对逆波兰表达式运算得出结果
示例:对于算数式 15+28*(4-2)+(50/(25-5)-40)*8=
先将其转换为逆波兰表达式:15 28 4 2 - * + 50 25 5 - / 40 - 8 * +
再对逆波兰表达式进行运算
*/
stark stark_num[10001]={0};//stark_num栈
stark stark_s[10001]={0};//stark_s栈
int top_num=1,top_s=1;//记录栈顶位置
int is_dec=0;//判断小数
int i=0;
int is_minus=0;//判断负数
double temp_dec=0.1;
double sum,x;
int begin=1;
while(1)//此循环负责将中序表达式转换为逆波兰表达式
{
x=0;
int flag=1;
while((a[i]>='0'&&a[i]<='9')||(a[i]=='.'))
{
if(a[i]=='.')
{
is_dec=1;
i++;
}
else if(is_dec==0)
{
x=x*10+a[i]-'0';
i++;
}
else if(is_dec==1)
{
x+=(a[i]-'0')*temp_dec;
temp_dec*=0.1;
i++;
}
}
if(begin==1)
{
begin=0;
if(a[i]=='-')
{
is_minus=1;
i++;
continue;
}
}
if(is_minus==1)//判断负数部分
{
x=-x;
is_minus=0;
}
if((a[i-1]>='0'&&a[i-1]<='9')||i-1==0)
{
stark_num[top_num].number=x;
stark_num[top_num].singal='#';
top_num++;//记录实数
}
stark_s[top_s].singal=a[i];
if(a[i]!='('&&a[i]!=')'&&a[i]!='=')//记录符号优先级
{
//for循环内负责将符号与stark_s栈顶元素比较,进行运算符的出栈入栈运算
for(;((stark_s[top_s-1].singal=='*'||stark_s[top_s-1].singal=='/')||((stark_s[top_s-1].singal=='+'||stark_s[top_s-1].singal=='-')&&(stark_s[top_s].singal=='-'||stark_s[top_s].singal=='+')))&&stark_s[top_s-1].singal!='('&&top_s>1;top_s--)
{
stark_s[top_s].singal='#';
stark_num[top_num].singal=stark_s[top_s-1].singal;
stark_s[top_s-1].singal='#';
top_num++;
flag=0;
stark_s[top_s-1].singal=a[i];
}
if(flag==0)
{
top_s++;
temp_dec=0.1;
is_dec=0;
i++;
continue;
}
}
else if(a[i]=='(')
{
if(a[i+1]=='-')
{
is_minus=1;
i++;
}//承接上方判断负数部分
temp_dec=0.1;
is_dec=0;
top_s++;
i++;
continue;
}
else if(a[i]==')')//处理括号内符号问题
{
top_s--;
for(;stark_s[top_s].singal!='(';top_s--)
{
stark_num[top_num].singal=stark_s[top_s].singal;
top_num++;
stark_s[top_s].singal='#';
}
stark_s[top_s].singal='#';
top_s--;
}//上方两个if语句用来处理括号内的运算符优先级及记录
temp_dec=0.1;
is_dec=0;
top_s++;
if(a[i]=='=')
{
top_s-=2;
for(;top_s>=1;top_s--)
{
stark_num[top_num].singal=stark_s[top_s].singal;
stark_s[top_s].singal='#';//重置记录运算符
top_num++;
}
break;//遇到=符号直接跳出循环
}
else
i++;//进行下次循环运算
}
stark s[1001]={0};//开辟新空间负责存储每次运算逆波兰式得到的数值
int k=2;
s[1].number=stark_num[1].number;
s[2].number=stark_num[2].number;
for(int j=3;j<top_num;j++)
{
if(stark_num[j].singal!='#')//遇到符号就对数值进行运算
{
if(stark_num[j].singal=='+')
{
s[k-1].number=s[k].number+s[k-1].number;
k--;
}
else if(stark_num[j].singal=='-')
{
s[k-1].number=s[k-1].number-s[k].number;
k--;
}
else if(stark_num[j].singal=='/')
{
if(s[k].number==0)
{
printf("表达式错误,请返回重试\n");
return ;
}
s[k-1].number=s[k-1].number/s[k].number;
k--;
}
else if(stark_num[j].singal=='*')
{
s[k-1].number=s[k].number*s[k-1].number;
k--;
}
}
else//遇到数值即进行存储
{
k++;
s[k].number=stark_num[j].number;
}
}
printf("%s=%.3lf\n",a,s[1].number);//打印结果
}