第一种方法的逻辑是我比较理得清的
法一:
midS是存放中缀表达式的字符串,字符之间没有空格,suffiexS是存放后缀表达式的字符串,数字和字符之间都有空格
思路:
1.如果midS[i]是'(',直接压栈
2.如果是数字, 把完整数字复制到到midS中后加一个空格,读取完数字后要判断此时的midS[i]是否是'\0',如果是的话,break结束循环
3.如果是')',不停弹栈,把弹栈后的字符存到suffiexS中,加空格,注意要更新ch中所存栈顶元素的值,等遇到栈顶为'('时,停止弹栈,把'('出栈
4.如果栈顶字符优先级小于midS[i]或者栈为空,那么midS[i]直接进栈
5.如果栈顶字符优先级大于等于midS[i],一直弹出栈顶元素到suffiexS中(直到栈顶字符优先级小于midS[i]或者栈为空),每次存字符之后都要加空格,循环中注意更新ch中所存栈顶元素的值,'('的优先级最低,所以无论如何都不会在此比较下被弹出
6.退出循环后,判断栈是否为空,如果不为空的话,一直弹栈,将字符存入后缀表达式的字符串,加空格
1 #include "SqStack.h" 2 #include <cctype> 3 4 double caculate(double a, char ch, double b) 5 { 6 switch (ch) 7 { 8 case '+': return a + b; 9 case '-': return a - b; 10 case '*': return a * b; 11 case '/': return a / b; 12 } 13 return 0; 14 } 15 16 int get_priority(char ch) 17 { 18 int priority = 0; 19 switch (ch) 20 { 21 case '+': 22 case '-': 23 priority = 1; 24 break; 25 case '*': 26 case '/': 27 priority = 2; 28 break; 29 case '(': 30 priority = 0; 31 break; 32 } 33 return priority; 34 } 35 36 /*中缀表达式转后缀表达式*/ 37 void transform(char* suffiexS, char* midS) 38 { 39 int i = 0; 40 int cnt = 0; //作为后缀表达式的字符栈的下标 41 SqStack<char> Stack; 42 char ch; 43 cout << midS << endl; 44 for (i = 0; midS[i] != '\0'; ++i) 45 { 46 /*先把'('和 '数字的情况考虑了*/ 47 if (midS[i] == '(') //如果是'('则直接进栈 48 { 49 Stack.push(midS[i]); 50 continue; 51 } 52 53 if (isdigit(midS[i])) 54 { 55 while (isdigit(midS[i]) && midS[i] != '\0') //如果是数字,则整个赋值到midS中 56 suffiexS[cnt++] = midS[i++]; 57 58 suffiexS[cnt++] = ' '; //在数字后面加一个空格 59 if (midS[i] == '\0') 60 break; 61 } 62 if (!Stack.IsEmpty()) 63 Stack.getTop(ch); 64 if (midS[i] == ')') 65 { 66 Stack.getTop(ch); 67 while (ch != '(') 68 { 69 Stack.pop(ch); 70 suffiexS[cnt++] = ch; 71 suffiexS[cnt++] = ' '; 72 Stack.getTop(ch); 73 } 74 Stack.pop(ch); //将'('弹出,但不存储 75 continue; 76 } 77 78 //如果栈顶字符优先级大于等于midS[i]且栈不为空,弹出栈顶元素到midS中,加空格 79 80 else if ((Stack.IsEmpty() || get_priority(ch) < get_priority(midS[i]))) 81 { 82 Stack.push(midS[i]); 83 } 84 85 else if (get_priority(ch) >= get_priority(midS[i])) 86 { 87 while (get_priority(ch) >= get_priority(midS[i]) && !Stack.IsEmpty()) 88 { 89 Stack.pop(ch); 90 suffiexS[cnt++] = ch; 91 suffiexS[cnt++] = ' '; 92 Stack.getTop(ch); 93 } 94 Stack.push(midS[i]); //把midS[i]入栈 95 } 96 } 97 while (!Stack.IsEmpty()) 98 { 99 Stack.pop(ch); 100 suffiexS[cnt++] = ch; 101 } 102 103 suffiexS[cnt] = '\0'; //在后缀表达式末尾加上空字符 104 cout << suffiexS << endl; 105 }
输入1:
1 #include <iostream> 2 #include <cctype> 3 #include <stack> 4 using namespace std; 5 6 int getPriority(char ch) 7 { 8 int priority = 0; 9 switch(ch) 10 { 11 case '+': 12 priority = 1; 13 break; 14 case '-': 15 priority = 1; 16 break; 17 case '*': 18 priority = 2; 19 break; 20 case '/': 21 priority = 2; 22 break; 23 case '(': 24 priority = 3; 25 break; 26 default: 27 priority = 0; 28 break; 29 } 30 return priority; 31 } 32 33 34 int main() 35 { 36 std::stack<char> S; 37 char ch; 38 cin >> ch; 39 while (ch != '#') 40 { 41 while (isdigit(ch)) 42 { 43 cout << ch; 44 cin >> ch; 45 if(!isdigit(ch)) //ch 不是数字且不是'#', 表示完成了一个整型数据的输入,此时打印一个空格 46 cout << " "; 47 48 49 } 50 if (ch == '#') 51 break; 52 if (ch == ')') //如果读入的字符是')',那么当栈顶元素不是‘(’时,一直输出栈顶元素 53 { 54 while (S.top() != '(') 55 { 56 cout << S.top()<< " "; 57 S.pop(); 58 } 59 S.pop(); 60 } 61 else //正常情况,将ch和栈顶字符比较优先级 62 { 63 while (!S.empty() && S.top() != '(' && getPriority(S.top()) >= getPriority(ch)) 64 { 65 cout << S.top()<< " " ; 66 S.pop(); 67 } 68 S.push(ch); 69 70 }cin >> ch; 71 } 72 73 while (!S.empty()) 74 { 75 cout << S.top(); 76 S.pop(); 77 if (!S.empty()) 78 cout << " "; 79 } 80 81 return 0; 82 }
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\xtgmath.h(214): warning C4602: #pragma pop_macro:“new”该标识符前面没有 #pragma push_macro
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\xtgmath.h(215): warning C4193: #pragma warning(pop) : 没有匹配的“#pragma warning(push)”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\xtgmath.h(216): warning C4161: #pragma pack(pop...) : 出栈的比入栈的多
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(23): error C2061: 语法错误: 标识符“abs”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(23): error C2059: 语法错误:“;”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(23): error C2061: 语法错误: 标识符“acos”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(23): error C2061: 语法错误: 标识符“asin”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(24): error C2061: 语法错误: 标识符“atan”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(24): error C2059: 语法错误:“;”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(24): error C2061: 语法错误: 标识符“atan2”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(24): error C2061: 语法错误: 标识符“ceil”
1>e:\极速考拉下载目录\vs2013(visual studio 2013旗舰版)\vc\include\cmath(25): error C2061: 语法错误: 标识符“cos”
若是switch单词写错了,则可能会出现上述错误。
最后是后缀表达式的计算:
1 /*表达式求解*/ 2 double evaluation(char* suffiexS) 3 { 4 SqStack<int> Stack; 5 int i = 0, num = 0; 6 //cout << suffiexS << endl; 7 int operand1, operand2, result; //两个操作数和计算结果 8 for (i = 0; suffiexS[i] != '\0'; ++i) 9 { 10 if (isdigit(suffiexS[i])) 11 { 12 while (isdigit(suffiexS[i])) 13 { 14 num = num * 10 + suffiexS[i] - '0'; 15 i++; 16 } 17 Stack.push(num); 18 num = 0; 19 } 20 21 if (suffiexS[i] == ' ') 22 continue; 23 if (suffiexS[i] == '+') 24 { 25 Stack.pop(operand1); 26 Stack.pop(operand2); 27 result = operand1 + operand2; 28 Stack.push(result); 29 30 } 31 32 if (suffiexS[i] == '-') 33 { 34 Stack.pop(operand1); 35 Stack.pop(operand2); 36 result = operand2 - operand1; //后pop出来的做被减数 37 Stack.push(result); 38 } 39 40 if (suffiexS[i] == '*') 41 { 42 Stack.pop(operand1); 43 Stack.pop(operand2); 44 result = operand1 * operand2; 45 Stack.push(result); 46 } 47 48 if (suffiexS[i] == '/') 49 { 50 Stack.pop(operand1); 51 Stack.pop(operand2); 52 result = operand2 / operand1; //后pop出来的做被除数 53 Stack.push(result); 54 } 55 56 } 57 Stack.pop(result); 58 return result; 59 }
中缀表达式的输入函数:
1 /*输入中缀表达式*/ 2 void readExpr(char *midS) 3 { 4 char ch; 5 int i = 0; 6 7 while (cin >> ch && ch != '#') 8 midS[i++] = ch; 9 midS[i] = '\0'; 10 11 }