目標:實現一個可以計算加減乘除四種運算,可以識別處理'(',')','+','-','*','/','=',可以操作整數的計算器。
步驟:(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 }