2.1棧的應用(括號匹配問題、簡單計算器)

一、括號匹配問題

1、題目和要求

時間限制:1s,內存限制:32MB,特殊判題:否
在這裏插入圖片描述

2、總結

1)c++有自帶的求char數組長度的函數strlen(),頭文件是string.h。自己還花時間寫了一個函數來求長度。
自己寫的函數直接在else裏返回 ,但是不符合在線編譯器編譯規則,應改爲下面的寫法:在函數末尾return

//修改前,計算輸入字符串長度
int stringLength(char* c)
{
    int i=0;
    while(i<N)
    {
        if(c[i]!='\0'){i++;}
        else{return i;}
    }
}
//修改後,計算輸入字符串長度
int stringLength(char* c)
{
    int i=0;
    while(i<N)
    {
        if(c[i]!='\0'){i++;}
        else{break;}
    }
    return i;
}

2)scanf("%s",input_string)scanf("%s",&input_string)第二種寫法不符合在線編譯器編譯規則。數組名本來就表示了數組的首地址,多加一個&,畫蛇添足!!!

3)由於系統通過判斷是否遇到’\0’,來決定是否終止字符串輸出;因此,當數組預留空間大於需要輸出的數組長度時,在輸出字符串的末尾一定要加上output_string[strlen(input_string)] = '\0'作爲結束符,否則還會繼續輸出一些未知的東西。


怎樣的char數組,系統會自動在結尾加上’\0’呢?
1.當以字符串形式在代碼中爲數組賦值時,系統會自動爲’\0’開一個存儲空間。
2.字符串長度不包括’\0’。


3、思路

主要思路:輸入字符串後,從後往前遍歷。遇到右括號入棧;遇到左括號根據中間棧中的內容進行下一步操作,如果棧爲空則不匹配,如果棧頂爲右括號則出棧。當輸入字符串遍歷結束後,若棧中還剩餘則不匹配。

4、代碼
#include <stdio.h>
#include <stack>
#include <string.h>
using namespace std;

#define N 100

//)(rttyy())sss)(
//存儲括號和位置信息
class bracket
{
private:
    int pos;
    char value;

public:
    bracket() {};
    void set(int p,char v)
    {
        pos = p;
        value = v;
    };

    int getPos()
    {
        return pos;
    }
    char getValue()
    {
        return value;
    }
};

int main()
{
    char input_string[N];           //記錄輸入字符串
    char output_string[N];          //記錄輸出字符串
    int i;                          //記錄輸入字符串、輸出字符串位置
    char c;                         //記錄當前字符
    bracket b;
    stack<bracket> s;               //中間棧

    scanf("%s",input_string);

    for(i=strlen(input_string)-1; i>=0; i--)
    {
        c = input_string[i];
        switch (c)
        {
        case ')':
            b.set(i,c);
            s.push(b);
            break;
        case '(':
            if(s.empty())
            {
                output_string[i] = '$';
            }
            else
            {
                b = s.top();
                if(b.getValue()==')')
                {
                    s.pop();
                    output_string[i] = ' ';
                    output_string[b.getPos()] = ' ';
                }
            }
            break;
        default:
            output_string[i] = ' ';
        }
    }

    while(!s.empty())
    {
        b = s.top();
        output_string[b.getPos()] = '?';
        s.pop();
    }

    output_string[strlen(input_string)] = '\0';
    printf("%s\n",input_string);
    printf("%s\n",output_string);
    return 0;
}

二、簡單計算器

1、題目和要求

時間限制:1s,內存限制:32MB,特殊判題:否
在這裏插入圖片描述

2、總結

1)using namespace std.h兩種方式的區別。選自:頭文件加.h和不加,h區別,以及using namespace std
.h是C語言中使用的,當使用.h時,相當於在c中調用庫函數,使用的是全局命名空間。
C++ 標準程序庫中的所有標識符都被定義於一個名爲std的namespace中,因此使用前要聲明命名空間。using namespace std是c++中聲明命名空間的一種方式。
在這裏插入圖片描述
2)stdioiostream兩種標準輸入輸出庫的區別。
stdio屬於c語言,輸入輸出爲printf(),scanf()。
iostream屬於c++,輸入輸出爲cout<<…,cin>>…。

3)c++中字符串的存儲和讀取方式。c++存儲字符串的方法( 讀取字符串、char 數組、string 類型)
在下面的代碼中,沒有指定getline()函數的結束符,輸入ctrl+z即可結束。

4)C語言中保留小數點後兩位數:printf("%.2lf",a);
c++中保留小數點後兩位數:cout << fixed <<setprecision(2)<<a;

5)注意:

  • 操作數出棧順序與入棧順序相反,除法和減法操作需注意。
  • 進行 “一次” 運算要出棧 “兩個操作數” 和 “一個運算符”
  • switch-case切記break!!
3、思路

1)設兩個堆棧,一個運算符棧,一個數字棧。
2)從左至右依次遍歷字符串。若遍歷到運算符,入運算符棧;若遍歷到數字,則開始拼接數字,完成後入數字棧。
3)開始計算。
1>若運算符棧棧頂運算符爲 × 、/,則彈出棧頂運算符,再從數字棧中依次彈出兩個棧頂數字,完成運算後,將結果壓入數字棧。
2>若運算符棧棧頂運算符爲 + 、- 且棧頂下一個運算符爲 × 、/,則彈出棧頂運算符和棧頂數字,保存。然後,彈出當前棧頂運算符,再從數字棧中依次彈出兩個棧頂數字,完成運算後,將結果壓入數字棧。最後,把剛剛保存的運算符和數字壓棧。
4)若運算符棧爲空,則運算結束,此時數字棧中唯一的數字即爲表達式的值,顯示後,彈出,爲下一輪運算清空棧。

4、代碼
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>
using namespace std;

#define N 200

stack<char> op;                 //運算符棧
stack<double> num;              //操作數棧
double a,b;                     //兩個操作數

double add()
{
    a = num.top();
    num.pop();
    b = num.top();
    num.pop();
    return (a+b);
}

double jianfa()
{
    a = num.top();
    num.pop();
    b = num.top();
    num.pop();
    return (b-a);
}

double mul()
{
    a = num.top();
    num.pop();
    b = num.top();
    num.pop();
    return (a*b);
}

double div()
{
    a = num.top();
    num.pop();
    b = num.top();
    num.pop();
    return (b/a);
}
int main()
{

    string input_string;
    char c,t;
    double value = 0;

    //使用getline讀取,可以讀取空格和換行
    while(getline(cin,input_string)!=0)
    {
        if(input_string=="0")
        {
            continue;
        }

        //從字符串開頭開始遍歷,入操作數棧和運算符棧
        for(int i=0 ; i<input_string.length(); )
        {
            c = input_string[i];
            if(c =='+' || c =='-'||c =='*'||c =='/')
            {
                op.push(c);
                i++;
            }
            else if(c<='9'&&c>='0')
            {
                while(c<='9'&&c>='0')
                {
                    value = value*10 +(double)(c-'0');
                    i++;
                    c = input_string[i];
                }
                num.push(value);
                value = 0;
            }
            else
            {
                i++;
            }
        }

        while(!op.empty())
        {
            c = op.top();
            op.pop();

            switch(c)
            {
            case '+':
                if(op.empty())
                {
                    num.push(add());
                }
                else
                {
                    t = op.top();
                    if(t=='+'||t=='-')
                    {
                        num.push(add());
                    }
                    else if(t=='*')
                    {
                        op.pop();
                        double number = num.top();
                        num.pop();
                        num.push(mul());
                        num.push(number);
                        op.push(c);
                    }
                    else if(t=='/')
                    {
                        op.pop();
                        double number = num.top();
                        num.pop();
                        num.push(div());
                        num.push(number);
                        op.push(c);
                    }
                }
                break;
            case '-':
                if(op.empty())
                {
                    num.push(jianfa());
                }
                else
                {
                    t = op.top();
                    if(t=='+'||t=='-')
                    {
                        num.push(jianfa());
                    }
                    else if(t=='*')
                    {
                        op.pop();
                        double number = num.top();
                        num.pop();
                        num.push(mul());
                        num.push(number);
                        op.push(c);
                    }
                    else if(t=='/')
                    {
                        op.pop();
                        double number = num.top();
                        num.pop();
                        num.push(div());
                        num.push(number);
                        op.push(c);
                    }
                }
                break;
            case '*':
                num.push(mul());
                break;
            case '/':
                num.push(div());
                break;
            }
        }

        if(!num.empty())
        {
            cout << fixed <<setprecision(2)<<num.top()<<endl;
            num.pop();
        }
    }

    return 0;
}

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