[C++基础入门] 计算器

说实话 我之前写过别的类型的计算器
基于lisp语言的那种 这种通用的没写过 但是因为要带几个C++新手入门
考虑再三 感觉还是计算器比较可行 作为入门的话 不会太难 也不太简单
既然是基础入门 计算思路就比较简单 (太复杂的我也不会哈,至少需要查书了)
加减乘除、多层括号、n次方混合运算
加减乘除、多层括号、n次方混合运算
下面贴代码

// Calculator.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
//#define DEBUG
using namespace std;
class CalElement
{
public:
    bool IsValue;//true=value  false=operat
    union
    {
        int operat;
        double value;
    }body;
    //存粹是为了让新手看一下union……这个例子里面内存节省基本上是0 
    //主要是能放在一个结构体里面方便后面使用
public:
    void SetValue(double src)
    {
        IsValue = true;
        body.value = src;
    }
    void SetOperat(int src)
    {
        IsValue = false;
        body.operat = src;
    }
    bool GetData(int &operat_o, double &value_o)
    //留意一下这种传参方式  C++ (&) C#(ref)都有
    {
        if (IsValue) { value_o = body.value; }
        else { operat_o = body.operat; }
        return IsValue;
    }

};
bool IsValue(char src)
{
    if ((src >= 48 && src <= 57) || src == 46)
    {
        return true;
    }
    return false;
}
int GetOperaValue(string src, int &count)
{
    count = 1;
    switch (src[0])
    {
    case 43:return 1; break;// +
    case 45:return 2; break;// -
    case 42:return 3; break;// *
    case 47:return 4; break;// /

    case 40:return 5; break;// (
    case 41:return 6; break;// )

    case 94:return 7; break;// ^
//目前这个版本还没支持xy变量,不过应该很好加
    case 120:return 20; break;// x
    case 88:return 20; break;// X
    case 121:return 21; break;// y
    case 89:return 21; break;// Y
    }
    if (src == "exp")
    {
        count = 3;
        return 100;
    }
    else if (src == "exp(")
    {
        count = 4;
        return 101;
    }
    else
    {
        count = 0;
        return -1;
    }
}
double getValue(string src, int index, int &count)//字符串转double
{
    string temp;
    count = 0;
    for (int i = index; i < src.length(); i++)
    {
        if (IsValue(src[i]))
        {
            temp = temp + src[i];
        }
        else
        {
            break;
        }
    }
    count = temp.length();
    if (count == 0)
    {
        count = 1;
        return 0;
    }
    return stod(temp);
}
int getOperat(string src, int index, int &count)//获得操作符
{
    string temp;
    count = 0;
    for (int i = index; i < src.length(); i++)
    {
        if (IsValue(src[i]))break;
        temp = temp + src[i];
    }
    int t = GetOperaValue(temp, count);
    return t;
}
//按照操作符和数字将输入的字符串给切开  注意传参时候的引用 &
void PreSeprate(string srcStr,vector<CalElement> &calStr)
{
    int i;
    int count = 0;
    int tempOperat;
    for (i = 0; i < srcStr.size();)
    {
        i = i + count;
        tempOperat = getOperat(srcStr, i, count);
        if (tempOperat == -1)
        {
            CalElement temp;
            temp.SetValue(getValue(srcStr, i, count));
            calStr.push_back(temp);
        }
        else
        {
            CalElement temp;
            temp.SetOperat(tempOperat);
            calStr.push_back(temp);
        }
    }
}
//将括号在新的数组里面标示出来,一方面计算括号层数,一方面可以进行括号的预分割
vector<int>GetBrackets(vector<CalElement>src, int &count)
{
    count = 0;
    vector<int>state;
    int t = 0;
    for (int i = 0; i < src.size(); i++)
    {
        if (!src[i].IsValue)
        {
            if (src[i].body.operat == 5)
            {
                t++;
                if (t > count) { count = t; }
                state.push_back(t);
            }
            else if (src[i].body.operat == 6)
            {
                t--;
                state.push_back(t);
            }
            else { state.push_back(t); }
        }
        else { state.push_back(t); }
    }
    return state;
}
double SampleCalculate(vector<CalElement>cal)
//没有括号的基本计算  
//这里面的vector insert我用的貌似很挫,感冒中,不想了。有人会的话在留言里教我一下
{
    CalElement tempElement;
    double temp;
    //符号首位
    if (!cal[0].IsValue)
    {
        if (cal[0].body.operat == 2)
        {
            temp = cal[1].body.value *(-1);
            //CalElement tempElement;
            tempElement.SetValue(temp);
            cal.erase(cal.begin(), cal.begin() + 2);
            cal.insert(cal.begin(), tempElement);
        }
        else if (cal[0].body.operat == 1)
        {
            cal.erase(cal.begin());
        }
    }
    //幂指数
    for (int i = 0; i < cal.size(); i++)
    {
        if (!cal[i].IsValue && cal[i].body.operat==7)
        {
            temp = pow(cal[i - 1].body.value, cal[i + 1].body.value);
            tempElement.SetValue(temp);
            cal.erase(cal.begin() + i - 1, cal.begin() + i + 2);
            if (cal.size() == 0) { return temp; }
            else if (cal.size() <= i - 1)
            {
                cal.push_back(tempElement);
            }
            else { cal.insert(cal.begin() + i - 1, tempElement); }
            i--;
        }
    }
    //乘除法   
    for (int i = 0; i < cal.size(); i++)
    {
        if (!cal[i].IsValue)
        {
            switch (cal[i].body.operat)
            {
            case 3:
                temp = cal[i - 1].body.value * cal[i + 1].body.value;
                tempElement.SetValue(temp);
                cal.erase(cal.begin() + i - 1, cal.begin() + i + 2);
                if (cal.size() == 0) { return temp; }
                else if (cal.size() <= i - 1)
                {
                    cal.push_back(tempElement);
                }
                else { cal.insert(cal.begin() + i - 1, tempElement); }
                i--;
                break;
            case 4:
                if (cal[i + 1].body.value != 0)
                {
                    temp = cal[i - 1].body.value / cal[i + 1].body.value;
                }
                else
                {
                    temp = double(LONG_MAX);
                }
                tempElement.SetValue(temp);
                cal.erase(cal.begin() + i - 1, cal.begin() + i + 2);
                if (cal.size() == 0) { return temp; }
                else if (cal.size() <= i - 1)
                {
                    cal.push_back(tempElement);
                }
                else { cal.insert(cal.begin() + i - 1, tempElement); }
                i--;
                break;
            }
        }
    }
    //加减法
    for (int t = 0; t < cal.size(); t++)
    {
        if (!cal[t].IsValue)
        {
            switch (cal[t].body.operat)
            {
            case 1:
                temp = cal[t - 1].body.value + cal[t + 1].body.value;
                tempElement.SetValue(temp);
                cal.erase(cal.begin() + t - 1, cal.begin() + t + 2);
                if (cal.size() == 0) { return temp; }
                else if (cal.size() <= t - 1)
                {
                    cal.push_back(tempElement);
                }
                else { cal.insert(cal.begin() + t - 1, tempElement); }
                t--;
                break;
            case 2:
                temp = cal[t - 1].body.value - cal[t + 1].body.value;
                tempElement.SetValue(temp);
                cal.erase(cal.begin() + t - 1, cal.begin() + t + 2);
                if (cal.size() == 0) { return temp; }
                else if (cal.size() <= t - 1)
                {
                    cal.push_back(tempElement);
                }
                else { cal.insert(cal.begin() + t - 1, tempElement); }
                t--;
                break;
            }
        }
    }
    return cal[0].body.value;
}
//总的递归调用的计算函数  说递归效率低的可以把这个按照maxLayer转成循环来写  
//懒得动  而且 让新学的同学了解一下递归  毕竟循环(迭代)都是会的不是
double Calculate(vector<CalElement>cal)
{
    int maxLayer;
    vector<int>Brackets = GetBrackets(cal, maxLayer);
    if (maxLayer == 0)
    {
        return SampleCalculate(cal);
    }
    else
    {
        int beginIndex = 0;
        int endIndex = 0;
        bool find = false;
        vector<CalElement>tempSimple;
        for (int i = 0; i < Brackets.size(); i++)
        {
            if (Brackets[i] == maxLayer)
            {
                if (find) { tempSimple.push_back(cal[i]); }
                else { beginIndex = i; }
                find = true;
            }
            if (find && Brackets[i] == maxLayer - 1)
            {
                endIndex = i;
                find = false;
                break;
            }
        }
        cal.erase(cal.begin() + beginIndex, cal.begin() + endIndex + 1);
        CalElement tempElement;
        tempElement.SetValue(Calculate(tempSimple));
        if (cal.size() < beginIndex)
        {
            cal.push_back(tempElement);
        }
        else { cal.insert(cal.begin() + beginIndex, tempElement); }
        return Calculate(cal);//递归调用
    }
}
//主函数调用
int main()
{
    //输入
    string srcStr;
    std::cin >> srcStr;
    //预处理
    vector<CalElement>calStr;
    PreSeprate(srcStr, calStr);
    //计算并输出
    cout << Calculate(calStr) << endl;
    cin >> srcStr;
    return 0;
}

其实回想一下流程很简单的,对吧。
有兴趣的可以把xy变量加进去。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值