核心是将中缀表达式转化为后缀表达式并进行求值。
此程序主要实现非负整数和浮点数的四则运算。
是这一篇的加强。
http://t.csdnimg.cn/N485Mhttp://t.csdnimg.cn/N485M区别在于:
前面这篇为了避免有错误的表达式,进行了括号匹配检查。
此篇默认输入的表达式括号无问题不进行检查,在上面那篇的基础上增加了浮点数的读入。从文件中读入表达式。
示例输入:
默认无空格无换行
(12.34*(3+1)/4)+8+6*9/3
#include<bits/stdc++.h>
using namespace std;
double calc(string org){
stack<char> op;//存放操作符的栈
int index=0;
char postfix[100];//用来存放后缀表达式,数字用'!'占位,从nums数组中取
double num[100];
double temp=0;//用来记录有多位的未拼完的数
double tp=0.0;//计算小数点后的部分
int flag=0;//用来标记当前是否在拼写数字
for(int i=0;i<org.length();i++){//将中缀表达式转换为后缀表达式
char c=org[i];//当前读入字符
if(isdigit(c)){//当前读入是数字,不知道有几位,进入拼写状态
if(flag>=2){//小数点后的计算
int n=flag-1;
tp=c-'0';
while(n--){
tp*=0.1;
}
temp+=tp;
flag++;
tp=0;
continue;
}
temp*=10;
temp+=c-'0';
flag=1;
}else if(c=='.'){
flag=2;
}
else{//如果不是数字
if(flag>0){//说明前面有数字且已经拼完
postfix[index]='!';//用'!'给数字占位,从num数组中取
num[index]=temp;//存入计算好的数
index++;//索引自增
temp=0;//工具状态初始化
flag=0;
}
if(c=='#'){//读到末尾了
while(!op.empty()){//全部出栈
postfix[index++]=op.top();
op.pop();
}
break;
}
else{//读到了括号或者运算符
if(c=='('){//读到左括号 ,直接入栈
op.push(c);
}
else if(c==')'){//读到右括号,出栈至左括号
while(!op.empty() && op.top()!='('){
postfix[index++]=op.top();
op.pop();
}
if(!op.empty()) op.pop();//弹出左括号
else return -1;//括号匹配错误,输入的表达式不正确
}
else if(c=='*' || c=='/'){//弹出站内乘除,新乘除入栈(同级符号优先级左大于右)
while(!op.empty()&&(op.top()=='*' || op.top()=='/')){
postfix[index++]=op.top();
op.pop();
}
op.push(c);
}
else{//那么最后就是加减了,出栈到空或左括号再入栈
while(!op.empty() && op.top()!='('){
postfix[index++]=op.top();
op.pop();
}
op.push(c);
}
}
}
}
//可以输出后缀表达式,测试用
/*
for(int i=0;i<index;i++){
if(postfix[i]=='!'){
cout<<num[i];
}
else cout<<postfix[i];
}
*/
//计算后缀表达式的值
stack<double> number;
for(int i=0;i<index;i++){
char po=postfix[i];
if(po=='!'){//如果是数字,进入数字栈
number.push(num[i]);
}
else{//如果是运算符,弹出两个数字进行计算并重新压回数字栈内
double temp1=number.top();
number.pop();
if(number.empty()) return -1;
double temp2=number.top();
number.pop();
if(po=='+'){
number.push(temp2+temp1);
}
else if(po=='-'){
number.push(temp2-temp1);
}
else if(po=='*'){
number.push(temp2*temp1);
}
else if(po=='/'){
number.push(temp2/temp1);
}
}
}
return number.top();
}
int main(){
FILE *fp;
fp=fopen("ari.txt","r");
string org;
if(fp!=NULL){//从文件中读入中缀算术表达式
//cout<<"打开成功"<<endl;
while(!feof(fp)){
org+=fgetc(fp);
}
//cout<<org<<endl;
org[org.length()-1]='#';//末尾会多读入一个'?',直接改为结束符
}
cout<<calc(org)<<endl;
return 0;
}
可以打开其中的测试代码输出后缀表达式:
12.3431+*4/8+69*3/+
最后结果:
38.34