核心考點:1.棧的應用 2.字符串處理
題目描述
所謂后綴表達式是指這樣的一個表達式:式中不再引用括號,運算符號放在兩個運算對象之后,所有計算按運算符號出現的順序,嚴格地由左而右新進行(不用考慮運算符的優先級)。
本題中運算符僅包含?+-*/+-*/。保證對于?//?運算除數不為 0。特別地,其中?//?運算的結果需要向 0 取整(即與 C++?/
?運算的規則一致)。
如:3*(5-2)+73*(5-2)+7?對應的后綴表達式為:3.5.2.-*7.+@3.5.2.-*7.+@。在該式中,@
?為表達式的結束符號。.
?為操作數的結束符號。
輸入格式
輸入一行一個字符串?ss,表示后綴表達式。
輸出格式
輸出一個整數,表示表達式的值。
輸入輸出樣例
輸入 #1
3.5.2.-*7.+@
輸出 #1
16
輸入 #2
10.28.30./*7.-@
輸出 #2
-7
詳細解答:
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;int main()
{stringstream streamer; // 用于存儲當前讀取的數字string str; // 存儲輸入的后綴表達式getline(cin, str, '@'); // 讀取輸入的后綴表達式,遇到 '@' 時結束輸入stack<int> sta; // 用棧來存儲操作數// 遍歷后綴表達式中的每個字符for (auto &c : str){if (c == '.') // 處理操作數結束符 '.'{int val;streamer >> val; // 讀取當前數字sta.push(val); // 將操作數壓入棧streamer.clear(); // 清空字符串流,為下一次讀取做準備}else if (isdigit(c)) // 如果是數字字符,加入到字符串流中streamer << c;else // 如果是運算符{int a, b;a = sta.top(); // 彈出棧頂的第一個操作數sta.pop();b = sta.top(); // 彈出棧頂的第二個操作數sta.pop();// 根據不同的運算符進行相應的運算switch (c){case '+': // 加法sta.push(a + b);break;case '-': // 減法sta.push(b - a);break;case '*': // 乘法sta.push(a * b);break;case '/': // 除法sta.push(b / a); // 向0取整的除法(C++中的整數除法)break;}}}printf("%d", sta.top()); // 輸出棧頂的值,即表達式的計算結果return 0;
}
核心知識積累:
1.通過stringstreamer字符串流將字符型和整型進行轉換
stringstreamer streamer;
streamer<<c;
steamer>>val;
2.循環語句的寫法:for(auto &c:str)
這句話的意思是:定義一個變量c,從str中逐一取元素,c的類型根據str決定,所以前面是auto
3.getline()函數
getline(cin,str,'@');若有三個參數,意思是遇見@停止輸入;?
getline(cin,str);若只有兩個參數,則意思是遇見回車停止輸入。?
題目解析
1. 思路分析
本題是關于后綴表達式的求值問題。后綴表達式的特點是:沒有括號,運算符出現在操作數之后。解決此類問題的常見方法是使用棧來存儲操作數。對于每個符號的處理可以分為以下幾步:
- 遇到數字:將數字壓入棧中。
- 遇到運算符:彈出棧頂的兩個操作數,進行相應的運算,然后將運算結果重新壓入棧中。
- 最后,棧頂的值即為整個表達式的結果。
2. 棧的使用
棧是本題的核心數據結構。后綴表達式中,運算符總是出現在兩個操作數之后,意味著在運算符出現時,操作數已經在棧中準備好。因此,棧可以方便地管理這些操作數并執行運算。
- 當遇到數字時,我們將其壓入棧。
- 當遇到運算符時,我們從棧中彈出兩個操作數,執行運算,然后將結果再壓入棧中。
3. 運算符處理
在本題中,支持的運算符有+
、-
、*
、/
,其中 /
運算符要求向0取整,這與大多數編程語言的向下取整規則不同。C++中的整型除法會自動執行向0取整(即除法結果的小數部分被截斷)。
4. 輸入輸出格式
- 輸入:一個字符串表示后綴表達式,表達式中的數字和運算符通過
.
與@
符號進行分隔,@
表示表達式的結束。 - 輸出:一個整數,表示后綴表達式的計算結果。
5.易錯點:push中b-a還是a-b要注意,以及除法
題目來源:P1449 后綴表達式 - 洛谷