目录
展示效果:
编辑
在Qt中,"栈"的概念主要体现在两个层面:一是程序设计中的数据结构——栈(Stack),二是用户界面管理中的QStackedWidget
控件。下面我将分别简要介绍这两个方面:
1. 数据结构:栈
尽管Qt本身并不直接提供一个名为"Stack"的容器类,但你可以使用C++标准库中的std::stack
,或者利用数组、向量等容器配合特定的操作来模拟栈的行为。栈是一种后进先出(Last In, First Out, LIFO)的数据结构,主要操作有压栈(push)、弹栈(pop)和查看栈顶元素。
算法思路概览
本算法利用栈的先进后出特性,通过分离数字和运算符,实现复杂表达式的高效解析与计算。具体步骤如下:
- 初始化栈结构
- 数字栈:用于存储待计算的数值。
- 运算符栈:存储运算符,初始时包含一个等于号(
=
),作为终止计算的标志。
- 解析输入字符串
- 将输入的表达式视为由数字和运算符组成的序列。
- 逐字符扫描输入字符串,识别数字和运算符。
- 数字栈操作
- 遇到数字时,连续读取构成整数的所有字符,直至遇到运算符或字符串结束。
- 将形成的整数压入数字栈。
- 运算符栈操作
- 当遇到运算符时,与栈顶运算符比较优先级。
- 若栈外运算符优先级高于栈顶运算符,将其压入运算符栈。
- 若低于或等于栈顶运算符优先级,执行以下步骤:
- 弹出运算符栈顶的运算符。
- 从数字栈弹出两个数值(后弹出的为右操作数,先弹出的为左操作数)。
- 根据弹出的运算符执行相应的数学运算。
- 将计算结果重新压入数字栈。
- 重复上述步骤,直至栈外运算符被压入栈或运算符栈为空。
- 终止条件
- 当扫描至字符串末尾或遇到等于号(
=
)时,进行最终的计算,直至运算符栈清空。
思路图
我个人认为最主要的还是利用了栈这个先进后出的特性,可以很好的匹配这个算法的需求。
将输入的内容看为一串字符串,遍历字符串寻找自己所寻求的字符,利用C++面向对象的特性类型转变起来也更加容易
编辑
代码段:
#include "widget.h" #include "ui_widget.h" //按键优化 #define DEFULT_BUTTON_STYLE "\ QPushButton{\ color:#000000;\ border:1px solid #AAAAAA;\ border-radius:0;\ background-color:#FFFFFF;\ }\ QPushButton:pressed{\ color:#FFFFFF;\ background-color:#AAAAAA;\ }\ " Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->setFixedSize(415,489); this->setWindowTitle("计算器"); temp = '0'; ui->Text_2->setPlainText(temp); ui->zerp_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->one_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->two_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->three_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->four_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->five_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->six_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->seven_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->eight_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->nine_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->sum_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->sub_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->max_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->mini_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->del_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->equal_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->C_2->setStyleSheet(DEFULT_BUTTON_STYLE); ui->lable_2->setStyleSheet(DEFULT_BUTTON_STYLE); } Widget::~Widget() { delete ui; } //拆分字符 double Widget::splitNum(QString str,int &i) { QString temp; double num; while(str[i] >= '0' && str[i] <= '9') { temp += str[i++]; } num = temp.toDouble(); return num; } //栈内优先级 int Widget::inprior(char ch) { int in = 0; switch (ch) { case '=': break; case '+': in = 3; break; case '-': in = 3; break; case '*': in = 5; break; case '/': in = 5; break; default: break; } return in; } //栈外优先级 int Widget::outprior(char str) { int out = 0; switch (str) { case '=': break; case '+': out = 2; break; case '-': out = 2; break; case '*': out = 4; break; case '/': out = 4; break; default: break; } return out; } //比较优先级 int Widget::cmpprior(int in, int out) { if(in > out) { return 1; } else if (in < out) { return -1; } else { return 0; } } //计算公式 int Widget::caculator(int num1, int num2, char op) { switch (op) { case '+': return num1 + num2; break; case '-': return num2 - num1; break; case '*': return num1 * num2; break; case '/': return num2 / num1; break; default: break; } } //等于 void Widget::on_equal_2_clicked() { int i = 0; int num = 0; int num1 = 0,num2 = 0; int result = 0; char top,del,buf; optr.clear(); numtr.clear(); optr.push('='); infix = ui->Text_2->toPlainText(); if(infix.isEmpty()) return; while(!optr.empty()) { if(infix[i] == '0' ||infix[i] == '1' ||infix[i] == '2' ||infix[i] == '3' ||infix[i] == '4' ||infix[i] == '5' ||infix[i] == '6' ||infix[i] == '7' ||infix[i] == '8' ||infix[i] == '9') { num = splitNum(infix,i); numtr.push(num); } else { top = optr.top(); switch (cmpprior(inprior(top),outprior(infix[i].toLatin1()))) { case 1: buf = optr.pop(); num1 = numtr.pop(); num2 = numtr.pop(); numtr.push(caculator(num1,num2,buf)); break; case -1: optr.push(infix[i].toLatin1()); i++; break; case 0: del = optr.pop(); if(del != '=') i++; break; default: break; } } result = numtr.top(); if(result == 0) { qDebug("运算错误"); return; } ui->lineEdit_2->setText(QString::number(result)); } } //0 void Widget::on_zerp_2_clicked() { infix += '0'; ui->Text_2->setPlainText(infix); } //1 void Widget::on_one_2_clicked() { infix += '1'; ui->Text_2->setPlainText(infix); } //2 void Widget::on_two_2_clicked() { infix += '2'; ui->Text_2->setPlainText(infix); } //3 void Widget::on_three_2_clicked() { infix += '3'; ui->Text_2->setPlainText(infix); } //4 void Widget::on_four_2_clicked() { infix += '4'; ui->Text_2->setPlainText(infix); } //5 void Widget::on_five_2_clicked() { infix += '5'; ui->Text_2->setPlainText(infix); } //6 void Widget::on_six_2_clicked() { infix += '6'; ui->Text_2->setPlainText(infix); } //7 void Widget::on_seven_2_clicked() { infix += '7'; ui->Text_2->setPlainText(infix); } //8 void Widget::on_eight_2_clicked() { infix += '8'; ui->Text_2->setPlainText(infix); } //9 void Widget::on_nine_2_clicked() { infix += '9'; ui->Text_2->setPlainText(infix); } //+ void Widget::on_sum_2_clicked() { infix += '+'; ui->Text_2->setPlainText(infix); } //- void Widget::on_sub_2_clicked() { infix += '-'; ui->Text_2->setPlainText(infix); } //* void Widget::on_max_2_clicked() { infix += '*'; ui->Text_2->setPlainText(infix); } //除法 void Widget::on_mini_2_clicked() { infix += '/'; ui->Text_2->setPlainText(infix); } //. void Widget::on_lable_2_clicked() { infix += '.'; ui->Text_2->setPlainText(infix); } //归零 void Widget::on_C_2_clicked() { temp = '0'; infix.clear(); ui->Text_2->setPlainText(temp); } //删除 void Widget::on_del_2_clicked() { infix.remove(infix.length()-1,1); if(infix.length() == 0) { temp = '0'; infix.clear(); ui->Text_2->setPlainText(temp); return; } ui->Text_2->setPlainText(infix); }
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
#ifndef WIDGET_H #define WIDGET_H #include <QtWidgets> #include <QStack> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); double splitNum(QString,int &i);//拆分数字 int inprior(char ch);//栈内优先级 int outprior(char ch);//栈外优先级 int cmpprior(int in,int out);//比较优先级 int caculator(int num1,int num2,char op); private slots: void on_zerp_2_clicked(); void on_one_2_clicked(); void on_two_2_clicked(); void on_three_2_clicked(); void on_four_2_clicked(); void on_five_2_clicked(); void on_six_2_clicked(); void on_seven_2_clicked(); void on_eight_2_clicked(); void on_nine_2_clicked(); void on_sum_2_clicked(); void on_sub_2_clicked(); void on_max_2_clicked(); void on_mini_2_clicked(); void on_lable_2_clicked(); void on_C_2_clicked(); void on_del_2_clicked(); void on_equal_2_clicked(); private: Ui::Widget *ui; QStack<char> optr; QStack<double> numtr; QString infix; QString temp; }; #endif // WIDGET_H