Calculator

// 本程序可以實(shí)現(xiàn)實(shí)數(shù)的加減程序四則運(yùn)算煌寇,支持括號運(yùn)算符返劲,不支持正負(fù)符號!另外Calculator類本身進(jìn)行了加減乘數(shù)輸入輸出的重載约巷!
//

#include "stdafx.h"
#include<iostream>
#include<functional>  //plus等標(biāo)準(zhǔn)庫函數(shù)對象
#include<map>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

class Calculator
{
public:
    //Calculator(const map<char,function<double(double,double)>> &c):calu(c){}
    Calculator() = default;
    Calculator(const string &s) :str(s),sum(get_sum(s)) {}
    
    string get_string()const { return str; }

    double get_sum(const string &s)
    { 
        if (sum_str(s))
        {
            str = s;
            return get_sum();
        }
            
        else
        {
            throw exception("NO sum!");
        }
    }
    double get_sum()
    {
        return sum;
    }

    void operator()()
    { 
        cout << get_sum();
    }

    friend Calculator operator+(const Calculator &lh, const Calculator &rh);
    friend Calculator operator-(const Calculator &lh, const Calculator &rh);
    friend Calculator operator*(const Calculator &lh, const Calculator &rh);
    friend Calculator operator/(const Calculator &lh, const Calculator &rh);
    friend istream& operator>>(istream &in, Calculator &rh);
    friend ostream& operator<<(ostream &os, const Calculator &rh);
    friend bool operator<(const Calculator &lh, const Calculator &rh);
    friend bool operator==(const Calculator &lh, const Calculator &rh);

    Calculator operator+=(const Calculator &rh)
    {
        str = str+"+"+rh.str;
        sum = rh.sum + sum;
        return  *this;
    }


private:
    double sum = 0;
    string str;
    map<string, function<double(double, double)>> calu={ { "+", plus<double>() },{ "-",minus<double>() },{ "*",multiplies<double>() },{ "/",divides<double>() } };// /轉(zhuǎn)義字符如何解決啊?為什么不能設(shè)置為static成員毅厚!
    double sum_str(string s);
};

Calculator operator+(const Calculator &lh, const Calculator &rh)
{
    Calculator sum = lh;
    sum += rh;
    return sum;
}
Calculator operator-(const Calculator &lh, const Calculator &rh)
{
    Calculator ret;
    ret.str = lh.str + "-(" + rh.str + ")";
    ret.sum = lh.sum - rh.sum;
    return ret;
}
Calculator operator*(const Calculator &lh, const Calculator &rh)
{
    Calculator ret;
    ret.str = string("(")+lh.str + ")" + "*(" + rh.str + ")";
    ret.sum = lh.sum * rh.sum;
    return ret;
}
Calculator operator/(const Calculator &lh, const Calculator &rh)
{
    Calculator ret;
    if (rh.sum != 0)
    {
        ret.str = string("(") + lh.str + ")" + "/(" + rh.str + ")";
        ret.sum = lh.sum / rh.sum;
        return ret;
    }
    else
        throw invalid_argument(to_string(rh.sum));

}
bool operator<(const Calculator &lh, const Calculator &rh)
{
    if (lh.sum < rh.sum)
        return true;
    else
        return false;
}
bool operator==(const Calculator &lh, const Calculator &rh)
{
    return lh.sum == rh.sum;
}

istream& operator>>(istream &in, Calculator &rh)
{
    in >> rh.str;
    if (in)
        rh.get_sum(rh.str);
    return in;
}
ostream& operator<<(ostream &os,const Calculator &rh)
{
    os << rh.sum;
    return os;
}

double Calculator::sum_str(string s)
{
    //size_t cc = 0;
    //for (auto r : s)      //for范圍需要引用嗎?可以引用浦箱,可以不引用吸耿。引用的時候可以改變字符!

    for (size_t i = 0; i < s.size(); i++)
    {
        if (s[i] == '(')
        {
            for (size_t j = s.size() - 1; j > i; --j)
            {
                if (s[j] == ')')
                {
                    bool flag = true;                   //判斷()內(nèi)部是否還有其他括號
                    for (size_t k = i+1; k < j; ++k)
                    {
                        if (s[k] == '(' || s[k] == ')')
                            flag = false;
                    }
                    if (flag)
                    {
                        string tmp1 = s.substr(i + 1, j - i - 1);
                        auto tmp2 = sum_str(tmp1);
                        s = s.substr(0, i) + to_string(tmp2) + s.substr(j + 1);
                        break;
                    }
                }
            }
        }
    }

    const string format = "+-*/.0123456789";
    for (auto r : s)                        //監(jiān)測是否含有非法字符酷窥?
    {
        if (format.find(r) == string::npos)
        {
            throw invalid_argument(s);
        }
    }

    const string format2 = "+-*/";
    size_t pos = 0;                 //分接字符串s咽安。(只做四則運(yùn)算,不包含括號和正負(fù)E钔啤)
    vector<string> tmp;
    for (size_t i = 0; i < s.size(); ++i)
    {
        if (format2.find(s[i]) != string::npos)
        {
            if (i == pos)                               //如果兩個符號相同位置妆棒,則將數(shù)字置為0.主要應(yīng)用于(-13)計(jì)算!
                tmp.push_back(string(1, '0'));
            else
                tmp.push_back(s.substr(pos, i - pos));
            tmp.push_back(string(1, s[i]));
            pos = i + 1;
        }
    }
    tmp.push_back(s.substr(pos));       //最后一個數(shù)字沸伏!

    size_t length = tmp.size();
    while (length>1)
    {
        for (size_t i = 0; i < length; ++i)
        {
            if (tmp[i] == "*" || tmp[i] == "/")
            {
                auto tmp_0 = stod(tmp[i - 1]);
                auto tmp_1 = stod(tmp[i + 1]);
                if (tmp[i] == "*")
                {
                    tmp_0=calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0*tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                else
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0/tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                for (size_t j = i; j < (length-3); j=j+2)
                {
                    swap(tmp[j], tmp[j + 2]);
                    swap(tmp[j + 1], tmp[j + 3]);
                }
                tmp.pop_back();
                tmp.pop_back();
                i = i-1;            //移動了vector的元素糕珊,所以實(shí)時位置i要更改!
                length = length - 2;
            }
        }

        for (size_t i = 0; i < length; ++i)
        {
            if (tmp[i] == "+" || tmp[i] == "-")
            {
                auto tmp_0 = stod(tmp[i - 1]);
                auto tmp_1 = stod(tmp[i + 1]);
                if (tmp[i] == "+")
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0+tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                else
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0 - tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                for (size_t j = i; j < (length - 3); j = j + 2)
                {
                    swap(tmp[i], tmp[i + 2]);
                    swap(tmp[i + 1], tmp[i + 3]);
                }
                tmp.pop_back();
                tmp.pop_back();
                length = length - 2;
            }
        }
    }
    sum = stod(tmp[0]);
    return sum;
}


double sum(string s)
{
    map<string, function<double(double, double)>> calu = { { "+", plus<double>() },{ "-",minus<double>() },{ "*",multiplies<double>() },{ "/",divides<double>() } };// /轉(zhuǎn)義字符如何解決耙阍恪红选?為什么不能設(shè)置為static成員!
    for (size_t i = 0; i < s.size(); i++)
    {
        if (s[i] == '(')
        {
            for (size_t j = s.size()-1; j > i; --j)
            {
                if (s[j] == ')')
                {
                    string tmp1 = s.substr(i + 1, j - i - 1);
                    auto tmp2 = sum(tmp1);
                    s = s.substr(0, i) + to_string(tmp2)+s.substr(j+1);
                    break;
                }
            }
        }
    }

    const string format = "+-*/.0123456789";
    for (auto r : s)                        //監(jiān)測是否含有非法字符姆另?
    {
        if (format.find(r) == string::npos)
        {
            throw invalid_argument(s);
        }
    }

    const string format2 = "+-*/";
    size_t pos = 0;                 //分接字符串s喇肋。(只做四則運(yùn)算,不包含括號和正負(fù)<7)
    vector<string> tmp;
    for (size_t i = 0; i < s.size(); ++i)
    {
        if (format2.find(s[i]) != string::npos)
        {
            if(i==pos)                              //如果兩個符號相同位置苟蹈,則將數(shù)字置為0.主要應(yīng)用于(-13)計(jì)算!
                tmp.push_back(string(1,'0'));
            else
                tmp.push_back(s.substr(pos, i - pos));
            tmp.push_back(string(1, s[i]));
            pos = i + 1;
        }
    }
    tmp.push_back(s.substr(pos));       //最后一個數(shù)字右核!

    size_t length = tmp.size();
    while (length>1)
    {
        for (size_t i = 0; i < length; ++i)
        {
            if (tmp[i] == "*" || tmp[i] == "/")
            {
                auto tmp_0 = stod(tmp[i - 1]);
                auto tmp_1 = stod(tmp[i + 1]);
                if (tmp[i] == "*")
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0*tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                else
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0/tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                for (size_t j = i; j < (length - 3); j = j + 2)
                {
                    swap(tmp[j], tmp[j + 2]);
                    swap(tmp[j + 1], tmp[j + 3]);
                }
                tmp.pop_back();
                tmp.pop_back();
                i = i - 1;          //移動了vector的元素慧脱,所以實(shí)時位置i要更改!類似于迭代器之于容器贺喝!
                length = length - 2;
            }
        }

        for (size_t i = 0; i < length; ++i)
        {
            if (tmp[i] == "+" || tmp[i] == "-")
            {
                auto tmp_0 = stod(tmp[i - 1]);
                auto tmp_1 = stod(tmp[i + 1]);
                if (tmp[i] == "+")
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0+tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                else
                {
                    tmp_0 = calu[tmp[i]](tmp_0, tmp_1);
                    //tmp_0 = tmp_0 - tmp_1;
                    tmp[i - 1] = to_string(tmp_0);
                }
                for (size_t j = i; j < (length - 3); j = j + 2)
                {
                    swap(tmp[i], tmp[i + 2]);
                    swap(tmp[i + 1], tmp[i + 3]);
                }
                tmp.pop_back();
                tmp.pop_back();
                length = length - 2;
            }
        }
    }
    auto su = stod(tmp[0]);
    return su;
}

int main()
{
    //map<char, function<double(double, double)>> cal = { {'+', plus<double>()},{'-',minus<double>()},{'*',multiplies<double>()},{'/',divides<double>() } };// /轉(zhuǎn)義字符如何解決傲馀浮宗兼?
    /*
    Calculator cc;
    cout<<cc.get_sum(("1+2*3/3-1*2/2"))<<endl;

    Calculator c1("1+4/2*3-1*2");
    Calculator c2("1+4/2*3+1*2");

    cout << c1.get_sum() << "  " << c2.get_sum() << endl;
    */

    Calculator ca1,ca2;
    cin >> ca1 >> ca2;
    //cout << ca1 << " + " << ca2 <<" = "<<ca1+ca2<< endl;

    auto ca3 = ca1 / ca2;
    cout << ca3.get_string() <<" = "<< ca3.get_sum(ca3.get_string())<<endl;

    auto ca4 = ca1 * ca2;
    cout << ca4.get_string() << " = " << ca4.get_sum(ca4.get_string()) << endl;


    cout << sum("(1-(2*(3+2*2)))") << endl;


    system("pause");
    return 0;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市氮采,隨后出現(xiàn)的幾起案子殷绍,更是在濱河造成了極大的恐慌,老刑警劉巖鹊漠,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件主到,死亡現(xiàn)場離奇詭異,居然都是意外死亡躯概,警方通過查閱死者的電腦和手機(jī)登钥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娶靡,“玉大人牧牢,你說我怎么就攤上這事∽硕В” “怎么了塔鳍?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呻此。 經(jīng)常有香客問我轮纫,道長,這世上最難降的妖魔是什么焚鲜? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任蜡感,我火速辦了婚禮,結(jié)果婚禮上恃泪,老公的妹妹穿的比我還像新娘郑兴。我一直安慰自己,他們只是感情好贝乎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布情连。 她就那樣靜靜地躺著,像睡著了一般览效。 火紅的嫁衣襯著肌膚如雪却舀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天锤灿,我揣著相機(jī)與錄音挽拔,去河邊找鬼。 笑死螃诅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的术裸。 我是一名探鬼主播倘是,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼袭艺,長吁一口氣:“原來是場噩夢啊……” “哼搀崭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起猾编,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轰传,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苇羡,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绸吸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年鼻弧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攘轩。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖歼捏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瞳秽,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布练俐,位于F島的核電站冕臭,受9級特大地震影響腺晾,放射性物質(zhì)發(fā)生泄漏辜贵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一鼻由、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗡靡,春花似錦跺撼、人聲如沸讨彼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜜自。三九已至菩貌,卻和暖如春重荠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戈鲁。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诈乒,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓怕磨,卻偏偏與公主長得像消约,于是被迫代替她去往敵國和親肠鲫。 傳聞我的和親對象是個殘疾皇子或粮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 現(xiàn)在在太原,太原是山西省的省會城市被啼,但一路走來并沒有發(fā)現(xiàn)它過多的繁華,有高樓泡挺,有長街,卻看不到想象中的熱鬧娄猫。在這下...
    Harpo閱讀 206評論 0 0
  • 那些日子我近乎瘋狂地祈禱他快點(diǎn)死掉,如果他不死掉那我就要死了媳溺。 不知是不是因?yàn)槲业钠矶\,他越來越虛弱越來越虛弱悬蔽,我...
    0088da845db6閱讀 1,161評論 0 1
  • 如果把身體比做一部工藝精巧,構(gòu)造特殊的機(jī)器录语,最近不知道怎么了,無論如何也打理不好了澎埠。 還記得在22歲以前,這...
    藍(lán)雪夜閱讀 212評論 0 0