使用C++实现,使用系统自带stac
- 支持括号处理
- 支持小数计算
- 支持表达式有效性检查
- 支持多轮输入。
运行结果示例:
代码:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
//判断是否是数字字符
int isNumber(char c)
{
if(c>='0' && c<='9')
return 1;
else
return 0;
}
//判断字符是否是操作符,这里仅支持+、-、*、/
int isOperator(char c)
{
if(c=='+' || c=='-' || c=='*' || c=='/')
return 1;
else
return 0;
}
//获取操作符的优先级
int priority(char op)
{
if(op=='+' || op=='-')
return 1;
else if(op=='*' || op=='/')
return 2;
else if(op=='(')
return 0;
return 0;
}
//有效性判断1:判断是否缺操作符,缺操作符返回1,否则返回0
int isLessOperator(char* p)
{
int i = 0,j,k;
//考虑一下几种情况:
//1.数字之间没有操作符,例如 2 3 + 4
//2.(前面是数字,例如 2(2+3),这里不支持省略乘号
//3.)后面是数字,例如 (2+3)3,这里不支持省略乘号
while(p[i]!='\0')
{
if(p[i]==' ')
{
j = i-1;
while(j>=0 && p[j]==' ') j--; //往前遍历,直到遇到非空格
k = i+1;
while(p[k]==' ') k++;//往后遍历,直到遇到非空格
if(j>=0 && isNumber(p[j]) && isNumber(p[k])) //空格前后都是数字
return 1; //说明缺少操作符,返回1
}
else if(p[i]=='(')
{
j = i-1;
while(j>=0)
{
if(isOperator(p[j]) || p[j]=='(')
break;
else if(p[j]==' ')//跳过空格
{
j--;
continue;
}
else if(isNumber(p[j]))
return 1;
else if(p[j]==')')//出现 )(这种情况,((这种情况在这里不讨论,会在括号匹配函数中处理
return 1;
else
return 2; //这里可能出现非数字、非操作符、非括号
}
}else if(p[i]==')')
{
j = i+1;
while(p[j]!='\0')
{
if(isNumber(p[j]))
return 1;
else if(isOperator(p[j]))
break;
else if(p[j]==' ')
{
j++;
continue;
}
else if(p[j]==')')
break;
else if(p[j]=='(')
return 1;
else
return 2; //出现非数字、非操作符、非括号
}
}
i++;
}
return 0;
}
//有效性判断2:判断括号是否匹配,匹配返回1,否则返回0
int isComplete(char* p)
{
int i=0;
int nmb = 0; //(的个数
while(p[i]!='\0')
{
if(p[i]=='(')
nmb++;
else if(p[i]==')')
nmb--;
if(nmb<0)
return 0;
i++;
}
if(nmb != 0)
return 0;
return 1;
}
//有效性判断3:是否是连续操作符(负数操作时必须用括号括起来),出现连续操作符返回1,否则返回0
int isMoreOperator(char* p)
{
int i=0,j;
while(p[i]!='\0')
{
if(isOperator(p[i]))
{
j=i-1; //向前判断
while(j>=0)
{
if(p[j]==' ')
{
j++;
continue;
}else if(isOperator(p[j]))
return 1;
else if(isNumber(p[j]))
break;
else if(p[j]==')'||p[j]=='(') //是括号
break;
else
return 2; //非数字、非空格、非括号、非操作符外的其他符号
}
}
i++;
}
return 0; //
}
//有效性判断4:判断是否是空括号,如2+()+3
int isEmptyKh(char* p)
{
int i=0,j;
while(p[i]!='\0')
{
if(p[i]==')')
{
j= i-1;
while(j>=0)
{
if(p[j]=='(')
return 1;
else if(p[j]==' ')
j--;
else
break;
}
}
i++;
}
return 0;
}
//判断表达式的有效性
int isValid(char* p)
{
int res = 1,t;
int len = strlen(p);
if(p[len-1]=='=' || p[len-1]=='#') //以=或者#结尾
p[len-1]=0;
t = isLessOperator(p);
if(t == 1)
{
printf("缺少操作符!\n");
res = 0;
}else if(t == 2)
{
printf("出现符数字、空格、操作符、括号之外的符号\n");
res = 0;
}
t = isComplete(p);
if(t==0)
{
printf("括号不匹配\n");
res = 0;
}
t = isMoreOperator(p);
if(t == 1)
{
printf("有多个连续运算符\n");
res = 0;
}else if(t==2)
{
printf("出现符数字、空格、操作符、括号之外的符号\n");
res = 0;
}
t = isEmptyKh(p);
if(t==1)
{
printf("有空括号\n");
res = 0;
}
return res;
}
//执行某个运算
int getResult(double a,double b,char c,double *v)
{
if(c=='+')
{
*v = a+b;
return 1;
}else if(c=='-')
{
*v = a-b;
return 1;
}else if(c=='*')
{
*v = a*b;
return 1;
}else if(c=='/')
{
if(b==0)
return 0;
*v = a/b;
return 1;
}
return 0;
}
//计算
int Caculate(char* p,double *res)
{
stack<double> data; //数据
stack<char> oper; //操作符
int i=0;
double a,b,c;
char op1,op2;
double mi=1;
while(p[i]!='\0')
{
if(isNumber(p[i])) //当前字符是数字,则读取后续的数字,并入栈
{
a = p[i]-'0';
i++;
//继续读取后面的数字
while(isNumber(p[i]))
{
a = a*10+(p[i]-'0');
i++;
}
if(p[i]=='.')
{
i++;
//处理小数部分
mi = 10;
while(isNumber(p[i]))
{
a = a + (p[i]-'0')/mi;
mi*=10;
i++;
}
}
data.push(a);//数据入栈
}else if(isOperator(p[i])) //是运算符
{
if(oper.empty())
{
oper.push(p[i]);
i++;
}else
{
op1 = oper.top(); //获取栈顶运算符
//比较op1和p[i]的优先级,如果op1的优先级高于p[i],则数据出栈并进行计算
if(priority(op1) >= priority(p[i]))
{
b = data.top(); //后操作数
data.pop();
a = data.top(); //前操作数
data.pop();
oper.pop(); //运算符出栈
if(getResult(a,b,op1,&c))
{
if(!oper.empty())
{
op2 = oper.top();
if(op2=='-' && c<0)
{
oper.pop();
oper.push('+');
data.push(-c); //减负数等价于加正数
oper.push(p[i]);
}else
{
data.push(c); //新数据入栈
oper.push(p[i]); //操作符入栈
}
}else
{
data.push(c); //新数据入栈
oper.push(p[i]); //操作符入栈
}
i++;
}else
{
printf("除数为0\n");
return 0;
}
}else
{
oper.push(p[i]); //操作符入栈
i++;
}
}
}else if(p[i]=='(')
{
oper.push(p[i]); //入栈
i++;
}else if(p[i]==')') //出栈计算
{
op1 = oper.top();
if(op1=='(')
{
oper.pop();//(出栈
i++;
}else
{
b = data.top(); //获取栈顶元素,该数为后操作数
data.pop();
a = data.top();
data.pop();
oper.pop(); //运算符出栈
if(getResult(a,b,op1,&c))
{
if(!oper.empty())
{
op2 = oper.top();
if(op2=='-' && c< 0)
{
oper.pop();
oper.push('+');
data.push(-c);
}else
data.push(c);
}else
data.push(c);//新数据入栈
}else
{
printf("除数为0\n");
return 0;
}
}
} else if(p[i]==' ')
i++;
}
//处理栈内数据
while(!oper.empty())
{
b = data.top();
data.pop();
a = data.top();
data.pop();
op1 = oper.top();
oper.pop();
if(getResult(a,b,op1,&c))
{
if(!oper.empty())
{
op2 = oper.top();
if(op2 == '-' && c< 0)
{
oper.pop();
oper.push('+');
data.push(-c);
}else
data.push(c);
}else
data.push(c);
}else
{
printf("除数为0\n");
return 0;
}
}
if(data.size() !=1 )
{
printf("error\n");
return 0;
}
*res = data.top();
data.pop();
return 1;
}
int main()
{
char buf[100]={0};
int op;
while(1)
{
printf("输入表达式:\n");
cin.getline(buf,100); //读取一行
double res = 0;
if(isValid(buf))
{
if(Caculate(buf,&res))
printf("%g\n",res);
}
printf("是否继续(1:继续 2:退出):");
scanf("%d",&op);
if(op == 2)
break;
getchar(); //吸收回车符
}
return 0;
}