思路:
①设立运算符和运算数两个栈,,一个用来存储运算符,另一个用来存储运算数。
②在运算符栈中放置一个特殊运算符#,其优先级最低。
③将表达式尾部添加一个特殊运算符$,其优先级次低。
④从左至右依次遍历字符串,若遍历到运算符,则将其与运算符栈的栈顶元素进行比较,若运算符栈的栈顶的优先级小于该运算符,则将该运算符压入运算符栈;若运算符栈的栈顶的优先级大于该运算符,则弹出该栈顶运算符,从运算数栈中依次弹出运算数,完成弹出运算符对应的运算后,再将该结果压入运算数栈。
⑤若遍历到表达式中的运算数,则直接压入运算数栈。
⑥若运算符栈中仅剩两个特殊运算符#和$,则表达式运算结束,此时运算数栈中唯一的数字就是表达式的值。
源代码:
#include<iostream> #include<stack> #include<map> #include<string> using namespace std; //例题5.6 KY129 简单计算器 //考虑到需要计算的数字可能不止一位,就从检测到数字的索引开始,一直到检测不到数字的索引,这之间的就是一整个数字 double getNum(string str, int& index) { double res = 0; while (isdigit(str[index])) { res = res * 10 + str[index] - '0'; index++; } return res; } //对两个数字进行运算 double cal(double x, double y, char op) { if (op == '+') { return x + y; } else if (op == '-') { return x - y; } else if (op == '*') { return x * y; } else if (op == '/') { return x / y; } return 0; } int main() { //存储多个运算符号的优先级 map<char, int> maps = { {'#',0},{'$',1},{'-',2},{'+',2}, {'/',3},{'*',3} }; string s; //因为需要运算的式子可能不止一条,这里用while循环 //因为输入的式子中可能包含多个空格,直接用getline(cin, s)回去整行的字符串,并赋值给s while (getline(cin, s)) { if (s == "0") { //结束条件 break; } stack<char> symbol; // 存储运算符的栈 stack<double> number; // 存储操作数的栈 int index = 0; //对字符串遍历的索引 symbol.push('#'); //把'#'压入符号中,优先级最低 s = s + '$'; //先把'$'放到要处理的公式字符串的末尾,优先级次低 while (index < s.size()) { //遍历公式中的每一个字符 //获取该数字索引开始的整个数字,并压入栈number中 if (isdigit(s[index])) { number.push(getNum(s, index)); } //遇到公式中的空格直接跳过 else if (s[index] == ' ') { index++; } else { //若运算符栈的栈顶的优先级小于遍历遇到的当前的运算符,则将该运算符压入运算符栈 if (maps[s[index]] > maps[symbol.top()]) { symbol.push(s[index]); index++; } //否则,弹出该栈顶运算符,从运算数栈中依次弹出运算数,完成弹出运算符对应的运算后,再将该结果压入运算数栈。 else { double x = number.top(); number.pop(); double y = number.top(); number.pop(); char op = symbol.top(); symbol.pop(); number.push(cal(y, x, op)); } } } //精确到小数点后2位 printf("%.2f\n", number.top()); } return 0; } // 64 位输出请用 printf("%lld")