中綴表示式轉字尾並求值C++(括號,小數點,負數)
阿新 • • 發佈:2018-12-16
題目內容:
通過把“中綴轉字尾”和“字尾求值”兩個演算法功能整合在一起(非簡單的順序呼叫),
實現對中綴表示式直接求值,新演算法還是從左到右掃描中綴表示式,
但同時使用兩個棧,一個暫存操作符,一個暫存運算元,來進行求值。
(支援 + - * / ^ 五種運算)
輸入格式:
共1行,為1個字串,即一箇中綴表示式,
其中每個數字或符號間由一個空格隔開。
輸出格式:
共1行,為一個整數,即求值的結果。
輸入樣例:
( 2 + 3 ) * 6 + 4 / 2
輸出樣例:
32
思路
- 首先將中綴轉換為字尾表示式。 (a ).對於形如(-1+1)的計算。 (b )使用一個棧來暫存操作符。將結果直接輸出到一個字串。 (c ).對符號設立優先順序,^ > / * > + - 。 (d ).括號的匹配與優先順序問題。’( '直接進棧,遇 ‘ )’彈出直至上一個‘( ’之間的所有運算子,括號不輸出到字尾表示式中。
- 字尾表示式的計算。 (a ).乘方運算函式 pow(int _left, int _right); (b ).空格符的處理:(a+b)與 ( a + b ):加入一個case ‘ ’:break;即可。
函式
void IntoPost(string inStr); //字首轉字尾 bool isPush(char pre, char late); //優先順序比較 void Calculate(char np); //彈出兩個棧內數運算後再壓進棧 void CalFix(); //字尾表示式計算 void pushChar(char np); //運算子出棧 string format(string str) ; //解決(-1+2)負數報錯問題
一些關鍵點
解決負數問題思路: 即在 -1 前面加一個0 變成 0-1 即可
string format(string str) { //解決(-1+2)負數報錯問題
for (int i = 0; i < str.length(); i++) //即在 -1 前面加一個0 變成 0-1 即可
if (str[i] == '-')
if (i == 0)
str.insert(0, 1, '0');
else if (str[i - 1] == '(')
str.insert(i, 1, '0');
return str;
}
優先順序比較(其實有更簡單一點的操作,我做複雜了)
void pushChar(char np) { //運算子出棧
if (!CharStack.empty()){
while (!CharStack.empty() && isPush(CharStack.top(), np)) {
fixStr += CharStack.top(); //判斷優先順序
CharStack.pop();
}
CharStack.push(np);
}
else
CharStack.push(np);
}
bool isPush(char pre, char late) { //優先順序比較
if (late == '^')
if (pre == '^') return true;
else return false;
if (late == '*' || late == '/')
if (pre == '^' || pre == '*' || pre == '/') return true;
else return false;
if (late == '+' || late == '-')
if (pre == '(') return false;
else return true;
return false;
}
程式碼
/* Author : YaaaZa! ?
* Time : 2018.10.20
* 中綴轉字尾求值
*/
#include "stdafx.h"
#include<iostream>
#include<stack>
#include<string>
using namespace std;
stack<int> MoveIn;
stack<char> CharStack;
string fixStr = "";
void IntoPost(string inStr);
bool isPush(char pre, char late);
void Calculate(char np);
void CalFix();
void pushChar(char np);
string format(string str) { //解決(-1+2)負數報錯問題
for (int i = 0; i < str.length(); i++) //即在 -1 前面加一個0 變成 0-1 即可
if (str[i] == '-')
if (i == 0)
str.insert(0, 1, '0');
else if (str[i - 1] == '(')
str.insert(i, 1, '0');
return str;
}
int main(){
string inStr;
getline(cin, inStr); //使用getline 解決字串錄入遇空格結束的問題 類似 ( a + b ) 只寫入了 ( 的
inStr = format(inStr);
IntoPost(inStr);
CalFix();
return 0;
}
void IntoPost(string inStr) { //字首轉字尾
for (int i = 0; i < inStr.length(); i++) {
switch (inStr[i]) {
case ' ': break;
case '+':pushChar('+'); break;
case '(':CharStack.push('('); break;//遇前括號直接入棧
case ')': //遇後括號彈出所有至上一個括號
while (CharStack.top() != '(') {
fixStr += CharStack.top();
CharStack.pop();
}
CharStack.pop();
break;
case '/':pushChar('/'); break;
case '*':pushChar('*'); break;
case '-':pushChar('-'); break;
case '^':pushChar('^'); break;
default:
fixStr += inStr[i]; break; //數字直接輸出
}
}
while (!CharStack.empty()) { //整式尾部時彈出所有站內符號
fixStr += CharStack.top();
CharStack.pop();
}
}
void pushChar(char np) { //運算子出棧
if (!CharStack.empty()){
while (!CharStack.empty() && isPush(CharStack.top(), np)) {
fixStr += CharStack.top(); //判斷優先順序
CharStack.pop();
}
CharStack.push(np);
}
else
CharStack.push(np);
}
bool isPush(char pre, char late) { //優先順序比較
if (late == '^')
if (pre == '^') return true;
else return false;
if (late == '*' || late == '/')
if (pre == '^' || pre == '*' || pre == '/') return true;
else return false;
if (late == '+' || late == '-')
if (pre == '(') return false;
else return true;
return false;
}
void CalFix() { //字尾表示式計算
for (int i = 0; i < fixStr.length(); i++) {
switch (fixStr[i]) {
case '+':Calculate('+'); break;
case '/':Calculate('/'); break;
case '*':Calculate('*'); break;
case '-':Calculate('-'); break;
case '^':Calculate('^'); break;
case ' ': break;
default:
int a;
a = (int)(fixStr[i] - 48);
MoveIn.push(a);
break;
}
}
cout << MoveIn.top();
}
void Calculate(char np) { //彈出兩個棧內數運算後再壓進棧
int pre, late;
late = MoveIn.top();
MoveIn.pop();
pre = MoveIn.top();
MoveIn.pop();
switch (np) {
case '+':MoveIn.push(pre + late); break;
case '/':MoveIn.push(pre / late); break;
case '*':MoveIn.push(pre * late); break;
case '-':MoveIn.push(pre - late); break;
case '^':MoveIn.push(pow(pre,late)); break;
default:
break;
}
}