[Abuse] 用C++建立四則運算解題工具:最簡單的計算器(第一天, 001)

接下來幾天會每天寫一些,逐漸建立一個完整的算術運算工具,功能會像是bc(Basic Calculator),功能當然會像它一樣強大囉,不過這會是一個過程好玩的專案,一個過程讓我覺得好玩的專案,所以程式碼一定要充滿趣味,基本上會有以下特性:
  1. 良好的可讀性
  2. 精簡的程式
  3. 刻意採用的設計模式
  4. 一些C++語言特性的功能濫用
1.可讀性是我在學習程式語言過程中相當在意的,就像說說話說得清楚,讓溝通順利,程式碼不只是給機器讀取後順利達成目標,在很多時候程式碼會與自己或他人交流,清楚表達程序與邏輯概念讓自己好維護、除錯,與人交流時也比較省力。
2.一天的時間有限,寫得越長閱讀時間越長,如果有精簡作法節省時間就要來省一下。
3.作為練習的專案,刻意練習平常不用的東西是好事
4.因為最近想學習C++11,事實上C++也不算熟,對於STL只有粗淺的認識,C++標準函式庫也需要一直查資料才會用(函式庫用了很多STL很讓人崩潰)。

 以下進入正題
一個簡單的計算器就是輸入三個東西順序依序是:數字(運算元)、運算符號(運算子)、數字(運算元)。
像是:
  • 1 + 1
  • 20 * 50
因為是簡單的計算器運算元被限定是:
  • +  加法
  • -  減法
  • *  乘法
  • /  除法
所以概念上
  1. 讀取輸入的一行
  2. 分別找出運算元與運算子
  3. 依據運算子對運算元進行處理
  4. 輸出結果
#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main()
{
    string line;
    regex expression(" *([0-9] ) *([\\ |\\-|\\*|/]) *([0-9] ) *");
    while(!cin.eof())
    {   
        getline(cin, line);
        
        if(!line.empty())
        {
            if(!regex_match(line, expression))
                cout << "Illegal expression" << endl;
            else
            {
                smatch m;
                regex_match(line, m, expression);
                
                //print submatch
                //for(auto &a : m){cout << a.str() << endl;}
                
                cout << "= ";
                switch((m[2]).str().c_str()[0]){
                    case ' ':
                        cout << stoll(m[1])   stoll(m[3]) << '\n';
                        break;
                    case '-':
                        cout << stoll(m[1]) - stoll(m[3]) << '\n';
                        break;
                    case '*':
                        cout << stoll(m[1]) * stoll(m[3]) << '\n';
                        break;
                    case '/':
                        cout << stoll(m[1]) / stoll(m[3]) << '\n';
                        break;
                }
            }
        }
    }
    
    return EXIT_SUCCESS;
}

看似簡單的流程但卻有利用'正規表示式'(Regular Expression, regex)的合理原因,利用正規表示式能夠檢查輸入是否合法、分析運算子與運算元,也算是一種練習符合還有一點'Abuse'的意象。
正規表示式處理空白很方便,不管空白在前、在後,還是在中間都順利解析運算子與運算元。
regex expression(" *([0-9]+) *([\\+|\\-|\\*|/]) *([0-9]+) *");

[明天與問題]
  1.  除法問題,除法目前沒有轉型因為我之後想做成分數的形式,盡可能的使用整數運算,因為在學習基本算術時往往都是整數的答案, 如果用浮點數運算可能會有精度問題。
  2. 明天目標:完成四則運算功能
[參考資料]
Regex

留言

這個網誌中的熱門文章

[Abuse] 用C++建立四則運算解題工具:語法分析器(Precedence climbing) Epidos 5 (第9天, 005)

[Abuse] 用C++建立四則運算解題工具:語法分析器Epidos 4 (第8天, 004)