程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++順序設計與言語(特別版) -- 一個桌面計算器

C++順序設計與言語(特別版) -- 一個桌面計算器

編輯:關於C++

C++順序設計與言語(特別版) -- 一個桌面計算器。本站提示廣大學習愛好者:(C++順序設計與言語(特別版) -- 一個桌面計算器)文章只能為提供參考,不一定能成為您想要的結果。以下是C++順序設計與言語(特別版) -- 一個桌面計算器正文


前言
  • 這裡要引見各種語句和表達式,將經過一個桌面計算器的順序做些事情,該計算器提供四種座位浮點數的中綴運算符的規范算術運算。
  • 這個計算器由四個局部組成:一個剖析器,一個輸出函數,一個符號表和一個驅動順序。
剖析器
program:
    END
    expr_list END //END表示輸出完畢
expr_list:
    expression PRINT // PRINT表示分號
    expression PRINT expr_list
expression:
    expression + term
    expression - term
    term
term:
    term / primary
    term * primary
    primary
primary:
    NUMBER
    NAME
    NAME = expression
    - primary
    (expression)
  • 語法剖析器采用通常的遞歸下降的作風。終結符由詞法剖析順序get_token()辨認,而非終結符由語法剖析函數expr(),term()和prim()辨認。一旦一個表達式的兩個運算對象都知道,就立刻對這個表達式求值。
  • 團體覺得剖析器好像是定義順序能承受什麼輸出,而這裡采用遞歸的方式,例如program代表順序,program可以承受END符號或許expr_list END,而expr_list又持續遞歸下去可以由其他的組成,直到可以失掉一個完畢狀況。
總代碼
#include<iostream>
#include<string>
#include<map>
#include<cctype>
using namespace std;

// 將token用他們的字符所對應的整數表示,這樣做既方便無效,
// 又能協助運用排錯零碎的人。
enum Token_value {
    NAME, NUMBER, END, PLUS='+',
    MINUS='-', MUL='*', DIV='/',
    PRINT=';', ASSIGN='=', LP='(', RP=')',
};
Token_value curr_tok = PRINT;

double expr(bool);
double term(bool);
double prim(bool);
Token_value get_token();
double error(const string&);
map<string, double> table;

int no_of_errors;

int main()
{
    table["pi"] = 3.1415924535;
    table["e"] = 2.178;

    while(cin) {
        get_token();
        if(curr_tok == END) break;
        if(curr_tok == PRINT) continue;
        cout<<expr(false)<<'\n';
    }
    return no_of_errors;
}

// 每個剖析器都有一個bool參數,
// 指明該函數能否需求調用get_token()去獲得下一個參數
// expr處置加減,不斷到不是加減前往left
double expr(bool get) {
    double left = term(get);
    for(;;) {
        switch (curr_tok){
        case PLUS:
            left += term(true);
            break;
        case MINUS:
            left += term(true);
            break;
        default:
            return left;
        }
    }
}

// 函數term處置乘除,采用的方式與expr()處置辦法一樣
double term(bool get) {
    double left = prim(get);
    for(;;) {
        switch (curr_tok){
        case MUL:
            left *= prim(true);
            break;
        case DIV:
            if (double d = prim(true)) {
                left /= d;
                break;
            }
            return error("divide by 0");
        default:
            return left;
        }
    }
}

double number_value;
string string_value;

// prim處置初等項的方式很像expr和term
double prim(bool get) {
    if (get) get_token();

    switch(curr_tok) {
    case NUMBER: {
        double v = number_value;
        get_token();
        return v;
    }
    case NAME: {
        double& v = table[string_value];
        if (get_token() == ASSIGN) v = expr(true);
        return v;
    }
    case MINUS:
        return -prim(true);
    case LP: {
        double e = expr(true);
        if (curr_tok != RP) return error(" ) expected");
        get_token();
        return e;
    }
    default:
        return error("primary expected");
    }
}

Token_value get_token() {
    char ch;
    
    do { // 低級輸出,改良輸出
        if(!cin.get(ch)) return curr_tok = END;
    } while(ch != '\n' && isspace(ch));

    switch(ch) {
    case 0:
        return curr_tok=END;
    case '\n':
        return curr_tok=PRINT;
    case '+':
    case '-':
    case '*':
    case '/':
    case ';':
    case '(':
    case ')':
    case '=':
        return curr_tok = Token_value(ch);
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    case '.':
        cin.putback(ch);
        cin>>number_value;
        return curr_tok = NUMBER;
    default:
        if (isalpha(ch)) {
            string_value = ch;
            while(cin.get(ch) && isalnum(ch)) string_value.push_back(ch);
            cin.putback(ch);
            return curr_tok = NAME;
        }
        error("bad token");
        return curr_tok = PRINT;
    }
}

double error(const string& s) {
    no_of_errors ++;
    cerr<<"error: "<<s<<'\n';
    return 1;
}
擴展
  • 自己的代碼只是復雜的拼接,這裡發現一個更好的博客。
    
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved