用棧將算術表達式轉換成后綴表達式的形式大家應該不陌生了,但是我在實現計算的時候卻發現坑還是不少。
題目描述: 讀入一個只包含 +, -, *, / 的非負整數計算表達式,計算該表達式的值。
輸入描述: 測試輸入包含若干測試用例,每個測試用例占一行,每行不超過200個字符,整數和運算符之間用一個空格分隔。沒有非法表達式。當一行中只有0時輸入結束,相應的結果不要輸出。
輸出描述: 對每個測試用例輸出1行,即該表達式的值,精確到小數點后2位。
示例1
輸入
1 + 2
4 + 2 * 5 - 7 / 11
0
輸出
3.00
13.36
PS:不知道為什么,$轉義總是失敗,有朋友知道怎么轉義的話請留言告訴我~
做這題必須注意幾個問題:
* 當棧里沒有運算符的時候,直接對棧頂和字符串讀取到的運算符進行比較會出錯,因此這里在一開始就往棧里壓入了一個我們設計的符號'#'
* 當我們遍歷字符串的時候,遇到數字要格外注意,因為此時一切都是字符形式了,比如說輸入11就會變成兩個字符1,因此我們在讀取的時候要進行判斷,確保所有連在一起的數字字符都讀到了,而不是只讀到了第一個字符。
* 當我們遍歷完字符串的時候,很有可能棧里還留有沒處理的運算符,因此我們需要繼續處理棧里的操作符,這里在字符串后面加入了符號//$是很巧妙的,\$的優先級比'#'高,比其他符號低,因此這保證了當讀到字符\$時,它一定比棧頂出現的所有字符優先級高(除了它自己和'#'),這樣就可以讓棧里剩下的運算符一個一個彈出來,至到處理結束,棧頂為'\#',壓入\$。
具體代碼如下:
#include<iostream>
#include<stack>
#include<string>
#include<stdio.h>
#include<cctype>
using namespace std;
/**
* 比較操作符優先級的函數
*/
int OperPrecedence(char a){
if(a == '/' || a == '*'){
return 3;
}else if(a == '+' || a == '-' ){
return 2;
}else if(a == '$'){
return 1;
}else if(a == '#'){
return 0;
}
}
/**
* 實現運算
*/
double operNums(char oper, double num1, double num2){
if(oper == '+'){
return num1 + num2;
}else if(oper == '-'){
return num1 - num2;
}else if(oper == '*'){
return num1 * num2;
}else if(oper == '/'){
return num1 / num2;
}
}
/**
* 實現遇到數字往后移動直到數字確定
*/
int getNum(string str, int &index){
string num = "";
while(isdigit(str[index])){
num += str[index];
index ++;
}
return atoi(num.c_str());
}
int main(){
stack<char> operStack;
stack<double> numStack;
string str;
char oper;
double num1;
double num2;
double sum = 0;
int index = 0, preceResult;
operStack.push('#');
while (getline(cin, str))
{
str += '$';
if(str[0] == '0'){
break;
}
while(index < str.size()){
if(str[index] == ' '){
index++;
}
else if(isdigit(str[index])){
//數字
numStack.push(getNum(str, index));
}else
{
//操作符
//比較優先級
if(OperPrecedence(operStack.top()) < OperPrecedence(str[index])){
operStack.push(str[index]);
index++;
}else{
num2 = numStack.top();
numStack.pop();
num1 = numStack.top();
numStack.pop();
oper = operStack.top();
operStack.pop();
numStack.push(operNums(oper, num1 ,num2));
}
}
}
// std::cout << "sum="<<sum << endl;
printf("%.2f\n", numStack.top());
index = 0;
}
}