要求0:
作业地址:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2266
要求1:
git仓库地址:https://git.coding.net/wangc556/f4.git
要求2:
结对同学博客地址:https://www.cnblogs.com/wangcwcgnaw/p/9926468.html
结对同学名字:王储 2016011925
解题思路:
根据王储同学的提示,四则运算求值一定要用到逆波兰表达式,所以我百度搜了一下逆波兰表达式的作用和用法。
将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
(5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
之后的每个功能在使用逆波兰表达式的基础上又做了一些细节的改动。
每个功能重、难点:
功能一:实现运算数为整数的不含小括号的四则运算,运算符具有优先级,对优先级进行规定。
功能二:在功能一的基础上支持了小括号,括号参与运算后是考虑括号的匹配和生成顺序,定义temp为未匹配的左括号数来解决括号匹配问题。同时考虑运算数据为浮点型,判断结果为无限小数还是有限小数很困难。
功能三:生成的四则运算表达式是不重复的并且工整输出。因为表达式重复的情况太多所以我认为这是一大难点,也是我们不太知道如何解决的。
1.进行题目数、功能、文件路径等变量定义
int main(int argc,char* argv[]){ string ss;//题目数的字符串 int qwq=0;//功能 string path;//输出的文件路径 for(int i=1;i<argc;++i){ string str=argv[i]; if(str=="-n"||str=="-c"){ ss=argv[i+1]; if(str=="-n") qwq=1; else qwq=2; } if(str=="-f") qwq=3,path=argv[i+1]; } int num=0,l,cnt=0;//num问题数,cnt回答正确数 //把问题数字符串转化为整数 l=ss.size(); for(int i=0;i<l;++i){ num*=10; num+=ss[i]-'0'; } //每次生成的随机数都不同 srand((int)time(0));
2.生成运算式,使用rand()函数,功能一随机生成1-10的整数,功能二、三生成0.01-10.00的浮点数
string s="";//生成的运算式的字符串 int temp=0;//未匹配的左括号数 //生成运算式 if(qwq==1){ for(int i=1;i<=4;++i){ if(i==1){ int r1=rand2(1,10); //整数转字符串 stringstream ssss; ssss<<r1; string t; ssss>>t; s+=t; } else{ int r1=rand2(1,5); if(r1==1) s+="+"; if(r1==2) s+="-"; if(r1==3) s+="*"; if(r1==4) s+="/"; int r2=rand2(1,10); stringstream ssss; ssss<<r2; string t; ssss>>t; s+=t; } } }
定义temp为当前位置未被匹配的左括号数量,在之后的位置以temp为上界,将未匹配的的括号进行匹配,保证括号合法。
else{ for(int i=1;i<=5;++i){ if(i==1){ int r1=rand2(0,2); for(int i=0;i<r1;++i) s+="("; temp+=r1;//temp:未匹配的左括号数 double r2=rand1(1,1000); stringstream ssss; ssss<<r2; string t; ssss>>t; s+=t; } else if(i==5){ for(int i=0;i<temp;++i) s+=")"; temp=0; } else{ int r1; //生成右括号 if(temp){ r1=rand2(0,temp); for(int i=0;i<r1;++i) s+=")"; temp-=r1; } int r2=rand2(1,5); if(r2==1) s+="+"; if(r2==2) s+="-"; if(r2==3) s+="*"; if(r2==4) s+="/"; //生成左括号 r1=rand2(0,2); for(int i=0;i<r1;++i) s+="("; temp+=r1; double r3=rand1(1,1000); stringstream ssss; ssss<<r3; string t; ssss>>t; s+=t; } } }
3.定义两个栈运算符栈和数字栈 应用逆波兰表达式
stack<double>sv; stack<char>sp; char c; int k=0,flag=1; double x,y; sp.push('