中缀表达式目前只大概会了 0-9的处理,实数处理目前还不会,这几天在请教下别人之后再补上。
1.九度OJ题目1019:简单计算器 (不带括号,实数)
2.带括号 0-9
只要问题还是中缀表式式和后缀表达式的转换以及后缀表达式的计算
主要思路
先看带括号 0-9
这里括号只有(),且输入合法
1.中缀转后缀
中缀表达式为:1+(2-3)*4+4/2
对应后缀表达式为:1 2 3 - 4* + 4 2 / +
怎么转换呢,首先要用到数据结构中的栈,栈的特性先进后出保存操作符,还要规定运算符的优先级,
从左到右遍历中序表达式,
1)遇到数字,直接添加到后续表达式后面
2)遇到±*/
如果栈为空,直接入栈,如果非空,需要判断当前读到的操作符与栈顶的操作符的优先级,如果栈顶的优先级比当前的大,就添加到后缀,然后pop(),在判断栈顶,如果不满足上述判断或者栈为空,将这个运算符入栈。要注意的是,经过上述步骤,这个运算符最终一定会入栈。
3)遇到()
遇到(直接读入栈,遇到),则不入栈,要把直到( 里的操作符都读入到后缀表达式里面,然后弹出(。
4)遍历完之后,如果站里面非空,把里面的操作符全部读入到后缀表达式里面,
注意:栈 每次弹出是,需要先判断是否为空。
2.计算后缀表达式
这几就比较简单,遍历后缀表达式
如果为数字读入到栈,如果为操作符弹出2个数字,操作完后在入栈,遍历完后栈中只剩下一个数字就是结果,
总结
1.先中缀转后缀
2.计算后缀
首先你要知道,中缀,后缀的含义,还要会转换,其次知道是什么在用代码模拟目前还是不简单,虽然数据结构讲了,但是用代码写还是不熟练。
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int priority(char ch){ //优先级
if (ch == '(') return 1;
else if (ch == '+' || ch == '-') return 2;
else if (ch == '*' || ch == '/') return 3;
else return 4;
}
string midpresent(string str){ //转后缀
stack<char> s;
int len=str.length(),i=0;
char temp;
string res="";
for(int i=0;i<len;i++){
if(str[i] == ' ') continue;
if(str[i] >='0' && str[i] <='9') res.push_back(str[i]);
else if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/'){
if(s.empty()) s.push(str[i]);
else {
while(!s.empty()){
temp = s.top();
if(priority(temp) >= priority(str[i])){
res.push_back(temp);
s.pop();
}
else break;
}
s.push(str[i]);
}
}
else {
if(str[i] == '(') s.push(str[i]);
else{
while(s.top() != '('){
res.push_back(s.top());
s.pop();
}
s.pop();
}
}
}
while(!s.empty()){
res.push_back(s.top());
s.pop();
}
return res;
}
double cal(string str){ //计算后缀
int len=str.length();
stack<double> s;
double num1,num2;
for(int i=0;i<len;i++){
if(str[i] >='0' && str[i] <='9'){
s.push(str[i] - '0');
}
else{
num2=s.top();
s.pop();
num1=s.top();
s.pop();
if(str[i] == '+'){
s.push(num1+num2);
}
else if(str[i] == '-'){
s.push(num1-num2);
}
if(str[i] == '*'){
s.push(num1*num2);
}
if(str[i] == '/'){
s.push(num1/num2);
}
}
}
return s.top();
}
int main() {
string str;
getline(cin,str);
cout << endl << str << endl;
string res = midpresent(str);
cout << endl << res << endl;
double num_res = cal(res);
printf("%.2lf",num_res);
return 0;
}
题目描述:
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入:
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出:
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
样例输入:
1 + 2
4 + 2 * 5 - 7 / 11
0
样例输出:
3.00
这题不像上面那么麻烦,主要是读取格式,因为有空格,这里和sscanf类似,但是我掌握的不怎么样
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX_N 1005
using namespace std;
const int INF = 0xffff;
int main() {
double n, temp;
char b, c[2];
while (scanf("%lf%c", &n, &b)) {
if (n == 0 && b == '\n') break;
double ans = 0;
stack<double> stk;
stk.push(n);
while (scanf("%s %lf", c, &n) != EOF) {
if (c[0] == '+') stk.push(n);
else if (c[0] == '-') stk.push(-n);
else if (c[0] == '*') {
temp = n*stk.top();
stk.pop();
stk.push(temp);
}
else {
temp = stk.top()/n;
stk.pop();
stk.push(temp);
}
if (b = getchar() , b == '\n') break;
}
while (!stk.empty()) {
ans += stk.top();
stk.pop();
}
printf("%.2lf\n", ans);
}
return 0;
}
这种解法和巧妙,他是便输入便判断计算,不像后缀表达式,先求出来整个式子在计算,目前还不知道有括号的怎么搞
参考思路
参考概念
参考做法1
参考做法2
参考做法3