计算机软件技术实习项目一——简易计算器(代码实现)

文章描述了一个使用Qt编程语言实现的计算器类,包含数字输入、运算符处理、优先级比较和表达式计算功能,主要涉及操作数栈和运算符栈的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStack>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT
    QString expression;   //接受通过按钮输入的表达式

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

    char compare(char a,char b);             //用于判断运算符栈栈顶运算符 a1 与读入运算符 a2 之间的优先关系函数
    double Operate(double m,double n,char x);//用于计算两个操作数和一个操作符
    double jointnum(QString str,int &i);     //用于将一个操作数转换为double类型数,以便于存入操作数栈
    void  caculator() ;

private slots:
    void on_num_0_clicked();

    void on_num_1_clicked();

    void on_num_2_clicked();

    void on_num_3_clicked();

    void on_num_4_clicked();

    void on_num_5_clicked();

    void on_num_6_clicked();

    void on_num_7_clicked();

    void on_num_8_clicked();

    void on_num_9_clicked();

    void on_sign_jia_clicked();

    void on_sign_jian_clicked();

    void on_sign_cheng_clicked();

    void on_sign_chu_clicked();

    void on_sign_dengyu_clicked();

    void on_sign_zuokuo_clicked();

    void on_sign_youkuo_clicked();

    void on_sign_delete_clicked();

    void on_sign_clear_clicked();

    void on_sign_dian_clicked();

private:
    Ui::Widget *ui;
    QStack <double> opnd;  // Operand stack操作数栈
    QStack <char> optr;  // Operator stack运算符栈

};
#endif // WIDGET_H

widget.cpp 

#include "widget.h"
#include "./ui_widget.h"
#include <QStack>
#include <QWidget>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("计算器");

}

Widget::~Widget()
{
    delete ui;
}

//信号与槽  当点击计算器上各个按钮时产生操作,将输入的表达式存入QString类型的变量expression中
/* 关联 connect(ui->pushbutton-2,signal(clicked),this,slot(myslot()))
 * 自定义 connect(this,signal(mysignal),this,)不用实现
 * 直接转到槽
 * */
int cout=0;
int flag=1;
void Widget::on_num_0_clicked()
{
    expression +="0";
    ui->input_0->setText(expression);
    cout++;
    if(cout>=2){
        if(expression[cout-2]=='/') ui->input->setText("表达式错误");  //除数为0的情况
    }

}

void Widget::on_num_1_clicked()
{
    expression +="1";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_2_clicked()
{
    expression +="2";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_3_clicked()
{
    expression +="3";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_4_clicked()
{
    expression +="4";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_5_clicked()
{
    expression +="5";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_6_clicked()
{
    expression +="6";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_7_clicked()
{
    expression +="7";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_8_clicked()
{
    expression +="8";
    ui->input_0->setText(expression);
    cout++;

}

void Widget::on_num_9_clicked()
{
    expression +="9";
    ui->input_0->setText(expression);
    cout++;

}



void Widget::on_sign_jia_clicked()
{
    cout++;
    flag=1;
    expression +="+";
    ui->input_0->setText(expression);
    if(cout>=2) {if(expression[cout-2]=='-'||expression[cout-2]=='*'||expression[cout-2]=='/'
                       ||expression[cout-2]=='(')
                       ui->input->setText("表达式错误");
        else {if (expression[cout-2]=='+'){
                   expression.remove(expression.length()-1,1);
                   cout--;
                       }
                     }
    }
    else {
         ui->input->setText("表达式错误");
    }
}


void Widget::on_sign_jian_clicked()
{
    expression +="-";
    flag=1;
    ui->input_0->setText(expression);
    cout++;
    if(cout>=2) {if(expression[cout-2]=='+'||expression[cout-2]=='*'||expression[cout-2]=='/'
             ||expression[cout-2]=='(')
                   ui->input->setText("表达式错误");
         else {if (expression[cout-2]=='-'){
                   expression.remove(expression.length()-1,1);
                   cout--;}
         }
    }

}


void Widget::on_sign_cheng_clicked()
{
    expression +="*";
    ui->input_0->setText(expression);
    cout++;
    flag=1;
    if(cout>=2) {if(expression[cout-2]=='-'||expression[cout-2]=='+'||expression[cout-2]=='/'
             ||expression[cout-2]=='(')
                   ui->input->setText("表达式错误");
         else {if (expression[cout-2]=='*'){
                   expression.remove(expression.length()-1,1);
                   cout--;}
         }
    }
    else {
         ui->input->setText("表达式错误");
    }
}


void Widget::on_sign_chu_clicked()
{
    expression +="/";
    flag=1;
    ui->input_0->setText(expression);
    cout++;
    if(cout>=2) {if(expression[cout-2]=='-'||expression[cout-2]=='*'||expression[cout-2]=='+'
             ||expression[cout-2]=='(')
                   ui->input->setText("表达式错误");
         else {if (expression[cout-2]=='/'){
                   expression.remove(expression.length()-1,1);
                   cout--;}
         }
    }
    else {
         ui->input->setText("表达式错误");
    }
}


void Widget::on_sign_zuokuo_clicked()
{
  expression +="(";
  ui->input_0->setText(expression);
  cout++;
  if(cout>=2) { if (expression[cout-2]=='(')
                    {
                       expression.remove(expression.length()-1,1);
                       cout--;
                     }
                  else {
                       if(expression[cout-2]<='9'&&expression[cout-2]>='0')
                       {ui->input->setText("表达式错误");}
                           }

         }

  }



void Widget::on_sign_youkuo_clicked()
{
  expression +=")";
  ui->input_0->setText(expression);
  cout++;
  int i=cout;            //处理缺少左括号
  while(i>0){
            if(expression[i-1]=='(') {

                break;
            }
            else {
                i--;
            }
  }
  if (i==0) {
            if(expression[0]!='(')
            ui->input->setText("表达式错误");
  }
  //处理同加减乘除
  if(cout>=2) {if(expression[cout-2]=='-'||expression[cout-2]=='*'||expression[cout-2]=='+'
                ||expression[cout-2]=='('||expression[cout-2]=='/')
            {ui->input->setText("表达式错误");
            //qDebug()<<"cuowu";
  }
            else {if (expression[cout-2]==')'){
                         expression.remove(expression.length()-1,1);
                         cout--;}
            }
  }
  else {
            ui->input->setText("表达式错误");
  }
}

void Widget::on_sign_dian_clicked()
{
  if(flag==0) ui->input->setText("表达式错误");
  expression +=".";
  cout++;
  flag=0;
  if(cout<2){
            expression[0]='0';
            expression +=".";           //处理输入的第一个运算符为小数点的情况
            cout++;
  }
  else{
            if(expression[cout-1]==expression[cout-2])
            {
            expression.remove(expression.length()-1,1);
            cout--;}

  }
  ui->input_0->setText(expression);

}

void Widget::on_sign_delete_clicked()
{
  expression.remove(expression.length()-1,1);
  ui->input_0->setText(expression);
  cout--;
}

void Widget::on_sign_clear_clicked()
{
  ui->input_0->clear();
  ui->input->clear();
  expression.clear();
  cout=0;
}



//compare 用于判断运算符栈栈顶运算符op1与读入运算符op2之间的优先关系函数
char Widget::compare(char op1,char op2){
    int i,j;//i表示op1,j表示op2
    switch(op1){
    case'+':i=0;break;
    case'-':i=1;break;
    case'*':i=2;break;
    case'/':i=3;break;
    case'(':i=4;break;
    case')':i=5;break;
    case'#':i=6;break;   // # 是表达式的结束符
    }
    switch(op2){
    case'+':j=0;break;
    case'-':j=1;break;
    case'*':j=2;break;
    case'/':j=3;break;
    case'(':j=4;break;
    case')':j=5;break;
    case'#':j=6;break;
    }
    const int maxn=110;
    char priority[7][7]={
        {'>','>','<','<','<','>','>'},
        {'>','>','<','<','<','>','>'},
        {'>','>','>','>','<','>','>'},
        {'>','>','>','>','<','>','>'},
        {'<','<','<','<','<','=','0'},             // 此行"("=")"表示左右括号相遇,括号内运算已完成
        {'>','>','>','>','0','>','>'},
        {'<','<','<','<','<','0','='}              // "=" 表示整个表达式求值完毕
    };                                             //  "0"表示不可能出现这种情况
    return priority[i][j];
}

//用于计算两个操作数和一个运算符
double Widget::Operate(double m,double n,char x){
    if(x=='+')
        return m+n;
    if(x=='-')
        return n-m;
    if(x=='*')
        return m*n;
    if(x=='/'){
        if(m == 0)
        {
            ui->input->setText("语法错误");  //校验
            return 0;
        }

        return n/m;
    }
}

//处理操作数,将字符串转变为double返回一个数,每次只处理一个数
double Widget::jointnum(QString str,int &i){
    QString temp;
    double result;
    //处理小数点前面的部分
    while(str[i]>='0'&&str[i]<='9'){
        temp+=str[i];
        i++;
    }
    //遇到小数点
    if(str[i]=='.'){
        temp+=str[i];
        i++;
        while(str[i]>='0'&&str[i]<='9'){
            temp+=str[i];
            i++;
        }
    }
    result=temp.toDouble();

    return result;
}

void Widget::on_sign_dengyu_clicked(){

    int i=cout,j=cout;            //处理缺少右括号
    while(i>0){
        if(expression[i-1]=='(') {
            while(j>0){
                if(expression[j-1]==')')break;
                else j--;
            }
            break;
        }
        else {
            i--;
        }
    }

    if(i!=0&&j==0) ui->input->setText("表达式错误");

    else {
        cout++;
        if(cout==1)  ui->input->setText("请输入表达式");
        else {if(cout>=2) {if(expression[cout-2]=='-'||expression[cout-2]=='*'||expression[cout-2]=='+'||expression[cout-2]=='(')
                               ui->input->setText("表达式错误");
                            else caculator();
                          }

    }
    }
}


//双栈法求表达式
void  Widget::caculator()
    {
    optr.clear();
    opnd.clear();
    expression = ui->input_0->text();
    QString out=expression;
    out+="=";
    expression +='#';         //目的是为了结束循环
    if(expression[0]=='-'){
        expression='0'+expression;     //处理第一个数字是负数的情况
    }
    if(expression.isEmpty()) return;
    optr.push('#');  //#至于栈底

    int i=0;
    double num,a,b;  //num临时保存操作数 a、b用于保存参与运算的操作数
    char op1,op2,op;  //op1栈顶运算符,op2当前的运算符,op用于保存出栈参与运算的运算符
    while(!optr.empty()){    //循环条件的设置
        if(expression[i]=='0'||expression[i]=='1'||expression[i]=='2'||expression[i]=='3'||
            expression[i]=='4'||expression[i]=='5'||expression[i]=='6'||expression[i]=='7'||
            expression[i]=='8'||expression[i]=='9'||expression[i]=='.'){
            num=jointnum(expression,i);
            opnd.push(num);     //每if一次入栈一个操作数,直至循环结束
        }
        //遇到运算符则执行else语句,此时expression[i]指向运算符,因为jointnum函数采用了引用传递
        else{
            //取运算符栈顶符号进行优先级比较
            op1=optr.top();
            op2=expression[i].toLatin1();
            switch(compare(op1,op2)){
            case '<':{
             //栈顶小于当运算符 入栈
             optr.push(op2);
             i++;  //指向下一个字符

            }break;
            case '>':{
             //栈顶大于当前运算符 出栈 运算 结果存入操作数栈
             op=optr.pop();
             a=opnd.pop();
             b=opnd.pop();
             //qDebug()<<a<<op<<b;
             opnd.push(Operate(a,b,op));

            }break;
            case '=':{
             //两种情况1、当前为右括号 2、遇到#,即结束标志
             op1=optr.pop();
             if(op1!='#') i++;
            }break;
            case '0':{
             //语法错误
             ui->input->setText("语法错误");
            }break;
            }
        }

    }
    num=opnd.pop();//计算结果存储在num里
    QString str_num=QString::number(num,'g',10);
    ui->input->setText(QString::number(num));
    ui->history->append(out+QString::number(num));

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值