用C++跟QT实现计算器,支持±*/()小数,容错做到极致了?
文章目录
基本思路:
原理:
UI与逻辑分离,容错利用QString做在UI上,只能在无错情况下进入逻辑,否则按下=无效.
计算利用中缀表达式转为后缀表达式后,入栈进行计算,得到一个数字返回给UI
具体一些:按下=时,如果有效则会将QString转换为string再转char数组,传给逻辑里的change(char[]pre)函数,将其转化为后缀表达式.
接下来就是用calculate(char[]post)后缀表达式的计算啦
小数部分如何实现?:
读取部分有一个post数组存放后缀表达式,和一个栈用来存放符号,读到一个数时会一直往后读到符号前,然后数组里加入一个空格用来分隔数.下一个是符号则先放入符号栈.
例如1.2+2#过程:
先向stack里放一个#
读取1 放入post数组,
读到".“放入post数组,
读到"2"放入post数组
读到”+" post数组加入一个空格,由于+优先级大于#优先级故直接加入栈中,否则弹栈符号直到+优先级最大,然后将+加入栈
读取"2"放入post数组
读到"#"停止
符号栈全部取出放入post数组 成功转化为后缀表达式,接下来就是后缀表达式的计算
后缀表达式的计算就比较简单了,读到一个数字,将post数组和该数字的下标地址传入readnumber方法,该方法用于读取数组直到遇见空格或是符号,为了将其转化为小数,然后放入栈中.
读到空格则继续
读到符号则从栈中取出两个数进行计算
遇见#循环停止
容错,
是在UI里大量的IF语句
有:
-
小数点容错:前一位不是括号符号,当前数字中不含小数点(7.7.7型)
-
数字容错:不能在)后输入数字,前一位是0的情况要验证小数点,如果没有小数点再验证数字是否首位不为0(01无法输入,但10000,0.00000001可以)
-
符号容错:符号不能在小数点后面,(后面和首位(-除外,第一位可以放-,只需要在计算时首位加0即可)
-
括号容错:(上一位不能是数,小数点和) 而)上一位不能是符号,小数点,不能当作首位,且前方有未匹配左括号,可以加入)
如果上一位是(则添加0后加入)(0)
与之匹配相互对应,在执行回退一位的时候需要验证是否是()并相应执行±,在清空时将括号匹配count置为0 -
="容错,前一位是±*/.,且括号全部匹配时,(即count=0)才可计算
智能优化:在=操作执行后,再次输入数字会清空文本框再输入 -
目前已知缺陷:数太大情况下放不下,如有其他,请留言我改正
源代码:
UI界面:
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QStack>
#include <QMainWindow>
#include <QChar>
#include "calculator.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0);
private:
QString s;
Calculator c;
void calculate0();
bool sign_judge(QString s);
bool point_judge(QString s);
bool not_type_01_(QString s);
int count = 0;
bool clear = false;
};
#endif
mainwindows.cpp:
#include "mainwindow.h"
#include <QPushButton>
#include <QTextEdit>
#include<string.h>
#include <QTextCharFormat>
#include <QFont>
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent) {
//初始化
s = "";
resize(510, 510);
setWindowTitle("CAL");
//设置按钮,指定父对象
QPushButton* button_1 = new QPushButton(this);
QPushButton* button_2 = new QPushButton(this);
QPushButton* button_3 = new QPushButton(this);
QPushButton* button_4 = new QPushButton(this);
QPushButton* button_5 = new QPushButton(this);
QPushButton* button_6 = new QPushButton(this);
QPushButton* button_7 = new QPushButton(this);
QPushButton* button_8 = new QPushButton(this);
QPushButton* button_9 = new QPushButton(this);
QPushButton* button_0 = new QPushButton(this);
QPushButton* button_add = new QPushButton(this);
QPushButton* button_dec = new QPushButton(this);
QPushButton* button_mul = new QPushButton(this);
QPushButton* button_div = new QPushButton(this);
QPushButton* button_clear = new QPushButton(this);
QPushButton* button_equal = new QPushButton(this);
QPushButton* button_point = new QPushButton(this);
QPushButton* button_left = new QPushButton(this);
QPushButton* button_right = new QPushButton(this);
QPushButton* button_delete = new QPushButton(this);
button_0->setText("0");
button_1->setText("1");
button_2->setText("2");
button_3->setText("3");
button_4->setText("4");
button_5->setText("5");
button_6->setText("6");
button_7->setText("7");
button_8->setText("8");
button_9->setText("9");
button_add->setText("+");
button_dec->setText("-");
button_mul->setText("*");
button_div->setText("/");
button_clear->setText("CE");
button_equal->setText("=");
button_point->setText(".");
button_left->setText("(");
button_right->setText(")");
button_delete->setText("Del");
//设置显示窗口
QTextEdit* text = new QTextEdit(this);
text->resize(490, 90);
text->move(10, 10);
QTextCharFormat fmt;
fmt.setFont(QFont("Timers", 14, QFont::Bold));
text->setCurrentCharFormat(fmt);
text->setEnabled(false);
//布局
button_0->resize(90, 90);
button_0->move(10, 110);
button_1->resize(90, 90);
button_1->move(110, 110);
button_2->resize(90, 90);
button_2->move(210, 110);
button_3->resize(90, 90);
button_3->move(310, 110);
button_4->resize(90, 90);
button_4->move(10, 210);
button_5->resize(90, 90);
button_5->move(110, 210);
button_6->resize(90, 90);
button_6->move(210, 210);
button_7->resize(90