Calculator

// 本程序可以实现实数的加减程序四则运算,支持括号运算符,不支持正负符号!另外Calculator类本身进行了加减乘数输入输出的重载!
//

#include "stdafx.h"
#include<iostream>
#include<functional>  //plus等标准库函数对象
#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>() } };// /转义字符如何解决啊?为什么不能设置为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;                   //判断()内部是否还有其他括号
                    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)                        //监测是否含有非法字符?
    {
        if (format.find(r) == string::npos)
        {
            throw invalid_argument(s);
        }
    }

    const string format2 = "+-*/";
    size_t pos = 0;                 //分接字符串s。(只做四则运算,不包含括号和正负!)
    vector<string> tmp;
    for (size_t i = 0; i < s.size(); ++i)
    {
        if (format2.find(s[i]) != string::npos)
        {
            if (i == pos)                               //如果两个符号相同位置,则将数字置为0.主要应用于(-13)计算!
                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));       //最后一个数字!

    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的元素,所以实时位置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>() } };// /转义字符如何解决啊?为什么不能设置为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)                        //监测是否含有非法字符?
    {
        if (format.find(r) == string::npos)
        {
            throw invalid_argument(s);
        }
    }

    const string format2 = "+-*/";
    size_t pos = 0;                 //分接字符串s。(只做四则运算,不包含括号和正负!)
    vector<string> tmp;
    for (size_t i = 0; i < s.size(); ++i)
    {
        if (format2.find(s[i]) != string::npos)
        {
            if(i==pos)                              //如果两个符号相同位置,则将数字置为0.主要应用于(-13)计算!
                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));       //最后一个数字!

    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的元素,所以实时位置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>() } };// /转义字符如何解决啊?
    /*
    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;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,002评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,777评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,341评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,085评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,110评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,868评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,528评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,422评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,938评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,067评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,199评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,877评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,540评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,079评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,192评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,514评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,190评论 2 357

推荐阅读更多精彩内容

  • 现在在太原,太原是山西省的省会城市,但一路走来并没有发现它过多的繁华,有高楼,有长街,却看不到想象中的热闹。在这下...
    Harpo阅读 208评论 0 0
  • 那些日子我近乎疯狂地祈祷他快点死掉,如果他不死掉那我就要死了。 不知是不是因为我的祈祷,他越来越虚弱越来越虚弱,我...
    0088da845db6阅读 1,179评论 0 1
  • 如果把身体比做一部工艺精巧,构造特殊的机器,最近不知道怎么了,无论如何也打理不好了。 还记得在22岁以前,这...
    蓝雪夜阅读 214评论 0 0