目标:实现一个可以计算加减乘除四种运算,可以识别处理'(',')','+','-','*','/','=',可以操作整数的计算器。
步骤:(1)将中缀表达式转换成后缀表达式
(2)计算后缀表达式
(3)输出结果
准备工作:
1.包含头文件:
1 #include <iostream> 2 #include <stack> 3 #include <string> 4 5 using namespace std;
2.定义两个栈
1 stack<char> opt; // 操作符栈 2 stack<double> val; // 操作数栈
3.定义两个常量表示在数字中的状态
1 const int IN = 0; // 在数字中 2 const int OUT = 1; // 在数字外
4.为操作符规定优先级,并判断输入的操作符是否合法
1 char opt_set[10] = "+-*/()=";
1 /* 为每一个操作符返回一个数,数越大优先级越高 */ 2 3 int level(char theOpt){ 4 for(int i = 0; i < 7; i++){ 5 if(theOpt == opt_set[i]) 6 return i; 7 } 8 return -1; 9 } 10 11 /* 判断输入的操作符是否合法 */ 12 13 bool in_set(char theChar){ 14 for(int i = 0; i < 7; i++){ 15 if(theChar == opt_set[i]) 16 return true; 17 } 18 return false; 19 }
5.整理输入,判断是否有非法字符,用到in_set()函数
1 /* 用于去除空格并检查是否有非法字符 */ 2 bool del_space(string &theString){ 3 string res; 4 for(int i = 0; i < theString.length(); i++){ 5 if(in_set(theString[i]) || isdigit(theString[i])){ 6 res += theString[i]; 7 } 8 else if(theString[i] == ' ') 9 ; 10 else{ 11 cout << "表达式含有错误字符,请重新输入。" << endl; 12 return false; 13 } 14 } 15 theString = res; 16 return true; 17 } 18
6.把数字转换成字符串
20 21 string to_string(int theInt) 22 { 23 if(theInt == 0) 24 return string("0"); 25 bool neg = false; 26 if(theInt < 0) 27 { 28 neg = true; 29 theInt = -theInt; 30 } 31 string res; 32 while(theInt != 0) 33 { 34 char c = (theInt % 10) + '0'; 35 res = c + res; 36 theInt /= 10; 37 } 38 if(neg) 39 res = '-' + res; 40 return res; 41 }
实现第一步:将中缀表达式转化成后缀表达式
1 /* 将中缀表达式转换成后缀表达式 */ 2 bool change(string &from, string &to){ 3 int theInt = 0; // 暂存数字 4 int state = OUT; // 初始状态:在数字外 5 char c; 6 /* 7 if(from[from.length() - 1] != '='){ 8 cout << "等于号语法有误!" << endl; 9 return false; 10 } 11 */ 12 for(int i = 0; i < from.length(); i++){ 13 c = from[i]; 14 if(isdigit(c)){ 15 theInt *= 10; 16 theInt += c - '0'; 17 state = IN; // 状态:在数字内 18 } 19 else{ 20 if(state == IN){ // 刚刚处理了数字 21 to += to_string(theInt) + ' '; 22 theInt = 0; 23 } 24 if(c == '='){ 25 /* 26 if(i != from.length() - 1){ 27 cout << "等于号语法有误!" << endl; 28 return false; 29 } 30 */ 31 break; 32 } 33 else if(c == '(') 34 opt.push(c); 35 else if(c == ')'){ 36 while(!opt.empty() && opt.top() != '('){ 37 to += opt.top(); 38 to += ' '; 39 opt.pop(); 40 } 41 /* 42 if(opt.empty()){ 43 cout << "括号匹配有误!" << endl; 44 return false; 45 } 46 else 47 */ 48 opt.pop(); 49 } 50 else{ 51 while(true){ 52 if(opt.empty() || opt.top() == '(') 53 opt.push(c); 54 else if(level(c) > level(opt.top())) 55 opt.push(c); 56 else{ 57 to += opt.top(); 58 to += ' '; 59 opt.pop(); 60 continue; 61 } 62 break; 63 } 64 } 65 state = OUT; // 状态:在数字外 66 } 67 } 68 while(!opt.empty()){ 69 /* 70 if(opt.top() == '('){ 71 cout << "括号匹配有误!" << endl; 72 return false; 73 } 74 */ 75 to += opt.top(); 76 to += ' '; 77 opt.pop(); 78 } 79 return true; 80 }
实现第二步:计算后缀表达式
1 bool compute(string &theExp){ 2 int theInt = 0; // 暂存数字 3 int state = OUT; // 初始状态:在数字外 4 char c; 5 for(int i = 0; i < theExp.length(); i++){ 6 c = theExp[i]; 7 if(isdigit(c)){ 8 theInt *= 10; 9 theInt += c - '0'; 10 state = IN; // 状态:在数字内 11 } 12 else{ 13 if(state == IN){ // 刚刚处理了数字 14 val.push(theInt); 15 theInt = 0; 16 } 17 double x, y; 18 if(c != ' '){ 19 /* 20 if(val.empty()){ 21 cout << "操作数语法错误!" << endl; 22 return false; 23 } 24 */ 25 x = val.top(); 26 val.pop(); 27 /* 28 if(val.empty()){ 29 cout << "操作数语法错误!" << endl; 30 return false; 31 } 32 */ 33 y = val.top(); 34 val.pop(); 35 switch(c){ 36 case '+': 37 val.push(x + y); 38 break; 39 case '-': 40 val.push(y - x); 41 break; 42 case '*': 43 val.push(x * y); 44 break; 45 case '/': 46 val.push(y / x); 47 break; 48 default: 49 cout << "未知的错误!" << endl; 50 } 51 } 52 state = OUT; 53 } 54 } 55 /* 56 if(val.size() != 1){ 57 cout << "缺少操作符!" << endl; 58 return false; 59 } 60 */ 61 return true; 62 }
实现第三步:测试,输出结果
1 int main() 2 { 3 cout << "请保证所有的操作数均为正整数,且不要输入(+x)的形式。" << endl; 4 cout << "若答案为小数,请按照四舍五入的规则保留小数点后三位。" << endl; 5 while(true){ 6 // 清空流 7 cin.clear(); 8 cin.sync(); 9 // 初始化操作:清空两个栈 10 while(!opt.empty()){ 11 opt.pop(); 12 } 13 while(!val.empty()){ 14 val.pop(); 15 } 16 17 // 输入表达式 18 string init_exp; 19 cout << "请输入以'='结尾的表达式,或输入\"exit\"退出:"; 20 getline(cin, init_exp); 21 22 if(init_exp == string("exit")){ 23 break; 24 } 25 26 // 去除空格并检查是否有非法字符 27 if(!del_space(init_exp)) 28 continue; 29 30 // 转换为后缀表达式 31 string cng_exp; 32 cng_exp.clear(); 33 if(!change(init_exp, cng_exp)) 34 continue; 35 cout << "此表达式转换为后缀表达式为:" << cng_exp << endl; 36 37 // 计算后缀表达式 38 if(!compute(cng_exp)) 39 continue; 40 41 double stdans = val.top(); 42 cout << "此表达式的运算结果为:" << stdans << endl; 43 } 44 return 0; 45 }