PTA7-4 後綴式求值 (25分) (題目 + 代碼 + 詳細註釋 + 坑點分析)

我們人類習慣於書寫“中綴式”,如 3 + 5 * 2 ,其值爲13。 (p.s. 爲什麼人類習慣中綴式呢?是因爲中綴式比後綴式好用麼?)
而計算機更加習慣“後綴式”(也叫“逆波蘭式”,Reverse Polish Notation)。上述中綴式對應的後綴式是: 3 5 2 * +
現在,請對輸入的後綴式進行求值。

輸入格式:

在一行中輸入一個後綴式,運算數運算符之間用空格分隔,運算數長度不超過6位,運算符僅有+ - * / 四種。

輸出格式:

在一行中輸出後綴式的值,保留一位小數。

輸入樣例:

3 5.4 2.2 * +

輸出樣例:

14.9

 

題意:給定字符串,算出其後綴表達式的結果

方法:典型的棧的操作,當讀入數字時,入棧;當讀到運算符時,彈出棧頂的兩個數進行運算,再把結果加入棧中(用STL的string和stack很容易實現)

注意點分析:

  • 判斷負數和小數
  • 當做減法和除法運算時,第二個彈出的數纔是被減數或被除數
  • 由題意知,除數不會是0,因爲會運算錯誤,題目沒有讓給出錯誤提示

AC代碼如下:

#include<bits/stdc++.h> 
using namespace std;

stack<double>num;                 //聲明一個棧,儲存操作數

double cal(double x1, double x2, char c){          //給定兩個數(x1先彈出)和操作符,得到計算結果
    if (c == '+')  return x1 + x2;
    if (c == '-')  return x2 - x1;               //注意是x2 - x1和 x2 / x1
    if (c == '*')  return x1 * x2;
    if (c == '/')  return x2 / x1;           
}

double change(string s) {                     //把字符串轉成相應的數值
    double ans = 0, sign = 1;                //sign爲符號,初始爲1
    if (s[0] == '-') {                       //先判斷負數
        sign = -1;                           //標記符號爲負
        s.erase(s.begin());                 //把首位的負號抹去
    }
    int cnt = 0, flag = 0;                   //cnt是小數位的位數(即最後小數點要往左移多少位),flag表示是否發現了小數點,二者初始都是0
    for (int i = 0; s[i]; i++) {             //遍歷字符串
        char c = s[i];                              
        if (c != '.') ans = ans * 10 + c - '0';          //如果是數字,則轉換成對應的值(高位乘10加本位)
        else  flag = 1;                //發現了小數點,flag改爲1
        if(c != '.') cnt += flag;      //小技巧:當發現了小數點之後,cnt每次都要+1,在此之前不變,即加0;而剛好和flag同步了,則可以直接加flag;這裏的判斷是因爲,剛發現小數點時,cnt不加
    }
    if(cnt)  ans /= pow(10, cnt);                 //小數點移位操作,即除以10^cnt
    return sign * ans;                       //最後連帶符號返回字符串對應的數值
}

int main() {
    string s;
    double ans;
    getline(cin, s);                     //對於中間有空格的字符串,要用getline
    for (int i = 0; s[i];) {             //遍歷字符串
        string temp = "";                
        while (s[i] != ' ' && s[i])       //得到每兩個空格之間的部分
            temp += s[i++];                  //string類可以把字符直接加到末尾
        if (s[i] == ' ')                  //跳過空格
            i++;
        if (temp == "+" || temp == "-" || temp == "*" || temp == "/") {       //如果是操作符
            double x1 = num.top();             //彈出兩個數
            num.pop();
            double x2 = num.top();
            num.pop();
            ans = cal(x1, x2, temp[0]);         //進行運算
            num.push(ans);              //再把結果壓入棧中
        }
        else                           //是操作數,就把string轉換成double,併入棧
            num.push(change(temp));

    }

    printf("%.1f\n", ans);                          //輸出最終結果
    return 0;
}

//常看我的博客都知道,我的博客講解就像金針菇那麼細,註釋都很詳細的。大神勿噴!

//先看後好習慣哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章