第四次作业 计算器第二步
2016-04-07 15:09
337 查看
题目链接:
http://www.cnblogs.com/fzuoop/p/5326667.htmlgithub链接:
https://github.com/MeKChen2/object-oriented/tree/master/Calculator-fourth%20homework1.解题思路:
这次拿到的题目要求在第三次作业上进行修改,在看过学长在第三次作业上的评论后,我重新审了一次第三次的题目,发现我把题目理解错了。在将第三次作业的代码改成五个文件的时候,出现了很多问题,无论用什么编译器都无法正常将代码分成五个文件。
所以,在进一步学习了栈的知识和浏览了许多博客后,我打算完全放弃第三次的代码来写第四次的作业。
表达式的计算思路:
1)准备两个栈:数据栈和运算符栈;反复读取表达式 。
2)如果是数,入数据栈;
3)如果是左括号,入运算符栈,如果是右括号,反复从运算符栈顶取运算符和从数据栈里取两个数据进行计算,并把结果入数据栈,直到遇到栈顶是左括号为止。
4)如果是运算符op,先跟栈顶的运算符比,只要不高于栈顶优先级,就取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到高于栈顶运算符优 先级或者遇到左括号或者运算符栈空为止,此时把op入栈;
5)处理栈中的运算符:取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到运算符栈空为止;
6)这时数据栈中的数据就是计算结果。
代码如下:
#include <iostream> #include <stack> #include <string> #include <cstring> using namespace std; class Calculation { private: stack<char> oper; stack<double> shu; double v,a,b; char op; //运算符 public: double calinput() //读取并计算表达式直到结束为止 { do { readdata(); } while(readop()); calsurplus(); //处理栈中剩余的运算符 cout << v << endl; return 0; } void readdata() //读取数据 { while(!(cin>>v)) //判断读取数据是否正常 { cin.clear(); cin >> op; oper.push(op); } shu.push(v); return; } bool readop() //读取运算符 { while((op = cin.get()) == ')') { while( oper.top() != '(' ) { b = shu.top(); shu.pop(); a = shu.top(); shu.pop(); shu.push(cal(a, oper.top(), b)); //计算并入栈 oper.pop(); //取走运算符 } oper.pop(); } if(op == '\n') { return false; } while(!oper.empty() && oper.top() != '(' && !com( op, oper.top())) { b = shu.top(); shu.pop(); a = shu.top(); shu.pop(); shu.push(cal( a, oper.top(), b )); //计算并入栈 oper.pop(); //取走运算符 } oper.push(op); return true; } void calsurplus() { while(!oper.empty()) { b = shu.top(); shu.pop(); a = shu.top(); shu.pop(); shu.push(cal( a, oper.top(), b )); //计算并入栈 oper.pop(); //取走运算符 } v = shu.top(); shu.pop(); return; } double cal(double a, char op, double b) { if(op=='+') return a+b; else if(op=='-') return a-b; else if(op=='*') return a*b; else if(op=='/') return a/b; } bool com(char c, char d) //若c比d优先级高返回true,否则返回false { if(c != '+' && c != '-' && d != '*' && d != '/') return true; else return false; } }; int main() { Calculation e; e.calinput(); system("pause"); return 0; }
运行结果:
存在的问题:
这部分代码无法满足题目要求,即当输入-a时要输出表达式,本想写完主要代码再进行-a那步骤的修改,想了很久没有想出方法。而且我定义的两个栈,一个是char,一个是double,所以没有用到sstream来将字符转换成数字。
改进:
剩下的三天时间,打算用其他方法再进行尝试,改进代码。反思:
此次代码虽然没有通过第三次代码基础修改得到,但是这次我查阅学习了资料,自我感觉代码比之前第三次的要好了很多,第三次的代码用这次的方法也能更容易写出,现在来看第三次作业反而觉得很简单。以后的学习中应该先掌握好足够的知识,再进行做题,更有效果参考资料:
http://www.nowamagic.net/librarys/veda/detail/2306http://blog.csdn.net/anye3000/article/details/7941231
http://blog.sina.com.cn/s/blog_786ce14d01014ixq.html
4.10更新版本二:
#include <iostream> #include <stack> #include <string> using namespace std; const int SIZE = 100; bool isOperator( char op ) { switch(op) { case '+': case '-': case '*': case '/': return true; default: return false; } } int check( char op ) { int value = -1; switch(op) { case '(': value = 0; break; case '+': case '-': value = 1; break; case '*': case '/': value = 2; break; } return value; } int change( string str, char a[SIZE], int &len ,int &sum ) { // 中缀式转换为后缀式 stack<char> oper; oper.push('\0'); int i = 0; int j = 0; while( str[i] != '\0' ) { if( str[i] >= '0' && str[i] <= '9' || str[i] == '.' ) { a[j++] = str[i]; len++; } else if( str[i] == '(' ) { oper.push(str[i]); } else if( str[i] == ')' ) { while( oper.top() != '(' ) { a[j++] = oper.top(); oper.pop(); len++; } oper.pop(); } else if( i == 0 && (str[i] == '+' || str[i] == '-') && str[i+1] != 'a') //表明第一个数为正负号 { a[j++] = str[i]; len++; } else if( i == 2 && (str[i] == '+' || str[i] == '-') && str[i-1] == 'a') //表明当出现"-a"时第三个数为正负号 { a[j++] = str[i]; len++; } else if( i == 0 && str[i] == '-' && str[i+1] == 'a' /*&& str[i+2] == ' '*/ ) { sum = 1; } else if( isOperator(str[i]) ) { a[j++] = ' '; //用空格隔开数 len++; while( check(str[i]) <= check( oper.top() ) ) { a[j++] = oper.top(); oper.pop(); len++; } oper.push(str[i]); } i++; } while( oper.top() != '\0' ) { a[j++] = oper.top(); oper.pop(); len++; } return 0; } double read(char str[],int *i) { double x=0.0; int k = 0; while(str[*i] >='0' && str[*i]<='9') // 处理整数部分 { x = x*10+(str[*i]-'0'); (*i)++; } if(str[*i]=='.') // 处理小数部分 { (*i)++; while(str[*i] >= '0'&&str[*i] <='9') { x = x * 10 + (str[*i]-'0'); (*i)++; k++; } } while(k!=0) { x /= 10.0; k--; } return x; } double calculate( char post[SIZE] ) { // 计算后缀表达式结果 stack<double> stack; // 操作数栈 double x1 = 0; double x2 = 0; bool flag = false; int i = 0; double d = 0; while( post[i] != '\0' ) { if( post[i] >= '0' && post[i] <= '9' ) { d = read(post,&i); if(flag) // 第一个数为负数 { d = -d; flag = false; } stack.push(d); } else if(post[i] == ' ' ) i++; else if (post[i] =='+') { x2 = stack.top(); stack.pop(); x1 = stack.top(); stack.pop(); stack.push(x1+x2); i++; } else if( post[i] == '-' && i == 0 ) //表明第一个数为负数,方便计算-1+2*3 { flag = true; i++; } else if (post[i] =='-') { x2 = stack.top(); stack.pop(); x1 = stack.top(); stack.pop(); stack.push(x1-x2); i++; } else if (post[i] =='*') { x2 = stack.top(); stack.pop(); x1 = stack.top(); stack.pop(); stack.push(x1*x2); i++; } else if (post[i] =='/') { x2 = stack.top(); stack.pop(); x1 = stack.top(); stack.pop(); stack.push(x1/x2); i++; } } return stack.top(); } int main() { string str = ""; string str1 = ""; int i = 0; int chang = 0; char a[SIZE]; cin >> str; chang = str.size(); int len = 0; int sum = 0; change( str, a, len ,sum); a[len] = '\0'; if(sum == 1) { str1 = str.substr(2,chang-2); cout << str1 << "= " << calculate(a) << endl; } else cout << calculate(a) << endl; system("pause"); return 0; }
运行结果:
反思:
换了一种方案后能够实现输入“-a”时输出表达式,通过把中缀表达式转换成后缀表达式进行计算。但代码仍有很多细节不符合题目要求,需要进一步修改。相关文章推荐
- Windows下搭建基于SSH的Git服务器
- c# 嵌入的资源
- Linux学习笔记(一)
- 更改状态栏字体颜色
- 8086汇编指令全集
- zz :Android测试之Monkey
- 存储过程建表时出现了权限不足的问题
- 在ipython notebook 上测试 ImportError: No module named _caffe
- py-faster-rcnn配置运行demo.py(Ubuntu14.04),不成功的朋友请与我(lee)联系,后面附带邮箱
- 动态输入框
- JQuery筛选器全系列介绍
- 什么是 IntentService
- PostgreSQL中美元符号引用的字符串常量
- 硬件基础---拆装机
- 最简单的拓扑排序
- Impossible to load an image in xcassets on bundle
- CentOS 6 安装VMWare tools,以及解决安装后/mnt中有hgfs但没共享文件的方法
- g++参数介绍
- 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理
- tinyos学习笔记12--与网络相关的重要结构体索引