精华内容
下载资源
问答
  • c++实现计算器界面
    2021-10-01 00:26:56

    数据结构课后的实验作业

    主要模块为:

    转换模块:将中缀表达式转换为后缀表达式;
    运算模块:对后缀表达式进行运算,得到最终运算结果。

    运行环境为Ubuntu,g++版本为9.3.0

    运算范围只限在32位整形以内
    运算符包括了加减乘除、取余和幂次
    可以进一步扩展的有:增加实数范围的运算;扩展运算符,例如根号等;实现图形操作界面

    使用了GNU的开源readline库来实现比较人性化的行编辑器功能,具体的操作在这篇博客

    源码:

    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <string>
    #include <stack>
    #include <memory>
    #include <utility>
    #include <readline/readline.h>
    #include <readline/history.h>
    #include <cmath>
    
    using namespace std;
    
    bool Error(false); //全局变量判断表达式是否非法
    
    void Execute(void);
    string Transform(const string&);
    int weight(const char); //判断算符的权重
    int calculate(const string&);
    void calculate_operater(const string&, stack<int>&);
    
    int main(void)
    {
        Execute();
    
        return 0;
    }
    
    void Execute(void)
    {
        string Aline;
        int num;
    
        //命令行历史功能初始化
        using_history();
    
        while(true)
        {
            //读取一行中缀表达式
            Aline = readline("enter expression, or q to quit: ");
            //转化为后缀表达式
            Aline = Transform(Aline);
    
            if(Aline == "exit")
            {
                cout << "invalid charactor or syntax error!" << endl;
                continue;
            }
    
            if(Aline == "")
            {
                continue;
            }
    
            //处理后缀表达式,得到最终运算结果
            num = calculate(Aline);
    
            if(Error)
            {
                cout << "invalid charactor or syntax error!" << endl;
                Error = false;
                continue;
            }
    
            cout << num << endl;
        }
    
        return;
    }
    
    string Transform(const string& line)
    {
        if(line == "q")
        {
            exit(1);
        }
    
        //将这个字符串添加到命令行历史中
        add_history(line.c_str());
    
        stack<char> Stack_charactors;
        string ret;
        string num;
        string Aline;
        bool flag(true);
        
        if(line[0] == '-')
        {
            Aline += '0';
        }
    
        Aline += line + "#";
    
        //cout << Aline << endl;
    
        //解析字符串
        for(auto itc = Aline.cbegin(),
            ite = Aline.cend(); ite!=itc; ++itc)
        {
            //空格直接跳过
            if(*itc == ' ')
            {
                continue;
            }
            //如果是数字
            else if(*itc >= '0' && *itc <= '9')
            {
                num += *itc;
                flag = true;
            }
            else
            {
                if(weight(*itc) == -1)
                {
                    return "exit";
                }
    
                if(flag == true)
                {
                    ret = ret + num + " ";
                    num = "";
                }
    
                if(Stack_charactors.empty() || (*itc == '('))
                {
                    Stack_charactors.push(*itc);
                }
                else if(*itc == ')')
                {
                    while(Stack_charactors.top() != '(')
                    {
                        ret = ret + Stack_charactors.top() + " ";
                        Stack_charactors.pop();
    
                        if(Stack_charactors.empty())
                        {
                            return "exit";
                        }
                    }
                    Stack_charactors.pop();
                }
                else
                {
                    while((!Stack_charactors.empty()) && (weight(*itc) <= weight(Stack_charactors.top())))
                    {
                        ret  = ret + Stack_charactors.top() + " ";
                        Stack_charactors.pop();
                    }
    
                    Stack_charactors.push(*itc);
                }
    
                flag = false;
            }
        }
    
        ret.resize(ret.size()-1);
        return ret;
    }
    
    int weight(const char sign)
    {
        switch(sign)
        {
            case '#':
            {
                return 0;
            }
            case '+':
            {
                return 1;
            }
            case '-':
            {
                return 1;
            }
            case '*':
            {
                return 2;
            }
            case '/':
            {
                return 2;
            }
            case '%':
            {
                return 2;
            }
            case '^':
            {
                return 3;
            }
            case '(':
            {
                return 0;
            }
            case ')':
            {
                return 0;
            }
            default:
            {
                return -1;
            }
        }
    }
    
    int calculate(const string& expression)
    {
        int ret;
        istringstream is(expression);
        string item;
        stack<int> Stack_nums;
    
        while(is >> item)
        {
            if((item=="+") || (item=="-") || (item=="*") || (item=="/") || (item=="%") || (item=="^"))
            {
                calculate_operater(item, Stack_nums);
    
                if(Error)
                {
                    return 0;
                }
            }
            else
            {
                Stack_nums.push(atoi(item.c_str()));
            }
        }
    
        return Stack_nums.top();
    }
    
    void calculate_operater(const string& sign, stack<int>& Stack_nums)
    {
        int t1, t2;
    
        if(sign == "+")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(t1 + t2);
        }
        else if(sign == "-")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(t1 - t2);
        }
        else if(sign == "*")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(t1 * t2);
        }
        else if(sign == "/")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(t1 / t2);
        }
        else if(sign == "%")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(t1 % t2);
        }
        else if(sign == "^")
        {
            if(Stack_nums.size() < 2)
            {
                Error = true;
                return;
            }
    
            t2 = Stack_nums.top();
            Stack_nums.pop();
            t1 = Stack_nums.top();
            Stack_nums.pop();
    
            Stack_nums.push(pow(t1, t2));
        }
    
        return;
    }
    
    更多相关内容
  • 两种用C++实现计算器界面设计的工程,用qt-creator编辑,一种是直接声明QWidget变量的方式,一种是继承QWidget的方式。
  • C++图形界面计算器

    热门讨论 2012-12-22 21:42:22
    C++语言 编写的带图形界面计算器,能实现加减乘除和清零功能。代码清晰,适合初学者学习。
  • C++实现计算器

    千次阅读 2020-11-30 21:22:06
    2、安装了QT(虽然我不知道怎么用),用QT来实现计算器界面设计。3、从b站看了相关的QT课程,为下一步实现第一个属于自己的作品做好铺垫。 今天看的内容仅仅了解一些计算方法的思路和使用QT的基本知识。明天还得再...

    day-1
    今天主要做了3件事。1、了解了实现算数表达式求值底层逻辑的三种方法:(a)用栈和队列分别存储运算符和操作数;(b)双栈算符优先级法 (c)用二叉树求解后缀表达式的值。个人感觉第二种方法思路比较好,操作性强。2、安装了QT(虽然我不知道怎么用),用QT来实现计算器的界面设计。3、从b站看了相关的QT课程,为下一步实现第一个属于自己的作品做好铺垫。
    今天看的内容仅仅了解一些计算方法的思路和使用QT的基本知识。明天还得再看看相关视屏,争取开始写实现算数表达式的代码
    day-2
    今天开始了计算器的界面设计,完成了基本按钮的设置,结果如图所示
    在这里插入图片描述
    相关的C++头文件
    #ifndef WIDGET_H
    #define WIDGET_H

    enum BtnType{
    Num,//数字
    Op,//操作符
    Dot,//点
    Back,//退格
    Equl,//等于
    Clear//清除
    };
    #include

    namespace Ui {
    class Widget;
    }

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

    private:
    Ui::Widget *ui;
    QString num1;//操作数1
    QString num2;//操作数2
    QString op;//操作符
    };

    #endif // WIDGET_H
    用枚举对按钮进行说明。没有“( )”操作符是因为这是我初步对计算器的设计,后面还要添加相应的模块
    主要收获:
    学会使用QT中的pushbutton
    在这里插入图片描述
    个人感觉还是很好用的,首先将需要使用的按钮创建出来,然后调节按钮的大小。
    在这里插入图片描述
    下面就是对按钮的精细调节
    在这里插入图片描述
    接下来就是要实现按钮的功能,在头文件中定义按钮。用枚举的方式实现按钮的分类。
    在这里插入图片描述
    具体的算数运算明天实现,后续内容明天更新,,,,,
    day-03
    今天实现了简单的四则运算,结果如下:
    在这里插入图片描述在这里插入图片描述

    #include "Widget.h"
    #include "ui_widget.h"
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        //数字按钮绑定
        connect(ui->Num0,&QPushButton::clicked,[this](){onclicked(Num,"0");});
        connect(ui->Num1,&QPushButton::clicked,[this](){onclicked(Num,"1");});
        connect(ui->Num2,&QPushButton::clicked,[this](){onclicked(Num,"2");});
        connect(ui->Num3,&QPushButton::clicked,[this](){onclicked(Num,"3");});
        connect(ui->Num4,&QPushButton::clicked,[this](){onclicked(Num,"4");});
        connect(ui->Num5,&QPushButton::clicked,[this](){onclicked(Num,"5");});
        connect(ui->Num6,&QPushButton::clicked,[this](){onclicked(Num,"6");});
        connect(ui->Num7,&QPushButton::clicked,[this](){onclicked(Num,"7");});
        connect(ui->Num8,&QPushButton::clicked,[this](){onclicked(Num,"8");});
        connect(ui->Num9,&QPushButton::clicked,[this](){onclicked(Num,"9");});
        //运算符按钮绑定
        connect(ui->Sum,&QPushButton::clicked,[this](){onclicked(Op,"+");});
        connect(ui->Sub,&QPushButton::clicked,[this](){onclicked(Op,"-");});
        connect(ui->Mul,&QPushButton::clicked,[this](){onclicked(Op,"*");});
        connect(ui->Div,&QPushButton::clicked,[this](){onclicked(Op,"/");});
        //其他
         connect(ui->Back,&QPushButton::clicked,[this](){onclicked(Back,"back");});
         connect(ui->Clear,&QPushButton::clicked,[this](){onclicked(Clear,"clear");});
         connect(ui->Dot,&QPushButton::clicked,[this](){onclicked(Dot,".");});
         connect(ui->Equ,&QPushButton::clicked,[this](){onclicked(Equ,"=");});
    }
    
    Widget::~Widget()
    
    {
        delete ui;
    }
    void Widget::onclicked(BtnType _type,QString _btn){
        switch(_type){      //按钮类型
        case Num:
            {
            if(mOp.isEmpty())//如果操作数为空,则为操作数一
            {
                mNum1+=_btn;
            }
            else //如果操作数不空,则为操作数二
            {
                mNum2+=_btn;
            }
             break;
            }
         case Op://运算符
            {
              mOp=_btn;
              break;
            }
         case Dot:
            {
            if(mOp.isEmpty())
            {
                //操作数一的点
                if(!mNum1.isEmpty() && !mNum1.contains("."))//操作数1非空且不包含"."
                {
                    mNum1+=_btn;
                }
    
            }
            else
            {
                if(!mNum2.isEmpty() && !mNum2.contains("."))//操作数2非空且不包含"."
                {
                    mNum2+=_btn;
                }
            }
            break;
            }
        case Back:
            { if(!mNum1.isEmpty()&&!mOp.isEmpty()&&!mNum2.isEmpty())//删除操作数二
                {
                mNum2.chop(1);//尾部删除,删除指定字符个数
                }
            else if (!mNum1.isEmpty()&&!mOp.isEmpty())
            {
                mOp.chop(1);
            }
            else if (!mNum1.isEmpty()) {
                mNum1.chop(1);
            }
            break;
                }
         case Clear://清除
           {
            mNum1.clear();
            mNum2.clear();
            mOp.clear();
           }
         case Equ://等于
           {
            if(mNum1.isEmpty()||mNum2.isEmpty()||mOp.isEmpty())
                return;
            double num1=mNum1.toDouble();//将字符串转化为小数
            double num2=mNum2.toDouble();//将字符串转化为小数
            double result=0.0;
            if(mOp=="+")
            {
             result=num1+num2;
            }
            else if (mOp=="-")
            {
              result=num1-num2;
            }
            else if (mOp=="*")
            {
              result=num1*num2;
            }
            else if (mOp=="/")
            {
                if(num2==0.0){
                   ui->lineEdit->setText("除数不能为0");
                 return;
                }
               else
                {
                    result=num1/num2;
                }
            }
            ui->lineEdit->setText(QString::number(result));//QString::number 数字转字符串
            mNum1.clear();
            mNum2.clear();
            mOp.clear();
            return;
           }
        }
        ui->lineEdit->setText(mNum1+mOp+mNum2);}
    

    ##这里暂时没有加入计算器扩号运算,明天会继续优化一下。
    主要掌握了一些类的函数,和字符串转换函数。逻辑实现主要靠switch实现,结构比较清晰;在涉及到除法的时候需要分类。
    然后主要就是对按钮进行了绑定,通过lineEdit实现输出
    day 04
    今天主要处理操作符的优先级问题,主要难点在于将中缀表达式正确的转化为后缀表达式,然后按照优先级出栈,再将结果入栈,最后出栈。
    主要代码如下:

     void Exp(const char *S,char OPS[],int &len)//将中缀表达式转变为后缀表达式
        {
            QStack<char> OPE;//符号栈
            unsigned int i,j=0;
            unsigned int tmp = strlen(S);
            for (i = 0; i < tmp; i++)
            {
                switch (S[i])
                {
                case'+':
                    if(OPE.isEmpty())//栈为空
                     OPE.push(S[i]);
                    else if (OPE.top() == '*' || OPE.top() == '/')
                    {
                        OPS[j++] = OPE.pop();//弹出比'+'运算符优先级高和相等的运算符,依次加入后缀表达式
                        i--;
                    }
                    else
                        OPE.push(S[i]);
                    break;
                case'-':
                    if(i!=0 && '('!=S[i-1])//正数
                    {
                     if(OPE.isEmpty())//栈为空
                          OPE.push(S[i]);
                      else if (OPE.top() == '*' || OPE.top() == '/')//弹出比'-'运算符优先级高和相等的运算符,依次加入后缀表达式
                     {
                       OPS[j++] = OPE.pop();
                       i--;
                     }
                      else
                        OPE.push(S[i]);
                    }
                    else//负数
                    {
                        while ((S[i] >= '0'&&S[i] <= '9' ) || S[i] == '.' || ('-'==S[i]&&(S[i-1]<'0'||S[i-1]>'9')))
                        {
                            OPS[j++] = S[i];
                            if('-'==S[i])
                              OPS[j++]='@';
                            i++;
                        }
                        i--;
                        OPS[j++] = '#';  //数字中的间隔符
                    }
                    break;
                case'*':
                    if(OPE.isEmpty())//栈为空
                       OPE.push(S[i]);
                    else
                        OPE.push(S[i]);
                    break;
                case'/':
                    if(OPE.isEmpty())//栈为空
                       OPE.push(S[i]);
    
                    else
                        OPE.push(S[i]);
                    break;
                case'(':
                    OPE.push(S[i]);
                    break;
                case')':
                    while (OPE.top() != '(')//依次把栈中的运算符加入后缀表达式并将其出栈
                    {
                        OPS[j++] = OPE.pop();
                    }
                    OPE.pop();//从栈中弹出'('
                    break;
                default:
                    while ((S[i] >= '0'&&S[i] <= '9') || S[i] == '.' || ('-'==S[i]&&S[i-1]<'0'&&S[i-1]>'9'))
                    {
    
                        OPS[j++] = S[i];
    
                        i++;
                    }
                    i--;
                    OPS[j++] = '#';  //数字中的间隔符
                    break;
                }
            }
            while (!OPE.isEmpty())
            {
                OPS[j++] = OPE.pop();
            }
            len = j;
        }
    
        void PostExp(char B[], int len, double &result,bool &flag)//用后缀表达式计算结果
        {
            int i;
            double a;
            double b;
            double c;
            QStack<double>SZ;
            for (i = 0; i < len; i++)
            {
                switch (B[i])
                {
                   case'+':
                   {
                    a = SZ.pop();
                    b = SZ.pop();
                    c = b + a;
                    SZ.push(c);
                    }
                       break;
                   case'-':
                   {
                    if('@'!=B[i+1])
                    {
                    a = SZ.pop();
                    b = SZ.pop();
                    c = b - a;
                    SZ.push(c);
                    }
                    else
                    {
                        int jx = 0;
                        double dx;
                        char *stx = new char[10];
                        while (B[i] != '#')
                        {
                           if('@'!=B[i])
                            stx[jx++] = B[i];
                            i++;
    
                        }
                        dx = atof(stx);//把字符串转换成浮点数
                        SZ.push(dx);
                        delete stx;
                    }
                   }
                       break;
                   case'*':
                   {
                    a = SZ.pop();
                    b = SZ.pop();
                    c = b*a;
                    SZ.push(c);
                   }
                       break;
                   case'/':
                   {
                      a = SZ.pop();
                      b = SZ.pop();
                      if (a == 0)
                      {
                          flag = false;
                          return;
                      }
                      c = b / a;
                      SZ.push(c);
                   }
                       break;
                   default:
                       int j = 0;
                       double d;
                       char *st = new char[10];
                       while (B[i] != '#')
                       {
                           st[j++] = B[i];
                           i++;
                       }
                       d = atof(st);//把字符串转换成浮点数
                       SZ.push(d);
                       delete st;
                       break;
                }
            }
            result=SZ.top();
        }`
    

    运行结果:
    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • 一个强大的计算器,集合了各种函数,就是界面不漂亮。
  • 简易计算器c++实现

    千次阅读 2022-04-03 11:00:22
    1 开发环境 vs2019 easyx头文件 2 设计思路 1 设置窗口大小以及缓冲区大小 ...实现了一部分计算器界面上的功能 4 未实现功能 1 大数计算 2 部分界面上功能 3 历史记录 代码: erash.h: #pr.

    1 开发环境

    vs2019 easyx头文件

    easyx虽然是老旧的Graphics.h的封装与拓展,在现代适用性并不高,但是其对于新手的友好,以及满足初学者的图像需求

    2 设计思路

    1 设置窗口大小以及缓冲区大小

    2 绘制整体界面

    3 获取鼠标输入并且高亮标注

    4 采用大数计算加减乘除 平方 开方

    5 采用字符串保存数字字符

    6 清空输入 输出区字符

    7 其他功能 回退,清空,等于

    3开发流程

    实现界面

    实现界面的操作反馈

    实现了普通的数字计算功能

    实现了一部分计算器界面上的功能

    1 关于栈实现表达式计算的部分:

    使用c++的头文件 #include<stack> 来实现栈的使用操作,无需自己定义栈结构。

    首先定义一个数字栈与一个操作符栈 将#压入操作符栈以便结尾操作。

    然后开始读取输入的用来记录表达式的字符串,如果使用isdigit() 函数发现数字,就继续用该 函数来将这一串数字全部读取到数字栈中 直到结束或操作符。

    如果读取到的是操作符 那么会进行一下判定:

    1 优先级大于操作符栈顶优先级 该操作符入栈

    2 优先级小于或等于操作符栈顶优先级 持续拿出操作符栈顶以及数字栈顶进行运算,直至 该操作符优先级大于操作符栈顶优先级,最后 该运算符与运算结果入栈。

    当读取字符串完成后,会进行扫尾工作:

    重复拿出操作符栈顶以及数字栈顶 进行运算 将运算结果入栈 直到栈顶为#为止。

    最后 返回数字栈栈顶元素。

    2 关于界面以及界面事件的实现:

    使用easyx自带的rectangle()来绘制矩形 outtextxy()来输出文字 line()绘制线条

    在主循环函数act()中读取鼠标信息 如果鼠标进入目标区域,则绘制一个较小的青色矩形来实现反馈,在鼠标离开后绘制同等位置与大小的背景色矩形将其掩盖。

    如果鼠标在目标区域点击,则会将字符串中添加点击的数字或运算符,并且通过之前的栈来实现表达式计算并立马输出在输出框中。在此之前,会对将要输送的栈的字符串进行检查,如果最后一位是表达式则会将最后一位删除,重复进行。

    如果点击的是‘=’,则会删除输入框的所有字符,并且将表达式得出的结果送入至用来记录表达式的字符串中

    4 未实现功能

    1 大数计算

    2 部分界面上功能

    3 历史记录

    下载以及运行:

    https://gitee.com/tang-zhihao2/c-calculator.git

    EasyX Graphics Library for C++

    5 关于如何将程序打包为exe文件

    在拓展中找到并下载该插件。

     右键解决方案->添加->新建项目

    建立setup project项目,复制好之前程序项目的目录,右键Application Foluder->Add->文件,粘贴刚刚复制的目录,然后右键Application Foluder->Add->项目输出,然后右键这个主输出->Create Shortcut to 主输出…创建一个快捷方式。然后将其放入User’s Desktop里,最后重新生成解决方案,并且点击安装一路走,结束后可得到exe文件。

    展开全文
  • (1)问题描述 设计一个简单的一元稀疏多项式计算器。 (2)基本要求 一个简单的一元稀疏多项式计算器...计算器仿真界面。 (3)数据结构及算法分析 可用带表头结点的单链表存储多项式,多项式的项数存放在头结点中。
  • 自己学习C++的时候写的项目: 基于C++计算器界面
  • C++语言 编写的带图形界面计算器,能实现加减乘除和清零功能。代码清晰,适合初学者学习。
  • C++数据结构实习。使用双栈实现计算器计算功能,除基本运算外,支持幂运算,开方运算和三角函数运算。原创,如有问题请联系我
  • C++计算器实现 ——(完整功能实现、设计分析)

    万次阅读 多人点赞 2021-01-07 22:58:47
    基于标准C++计算器实现。 一、需求实现 1、实现功能: 支持运算符:+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( ) [ ] { } 支持数据类型:正负数、小数。 2、实现方法 符号...

    基于标准C++的计算器实现。

    一、需求实现

    1、实现功能:

    支持运算符:+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( ) [ ] { }

    支持数据类型:正负数、小数。

    2、实现方法

    符号优先级处理方法:符号等级制

    运算表达式处理方法:后缀表达式法

    后缀表达式转换及计算辅助方法:符号栈、数字栈

    二、设计实现

    总体设计:

    计算器类

    //计算器类
    class Calculator
    {
    public:
    	Calculator();
    	void getFormat();					//表达式自定义标准格式化
    	int getPrior(char c);				//获取算术符号优先级
    	void getPostfix();					//后缀表达式转换
    	void calResult();					//计算结果
    	void calculate();					//计算方法
    	double getResult();					//获取结果
    
    	string operatorSym;					//运算符号
    	string infix;						//表达式缓存
    
    private:
    	vector<string> postfix;				//后缀表达式向量
    	stack<char> symStack;				//符号栈
    	stack<double> figStack;				//数字栈
    	string stdInfix;					//自定义标准格式化表达式
    	double result;						//最终计算结果
    };
    

    1、运算优先级功能实现

    (1)运算符等级

    声明为枚举常量(在整个类中恒定),便于数据管理、数据与程序分离。

    //算术符号优先权等级
    enum PRIO_LV {
    	PRIO_LV0 = 0,
    	PRIO_LV1 = 1,
    	PRIO_LV2 = 2,
    	PRIO_LV3 = 3,
    	PRIO_LV4 = 4,
    };
    
    (2)运算符优先级获取

    用于运算优先级比较的依据。

    //获取算术符号优先级
    int Calculator::getPrior(char c) {
    
    	if (c == '+' || c == '-') {
    		return PRIO_LV1;
    	}
    	else if (c == '*' || c == '/') {
    		return PRIO_LV2;
    	}
    	else if (c == '%' || c == '^') {
    		return PRIO_LV3;
    	}
    	else if (c == '!') {
    		return PRIO_LV4;
    	}
    	else {
    		return PRIO_LV0;
    	}
    	//else { cout << c << 非法符号! << endl; }
    }
    

    2、绝对值符号奇偶性实现

    //绝对值符号个数的奇偶性
    enum ABS_ODEVITY {
    	ABS_ODD = 1,
    	ABS_EVEN = 2,
    };
    

    3、正负数运算实现

    
    //表达式自定义标准格式化
    void Calculator::getFormat() {
    
    	stdInfix = infix;
    
    	//实现正负数
    	//for (int i = 0; i < stdInfix.length(); i++) {			//string下标调用运算符时可能会导致类型溢出
    	for (size_t i = 0; i < stdInfix.size(); i++) {			//string.size()返回size_type类型,避免下标运算时的类型溢出
    		if (stdInfix[i] == '-' || stdInfix[i] == '+') {		//-x转换为0-x,+x转化为0+x
    			if (i == 0) {
    				stdInfix.insert(0, 1, '0');
    			}
    			else if (stdInfix[i - 1] == '(') {
    				stdInfix.insert(i, 1, '0');
    			}
    		}
    	}
    }
    

    4、后缀表达式转换

    要直接对表达式求值,首先要能够正确解释表达式,或者翻译成能正确求值的一个机器指令序列,以便计算机的处理执行。因此有前缀表达式和后缀表达式方法,此处采用较为广泛的后缀表达式方法。

    //后缀表达式转换
    void Calculator::getPostfix() {
    
    	int absNumeber = ABS_ODD;				//绝对值符号个数的奇偶性
    	string tmp;
    
    	//for (int i = 0; i < stdInfix.length(); i++) {
    	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
    		tmp = "";
    		switch (stdInfix[i]) {
    		case '+':
    		case '-':
    		case '*':
    		case '/':
    		case '%':
    		case '^':
    		case '!':
    			if (symStack.empty() || symStack.top() == '(' || symStack.top() == '[' || symStack.top() == '{' || (symStack.top() == '|' && absNumeber == ABS_ODD)) {
    				symStack.push(stdInfix[i]);
    			}
    			else {
    				while (!symStack.empty() && (getPrior(symStack.top()) >= getPrior(stdInfix[i]))) {
    					tmp += symStack.top();
    					postfix.push_back(tmp);
    					symStack.pop();
    					tmp = "";
    				}
    				symStack.push(stdInfix[i]);
    			}
    			break;
    		case '|':
    			if (absNumeber == ABS_ODD) {
    				symStack.push(stdInfix[i]);
    				absNumeber = ABS_EVEN;
    			}
    			else{
    				while (!symStack.empty() && symStack.top() != '|') {
    					tmp += symStack.top();
    					postfix.push_back(tmp);
    					symStack.pop();
    					tmp = "";
    				}
    				if (!symStack.empty() && symStack.top() == '|') {
    					tmp += symStack.top();
    					postfix.push_back(tmp);						//左绝对值符号'|'加入后缀表达式,用于绝对值的检测计算
    					symStack.pop();
    					absNumeber = ABS_ODD;
    				}
    			}
    			break;
    		case '(':
    		case '[':
    		case '{':
    			symStack.push(stdInfix[i]);
    			break;
    		case ')':
    			while (!symStack.empty() && symStack.top() != '(') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '(') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		case ']':
    			while (!symStack.empty() && symStack.top() != '[') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '[') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		case '}':
    			while (!symStack.empty() && symStack.top() != '{') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '{') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		default:
    			if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) {
    				tmp += stdInfix[i];
    				while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) {		//小数处理
    
    					tmp += stdInfix[i + 1];			//是连续的数字,则追加
    					i++;
    				}
    				if (tmp[tmp.length() - 1] == '.') {
    					tmp += '0';						//将x.做x.0处理
    				}
    				postfix.push_back(tmp);
    			}
    			break;
    		}//end switch
    	}//end for
    
    	//if(!symStack.empty()) {
    	while (!symStack.empty()) {						//将栈中剩余符号加入后缀表达式
    		tmp = "";
    		tmp += symStack.top();
    		postfix.push_back(tmp);
    		symStack.pop();
    	}
    }
    

    5、计算后缀表达式

    计算后缀表达式,得到最终计算结果,将结果传递到计算器类的result属性。

    //计算
    void Calculator::calResult() {
    
    	string tmp;
    	double number = 0;
    	double op1 = 0, op2 = 0;
    
    	for (int i = 0; i < postfix.size(); i++) {
    		tmp = postfix[i];
    		if (tmp[0] >= '0' && tmp[0] <= '9') {
    			number = atof(tmp.c_str());
    			figStack.push(number);
    		}
    		else if (postfix[i] == "+") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1 + op2);
    		}
    		else if (postfix[i] == "-") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1 - op2);
    		}
    		else if (postfix[i] == "*") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1* op2);
    		}
    		else if (postfix[i] == "/") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop(); 
    			}
    			if (op2 != 0) {
    				///除数不为0,未做处理,默认
    			}
    			figStack.push(op1 / op2);
    		}
    		else if (postfix[i] == "%") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(fmod(op1, op2));			//可进行小数求余
    		}
    		else if (postfix[i] == "^") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(pow(op1, op2));
    		}
    		else if (postfix[i] == "|") {
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(abs(op1));
    		}
    		else if (postfix[i] == "!") {
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			if (op1 > 0) {
    				//阶乘数应大于;为小数时(转化为整数求阶)
    				double factorial = 1;
    				for (int i = 1; i <= op1; ++i)
    				{
    					factorial *= i;
    				}
    				op1 = factorial;
    			}
    			figStack.push(op1);
    		}
    	}//end for
    	if (!figStack.empty()) {
    		result = figStack.top();
    	}
    }
    

    6、对象的外部调用方法

    //计算方法
    void Calculator::calculate() {
    
    	getFormat();				//表达式自定义标准格式化
    	getPostfix();				//后缀表达式转换
    	calResult();				//获取算术结果
    }
    
    //获取结果
    double Calculator::getResult() {
    	return result;
    }
    

    三、完整代码

    Calculator.h: 头文件

    //Calculator.h: 头文件
    #include <stack>
    #include <vector>
    #include <string>
    using namespace std;
    
    //计算器类
    class Calculator
    {
    public:
    	Calculator();
    	void getFormat();					//表达式自定义标准格式化
    	int getPrior(char c);				//获取算术符号优先级
    	void getPostfix();					//后缀表达式转换
    	void calResult();					//计算后缀表达式
    	void calculate();					//计算方法
    	double getResult();					//获取结果
    
    	string operatorSym;					//运算符号
    	string infix;						//表达式缓存
    
    private:
    	vector<string> postfix;				//后缀表达式向量
    	stack<char> symStack;				//符号栈
    	stack<double> figStack;				//数字栈
    	string stdInfix;					//自定义标准格式化表达式
    	double result;						//最终计算结果
    };
    

    Calculator.cpp: 实现文件

    //Calculator.cpp: 实现文件
    #include <stack>
    #include <vector>
    #include <string>
    #include <cmath>
    using namespace std;
    
    //绝对值符号个数的奇偶性
    enum ABS_ODEVITY {
    	ABS_ODD = 1,
    	ABS_EVEN = 2,
    };
    
    //算术符号优先权等级
    enum PRIO_LV {
    	PRIO_LV0 = 0,
    	PRIO_LV1 = 1,
    	PRIO_LV2 = 2,
    	PRIO_LV3 = 3,
    	PRIO_LV4 = 4,
    };
    
    Calculator::Calculator() {				//构造函数,初始化成员变量
    
    	operatorSym = "支持运算符:+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( ) [ ] { }";
    	result = 0.0;
    }
    
    
    //表达式自定义标准格式化
    void Calculator::getFormat() {
    
    	stdInfix = infix;
    
    	//实现正负数
    	//for (int i = 0; i < stdInfix.length(); i++) {					//string下标调用运算符时可能会导致类型溢出
    	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
    		if (stdInfix[i] == '-' || stdInfix[i] == '+') {				//-x转换为0-x,+x转化为0+x
    			if (i == 0) {
    				stdInfix.insert(0, 1, '0');
    			}
    			else if (stdInfix[i - 1] == '(') {
    				stdInfix.insert(i, 1, '0');
    			}
    		}
    	}
    }
    
    //获取算术符号优先级
    int Calculator::getPrior(char c) {
    
    	if (c == '+' || c == '-') {
    		return PRIO_LV1;
    	}
    	else if (c == '*' || c == '/') {
    		return PRIO_LV2;
    	}
    	else if (c == '%' || c == '^') {
    		return PRIO_LV3;
    	}
    	else if (c == '!') {
    		return PRIO_LV4;
    	}
    	else {
    		return PRIO_LV0;
    	}
    	//else { cout << c << 非法符号! << endl; }
    }
    
    //后缀表达式转换
    void Calculator::getPostfix() {
    
    	int absNumeber = ABS_ODD;				//绝对值符号个数的奇偶性
    	string tmp;
    
    	//for (int i = 0; i < stdInfix.length(); i++) {
    	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
    		tmp = "";
    		switch (stdInfix[i]) {
    		case '+':
    		case '-':
    		case '*':
    		case '/':
    		case '%':
    		case '^':
    		case '!':
    			if (symStack.empty() || symStack.top() == '(' || symStack.top() == '[' || symStack.top() == '{' || (symStack.top() == '|' && absNumeber == ABS_ODD)) {
    				symStack.push(stdInfix[i]);
    			}
    			else {
    				while (!symStack.empty() && (getPrior(symStack.top()) >= getPrior(stdInfix[i]))) {
    					tmp += symStack.top();
    					postfix.push_back(tmp);
    					symStack.pop();
    					tmp = "";
    				}
    				symStack.push(stdInfix[i]);
    			}
    			break;
    		case '|':
    			if (absNumeber == ABS_ODD) {
    				symStack.push(stdInfix[i]);
    				absNumeber = ABS_EVEN;
    			}
    			else{
    				while (!symStack.empty() && symStack.top() != '|') {
    					tmp += symStack.top();
    					postfix.push_back(tmp);
    					symStack.pop();
    					tmp = "";
    				}
    				if (!symStack.empty() && symStack.top() == '|') {
    					tmp += symStack.top();
    					postfix.push_back(tmp);						//左绝对值符号'|'加入后缀表达式,用于绝对值的检测计算
    					symStack.pop();
    					absNumeber = ABS_ODD;
    				}
    			}
    			break;
    		case '(':
    		case '[':
    		case '{':
    			symStack.push(stdInfix[i]);
    			break;
    		case ')':
    			while (!symStack.empty() && symStack.top() != '(') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '(') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		case ']':
    			while (!symStack.empty() && symStack.top() != '[') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '[') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		case '}':
    			while (!symStack.empty() && symStack.top() != '{') {
    				tmp += symStack.top();
    				postfix.push_back(tmp);
    				symStack.pop();
    				tmp = "";
    			}
    			if (!symStack.empty() && symStack.top() == '{') {
    				symStack.pop();							//将左括号出栈丢弃
    			}
    			break;
    		default:
    			if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) {
    				tmp += stdInfix[i];
    				while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) {		//小数处理
    
    					tmp += stdInfix[i + 1];			//是连续的数字,则追加
    					i++;
    				}
    				if (tmp[tmp.length() - 1] == '.') {
    					tmp += '0';						//将x.做x.0处理
    				}
    				postfix.push_back(tmp);
    			}
    			break;
    		}//end switch
    	}//end for
    
    	//if(!symStack.empty()) {
    	while (!symStack.empty()) {						//将栈中剩余符号加入后缀表达式
    		tmp = "";
    		tmp += symStack.top();
    		postfix.push_back(tmp);
    		symStack.pop();
    	}
    }
    
    //计算后缀表达式
    void Calculator::calResult() {
    
    	string tmp;
    	double number = 0;
    	double op1 = 0, op2 = 0;
    
    	for (int i = 0; i < postfix.size(); i++) {
    		tmp = postfix[i];
    		if (tmp[0] >= '0' && tmp[0] <= '9') {
    			number = atof(tmp.c_str());
    			figStack.push(number);
    		}
    		else if (postfix[i] == "+") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1 + op2);
    		}
    		else if (postfix[i] == "-") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1 - op2);
    		}
    		else if (postfix[i] == "*") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(op1* op2);
    		}
    		else if (postfix[i] == "/") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop(); 
    			}
    			if (op2 != 0) {
    				///除数不为0,未做处理,默认
    			}
    			figStack.push(op1 / op2);
    		}
    		else if (postfix[i] == "%") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(fmod(op1, op2));			//可进行小数求余
    		}
    		else if (postfix[i] == "^") {
    			if (!figStack.empty()) {
    				op2 = figStack.top();
    				figStack.pop();
    			}
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(pow(op1, op2));
    		}
    		else if (postfix[i] == "|") {
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			figStack.push(abs(op1));
    		}
    		else if (postfix[i] == "!") {
    			if (!figStack.empty()) {
    				op1 = figStack.top();
    				figStack.pop();
    			}
    			if (op1 > 0) {
    				//阶乘数应大于;为小数时(转化为整数求阶)
    				double factorial = 1;
    				for (int i = 1; i <= op1; ++i)
    				{
    					factorial *= i;
    				}
    				op1 = factorial;
    			}
    			figStack.push(op1);
    		}
    	}//end for
    	if (!figStack.empty()) {
    		result = figStack.top();
    	}
    }
    
    //计算方法
    void Calculator::calculate() {
    
    	getFormat();				//表达式自定义标准格式化
    	getPostfix();				//后缀表达式转换
    	calResult();				//获取算术结果
    }
    
    //获取结果
    double Calculator::getResult() {
    	return result;
    }
    

    Main.cpp:主程序

    #include <iostream>
    using namespace std;
    
    //const int MAX_EXP_LEN = 1000;			//最大表达式长度	防止内存溢出
    
    //main函数
    int main()
    {
    	Calculator cal;
    	cout << cal.operatorSym << endl;
    	cout << "----------" << endl;
    
    	while (true) {
    		getline(cin, cal.infix);
    		/*
    		if (cal.infix.length() > MAX_EXP_LEN) {
    			cout << "超出最大长度!" << endl;
    			system("pause");
    		}
    		else {
    			cal.calculate();
    		}
    		*/
    		cal.calculate();
    		cout << cal.getResult() << endl;
    	}
    	return 0;
    }
    

    资源获取

    展开全文
  • QT、C++---实现计算器

    千次阅读 2022-04-15 21:10:41
    可以实现加减乘除,以及多个计算结果(连加、减、乘、除),支持按钮之间的联动,支持用户图形化界面。 思路 界面布局,包括数字按钮(0,1,2,3,4,5,6,7,8,9)、操作按钮(+、-、*、/、)、其他按钮(C == ...
  • 界面计算器

    2019-06-13 20:53:28
    数据结构课程设计计算器,带界面,具有报错功能,可以进行加减乘除括号混合运算,与或非逻辑运算。开发环境vs2017。上传为整个计算器设计工程,可以用vs2017打开。
  • 实现一个简单的计算器,它类似于带有Windows附件的计算器。该计算器不仅实现了简单的四种算术运算功能,而且实现了先进的科学计算功能,具有简洁大方的外观。它的设计是按照软件工程方法进行的。该系统界面友好,...
  • 简单的计算器界面

    2018-03-07 19:24:15
    有关于计算器界面的代码,方便取用有关于计算器界面的代码,方便取用有关于计算器界面的代码,方便取用
  • C++&QT实现计算器图形界面交互

    千次阅读 2020-05-10 14:49:49
    一、实验目的和要求 要求:在实验-03、实验-05的作业内容基础上 (1)增加图形交互功能。 (2)增加3个逻辑运算符 &&、||、 !,并能处理逻辑运算符和算术运算符的混合... DevC++&QT creator 系统:
  • C++MFC实现智能计算器

    2020-12-03 16:55:43
    使用VC6.0编写一个简易的计算,实现加、减、乘、除等运算。要求自己设计界面,用MFC“基本对话框”实现
  • c++写出带交互界面的简单计算器

    千次阅读 多人点赞 2020-05-21 15:53:59
    利用devc++和QT写交互界面计算器 一.先下载一个QT 下载地址 http://download.qt.io/archive/qt/ 我下载的是 5.12.8 版本的 第四个是windos的 第五个是mac的 第六个是linux的 按需下载就行了 这里有一篇下载安装...
  • 武汉理工大学 专业课程设计 2课程设计说明书 目录 1 基本功能描述1 2 设计思路1 3 软件设计4 3.1 设计步骤4 3.2 界面设计5 3.3 关键功能的实现11 4 结论与心得体会12 5 参考文献13 6 思考题13 7 附录14 7.1 调试报告...
  • 这是一个C++(windows forms)编写的表达式计算器,具有图形化界面,采用正常的波兰表达式输入
  • 1.2 计算器的介绍 (1)在运行程序后系统会弹出一个基于对话框的计算器界面如下图所示 图 1.1 计算器界面 (2)在计算器程序中主要通过一个编辑框来获取表达式和显示计算结果表达式可以 通过键盘和单击按钮 2 种方式输入...
  • 这个一个源码包,直接下载就可以看到可视化的小界面。适用于处于学习阶段的同学拿来研究学习,这个是本人本科学习时期的小作业,因为也经受过在网上找始终找不到适用的,所以拿来分享给大家。希望能帮助到有需要的你...
  • 计算器外观的制作 打开资源文件中的.rc文件: 选择视图中的工具箱选项: 主要用到下面三个工具: Botton:按键功能 Edit Control(编辑框):编辑控制功能 Static Text:存放静态文本 插入任意一个对话框,单击...
  • 告 汇 编 报告文档借鉴学习 word可编辑实用文档 目录 TOC \o "1-3" \h \z \u 1 基本功能描述 1 2 设计思路 1 3 软件设计 4 3.1 设计步骤 4 3.2 界面设计 5 3.3 关键功能的实现 11 4 结论与心得体会 12 5 参考文献 13...
  • c++实现计算器

    2019-12-26 20:28:27
    全新的界面设计 ,将会带来全新的写作体验; 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示; 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示; 全新的...
  • C++计算器可视化.rar

    2021-03-20 12:55:13
    基于MFC界面计算器,可以实现简单的加减乘除,代码简单易懂,下载可以直接运行
  • Qt/C++实现多功能计算器

    千次阅读 2021-09-02 15:52:25
    计算器可以实现简单的加减乘除的运算以及带括号、带基本的三角函数、对数、指数的表达式的运算。 容错处理: 1.在文本框中输入表达式时,会自动检测表达是否正确,若即将输入的字符会导致表达式错误,则该字符不会...
  • 以及给两个日期你可以得出他们两个之间相隔多少天.(需要考虑闰年,每个月天数不同,我们需要写一个我们直接可以使用的日期加减器)因为时间比较仓促,我也没有写界面,只有其中几个主要的函数的架构思想以及简单的...
  • c++图形计算器

    2012-09-26 09:01:47
    用vc++编写的计算器,图形界面,不支持键盘操作,可进行复数运算。
  • c++界面计算器

    2013-04-02 02:58:11
    c++builder6.0 开发的计算器,带界面,希望能帮助学生朋友

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,055
精华内容 3,222
关键字:

c++实现计算器界面