栈实现表达式求值
通过前两天的博客园,可以知道我最近在疯狂补作业,这是我在数据结构实验课遇到的一个题,我通过搜寻相关知识点,理清了后缀表达式的转化过程
题目要求:
使用键盘输入数学表达式(含数字,四种运算符+、-、、/和小括号,其中运算数都是一位数(0~9)),将数学表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。
输入格式:
输入正确的表达式(可以有空格)后回车,得到后缀表达式和结果。输入括号缺失的表达式,输出"ERROR:缺少括号"。输入两个除括号外运算符连续的表达式,输出"ERROR:表达式缺操作数"。
输出格式:
请在这里描述输出格式。例如:对每一组输入,在一行中输出A+B的值。
输入样例:
在这里给出一组输入。例如:
5*(8-(3+2))
输出样例:
在这里给出相应的输出。例如:
5832+-
15
源码如下
#include<iostream> #include<cstdio> #include<string> using namespace std; const int N = 100010; string change(string s) { string ss; for (int i = 0; i < s.size(); i++) { if (s[i] == 32) continue;//空格继续输入 ss += char(s[i]);//强制转换为字符类型 } return ss; } bool ck1(string s) //判断字符串是否缺少对应的括号 { int cnt = 0; for (int i = 0; i < s.size(); i++) { if (s[i] == '(') cnt++; else if (s[i] == ')') cnt--; } return cnt == 0; } bool ck2(string s) //判断字符串是否符合运算规律 { for (int i = 0; i < s.size(); i++) { if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') { if (i == 0 || i == s.size() - 1 || i && (s[i - 1] == '+' || s[i - 1] == '-' || s[i - 1] == '*' || s[i - 1] == '/')) { return 0; } } } return 1; } int cx(char ch) { return ch == '*' || ch == '/' ? 2 : 1; } char ch[N]; int cnt; string cg(string s) { string ss; for (int i = 0; i < s.size(); i++) { if (s[i] >= '0' && s[i] <= '9') { ss += char(s[i]); } else { if (s[i] == '(') { ch[cnt++] = '('; } else if (s[i] == ')') { while (ch[cnt - 1] != '(') { ss += ch[--cnt]; } cnt--; } else { char c = char(s[i]); if (cnt > 0 && cx(c) <= cx(ch[cnt - 1])) { while (cnt > 0 && ch[cnt - 1] != '(' && cx(c) <= cx(ch[cnt - 1])) { ss += ch[--cnt]; } } ch[cnt++] = c; } } } while (cnt > 0) { ss += ch[--cnt]; } return ss; } int op(int x, int y, char ch) { if (ch == '+') return x + y; else if (ch == '-') return x - y; else if (ch == '*') return x * y; else return x / y; } int a[N], ct=0; int op(string s) { for (int i = 0; i < s.size(); i++) { if (s[i] >= '0' && s[i] <= '9') { a[ct++] = s[i] - 48; } else { int x = a[ct - 2], y = a[ct - 1]; ct -= 2; a[ct++] = op(x, y, char(s[i])); } } return a[0]; } int main() { string s; getline(cin, s); s = change(s); if (!ck1(s)) { cout << "ERROR:缺少括号"; return 0; } if (!ck2(s)) { cout << "ERROR:表达式缺操作数"; return 0; } string ss = cg(s); cout << ss << endl; cout << op(ss); return 0; }
实验体会
在实验过程中,我先观看了老师的讲解视频,在视频中我有了一个大概的思路,在进行编写的时候,我对于如何转变为中缀式和后缀式有些疑问,对于符号和位置的表达不够清晰,后来我在网上查找了一些资料,了解到了中缀式和后缀式的转化,最终成功实现了本次实验。经过本次实验,关于表达式求值,用栈的方式,首先判断输入的数字和符号,以此判断优先级,在整个运算过程中括号的优先级最高,依次是乘除和加减,通过函数cg,将数字单独安顺序输入数组是s[i],括号运算符输入数组ch[],并且记录下运算符的位置,然后专门计算括号内的算术式,设置函数op计算四个运算符,设置函数判断输入括号缺失的表达式,输出"ERROR:缺少括号"。输入两个除括号外运算符连续的表达式,输出"ERROR:表达式缺操作数"。在本次实验中,我进行了栈的练习,学习了如何利用栈进行对于带括号的运算式的计算,如何将运算式变成中缀式,再从中缀式变成后缀式,对于栈有了更深的了解,但还是对知识点的掌握有很大的不足,需要继续练习和复习栈知识。