项目源码地址:class01_Qt计算器: 计算机软件实习项目01 (gitee.com)
程序员只进行理论的学习无异于一个士兵只练习而不上战场
只懂得理论是不行的,但实际情况是,理论枯燥难懂,也根本懂不了。在工作中,更需要的是业务能力,就是编写代码,解决bug的能力。如果想找一个好工作,应该把重心放在实战上,有了项目才是有了能力,要分清主次。
所以我想通过这次软件实习几个项目提升自己的能力。
一、需求分析
用户可以通过界面按钮进行计算式的输入,要求可以计算加减乘除以及带括号的优先级的运算
二、界面设计
使用控件:pushbutton、label、lineedit
信号与槽
此项目最重要的地方,是进行按钮的点击,绕不开的一个地方就是信号与槽了。信号与槽实现了对点击操作的响应,对响应函数的编写是我们主要该做的
信号与槽有三种关联方式:1、右击控件,选择转到槽,选择要响应的操作,对于按钮控件来说,它的(操作)即信号有单击,双击,点压,释放等等;2、自定义槽函数,自己关联,自己在private slots:下面定义槽函数,使用connect(发送者,信号,接收者,槽)将其与某个控件的信号关联;3、自定义信号又自定义槽,自己在signals: private slots: 定义信号函数和槽函数,注意信号函数无需实现也无法实现。
三、实现原理
结构目录
代码编写主要分为两个方向:即点击操作ui显示和计算式计算
通过在按钮点击的槽函数中写ui->lineedit->settext(),实现将点击输出到显示框里,如何连续输入并显示,ui->lineedit->settext(ui->lineedit->text()),只需加上已有的内容
设计两个界面,一个是主计算界面,一个是显示历史记录的界面
实现计算原理使用双栈法
calculate.cpp中实现具体的计算操作,具体函数为
//判断优先级
int operate(char ch){
if(ch=='(') return 0;
else if(ch=='+'||ch=='-') return 1;
else if(ch=='*'||ch=='/'||ch=='%') return 2;
else if(ch=='q') return 3;
else return 4;
}
//出栈元素的计算
void calculate(char temp,stack&Num){
double a=Num.top();Num.pop();
double innum;
if(temp=='q')innum=sqrt(a);
else{
double b=Num.top();Num.pop();
if(temp=='+')innum=b+a;
else if(temp=='-')innum=b-a;
else if(temp=='*')innum=b*a;
else if(temp=='/')innum=b/a;
else if(temp=='^')innum=pow(b,a);
else if(temp=='%')innum=fmodf(b,a);
}
Num.push(innum);
}
//表达式入栈出栈
double twoStack(string str){
stack Num;//存数字
stack Ch;//存操作符
int i = 0, j;
int size = str.size();
string num;
char temp;
while (i < size) {
if (str[i] >= '0' && str[i] <= '9') {
j = i;
while ((j < size && str[j] >= '0' && str[j] <= '9') || str[j]=='.') { j++; }
//从下标i开始截取长度为j-i的字符
num = str.substr(i, j - i);
//atof函数将字符串转换成浮点型数
Num.push(atof(num.c_str()));
i = j;
}
else if(str[i]=='('||str[i]==')'){
if (str[i]=='(') Ch.push(str[i]);
else{
while(Ch.top()!='('){
temp=Ch.top();
Ch.pop();
calculate(temp, Num);
}
Ch.pop();//左括号出栈!!这里我忘了两次!!
}
i++;
}
else{
if (Ch.empty()) {
Ch.push(str[i]);
}
else {
while (!Ch.empty()) {
temp = Ch.top();
if (operate(temp) >= operate(str[i])) {
Ch.pop();
calculate(temp, Num);
}
else break;
}
Ch.push(str[i]);
}
i++;
}
}
while(!Ch.empty()){
temp=Ch.top();
Ch.pop();
calculate(temp,Num);
}
return Num.top();
}
作为一个项目的开发,必不可少的就是程序的稳健性,就是在输入错误时,程序尽可能减少闪退
我采用的是在输入阶段就去抑制错误输入,从源头减少错误,怎么进行,就是在点击的时候,判断字符串末尾能不能接下一个字符,不能就返回空。
1.开头输入小数点、运算符、右括号;2、运算符前只能是数字或);3、根号前不能为根号)^;4、已经有运算符后,点击运算符可以切换运算符,避免了输入连续多个运算符