目录
目录
在这里主要记载了如何使用Qt creator完成一个计算器的功能。该计算器可以实现正常的加减乘除以及括号操作,能实现简单的计算器功能。
1 界面设计
该计算器的界面设计如下所示:
2 思路简介
1. 中缀表达式的构建
将按键输入字符转换为字符串的形式。
比如:中缀表达式3+2+34+(6-3*5);
那么可以定义一个字符数组char Chars[1024];存储,之后使用QString::fromUtf8(this->Chars);将该字符数组转换为LineEdit可以显示的类型。
2. 中缀表达式转变为后缀表达式
直接按照字符将中缀转变为后缀表达式,在进行计算时,再转换为数据和符号。这里在将中缀表达式转变为后缀表达式时,把每个数都使用&进行分割,方便后续计算。比如32+21转换为后缀表达式就是32&&21+。
3. 使用后缀表达式进行计算
3 代码
3.1 widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void Fb_Change(); // 中缀转换为后缀表达式
void Clear();
public:
int i,j;
private slots:
void on_but_one_clicked();
void on_but_zero_clicked();
void on_but_two_clicked();
void on_but_three_clicked();
void on_but_four_clicked();
void on_but_five_clicked();
void on_but_six_clicked();
void on_but_seven_clicked();
void on_but_eight_clicked();
void on_but_nine_clicked();
void on_but_add_clicked();
void on_but_sub_clicked();
void on_but_mul_clicked();
void on_but_div_clicked();
void on_but_leftbrk_clicked();
void on_but_rightbrk_clicked();
void on_but_cls_clicked();
void on_but_bit_clicked();
void on_but_eql_clicked();
void on_but_close_clicked();
private:
Ui::Widget *ui;
int Data[128]; // data stack
char suffix[128]; // 后缀表达式 stack
char sign[128]; // 符号栈
char Chars[1024]; // zhong缀表达式字符数组
int data_sp = 0; // 数据栈顶指针
int suffix_sp = 0; // 后缀栈顶指针
int sign_sp = 0; // 符号栈顶指针
int char_sp = 0; //
int Operation_end = 0; // 运算结束标志位,1:运算结束
};
#endif // WIDGET_H
3.2 widget.c
#include "widget.h"
#include "ui_widget.h"
#include "qdebug.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_but_one_clicked()
{
this->Chars[char_sp++] = '1';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_zero_clicked()
{
this->Chars[char_sp++] = '0';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_two_clicked()
{
this->Chars[char_sp++] = '2';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_three_clicked()
{
this->Chars[char_sp++] = '3';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_four_clicked()
{
this->Chars[char_sp++] = '4';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_five_clicked()
{
this->Chars[char_sp++] = '5';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_six_clicked()
{
this->Chars[char_sp++] = '6';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_seven_clicked()
{
this->Chars[char_sp++] = '7';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_eight_clicked()
{
this->Chars[char_sp++] = '8';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_nine_clicked()
{
this->Chars[char_sp++] = '9';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_add_clicked()
{
this->Chars[char_sp++] = '+';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_sub_clicked()
{
this->Chars[char_sp++] = '-';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_mul_clicked()
{
this->Chars[char_sp++] = '*';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_div_clicked()
{
this->Chars[char_sp++] = '/';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_leftbrk_clicked()
{
this->Chars[char_sp++] = '(';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_rightbrk_clicked()
{
this->Chars[char_sp++] = ')';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}
void Widget::on_but_cls_clicked()
{
Clear();
}
void Widget::on_but_bit_clicked()
{
if(Operation_end == 0) // 没有运算结束
{
this->Chars[--char_sp] = ' ';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars));
}else {
// 运算结束
Clear();
}
}
void Widget::on_but_eql_clicked()
{
Fb_Change();
}
void Widget::Clear()
{
this->char_sp = 0;
ui->lineEdit->clear();
for(i=0; i<sign_sp; i++)
{
this->sign[i] = ' ';
}
sign[0] ='\0';
this->sign_sp = 0;
for(i=0; i<suffix_sp; i++)
{
this->suffix[i] = ' ';
}
this->suffix_sp = 0;
suffix[0] ='\0';
for(i=0; i<data_sp; i++)
{
this->Data[i] = 0;
}
this->data_sp = 0;
Operation_end = 0; // 运算结束标志位
}
// 中缀转换为后缀表达式
void Widget::Fb_Change()
{
int font=0;
int flag = 0;
i = char_sp;
j = 0;
int count = 0;
// 12*4+34/5-(56=67*4)+32 => 12 4 * 34 5 / 56 67 4 * + - 32 + +
qDebug() << "1";
while(i--) // 总共字符个数
{
if(isdigit(this->Chars[j])) // 如果是数字字符
{
if(flag == 0)
{
suffix[suffix_sp++] = this->Chars[j]; // !
j++;
}else{
suffix[suffix_sp++] = '&'; // 主要是为了正确分割数据, 和flag配合
suffix[suffix_sp++] = this->Chars[j]; // !
j++;
flag = 0;
}
continue;
}
if((sign_sp == 0 || sign[sign_sp-1] == '(') && this->Chars[j] != ')') // 如果符hao栈为空或者栈顶元素为'('
{
qDebug() << "null" <<endl;
suffix[suffix_sp++] = '&'; // 主要是为了正确分割数据, 和flag配合
sign[sign_sp++] = this->Chars[j]; // !
j++;
flag = 1; // 主要是为了正确分割数据
continue;
}
//
if((this->Chars[j] == '*' || this->Chars[j] == '/') && (sign[sign_sp-1] == '-' || sign[sign_sp-1] == '+'))
{
sign[sign_sp++] = this->Chars[j]; // !
j++;
flag = 1; //
continue;
}
if((this->Chars[j] == '*' || this->Chars[j] == '/') && (sign[sign_sp-1] == '*' || sign[sign_sp-1] == '/'))
{
suffix[suffix_sp++] = '&'; // 主要是为了正确分割数据, 和flag配合
suffix[suffix_sp++] = sign[--sign_sp];
sign[sign_sp++] = this->Chars[j];
j++;
flag = 1; // 主要是为了正确分割数据
continue;
}
if(this->Chars[j] == '+' || this->Chars[j] == '-')
{
suffix[suffix_sp++] = '&'; // 主要是为了正确分割数据, 和flag配合
suffix[suffix_sp++] = sign[--sign_sp];
sign[sign_sp++] = this->Chars[j];
j++;
flag = 1; //
continue;
}
if(this->Chars[j] == '(')
{
sign[sign_sp++] = this->Chars[j]; // !
j++;
flag = 1; //
continue;
}
if(this->Chars[j] == ')')
{
while(sign[--sign_sp] != '(')
{
suffix[suffix_sp++] = '&'; // 主要是为了正确分割数据, 和flag配合
suffix[suffix_sp++] = sign[sign_sp];
}
sign[sign_sp] = ' ';
j++;
flag = 1; //
continue;
}
}
while(sign_sp--){
suffix[suffix_sp++] = sign[sign_sp];
}
suffix[suffix_sp] = '\0';
qDebug()<< suffix;
// suffix compute
int arg_01, arg_02;
for(i=0; i < suffix_sp; i++)
{
if(suffix[i] >= '0' && suffix[i] <= '9')
{
font = font*count*10 + ((int)suffix[i] - 48); // 252
count = 1;
continue;
}
if(suffix[i] == '&')
{
if(count == 1) // 说明取过数
{
Data[data_sp++] = font;
font = 0;
}
count = 0;
continue;
}
if(suffix[i] == '+')
{
if(count == 1) // 说明取过数
{
Data[data_sp++] = font;
font = 0;
}
arg_01 = Data[--data_sp]; //
arg_02 = Data[--data_sp]; //
Data[data_sp++] = arg_01+arg_02;
qDebug() << Data[data_sp - 1];
count = 0;
continue;
}
if(suffix[i] == '-')
{
if(count == 1) // 说明取过数
{
Data[data_sp++] = font;
font = 0;
}
arg_01 = Data[--data_sp]; //
arg_02 = Data[--data_sp]; //
Data[data_sp++] = arg_02 - arg_01;
count = 0;
continue;
}
if(suffix[i] == '*')
{
if(count == 1) // 说明取过数
{
Data[data_sp++] = font;
font = 0;
}
arg_01 = Data[--data_sp]; //
arg_02 = Data[--data_sp]; //
Data[data_sp++] = arg_01 * arg_02;
count = 0;
continue;
}
if(suffix[i] == '/')
{
if(count == 1) // 说明取过数
{
Data[data_sp++] = font;
font = 0;
}
arg_01 = Data[--data_sp]; //
arg_02 = Data[--data_sp]; //
Data[data_sp++] = arg_02 / arg_01;
count = 0;
continue;
}
}
qDebug() << Data[0];
ui->lineEdit->clear();
this->Chars[char_sp++] = '=';
Chars[char_sp] ='\0';
ui->lineEdit->setText(QString::fromUtf8(this->Chars)+QString::number(Data[0]));
Operation_end = 1; // 运算结束标志位
}
// 237 238 236
void Widget::on_but_close_clicked()
{
this->close(); // close window
}