序言
为了下学期校招单位的Qt岗,我将我大一做过的两个项目又拿出来重做了下,分别是计算圆面积APP和仿计算器APP。这个计算器是不含括号的但是有优先级的,基本原理就是先转为逆波兰表达式,再计算结果。计算圆面积APP被命名为first而仿计算器APP命名为second,first用的是UI设计的,即拖动相应的部件并调整大小;而second使用的是布局管理器(QGridLayout)来实现的,纯代码类型。
现在来看项目first。
圆面积计算APP(项目名:first)
结果展示
具体思路
它的主要想法是输入圆的半径R,通过圆面积公式来计算面积S。全部文件如下所示:
类名为dialog主要的逻辑公式写在dialog.cpp中如下所示:
void Dialog::on_countBtn_clicked()
{
bool ok;
QString tempStr;
QString valueStr=ui->radiusLineEdit->text();//传过来的信号(半径R)
int valueInt=valueStr.toInt(&ok);//将字符串R转为数字
double area=valueInt*valueInt*3.14159;//逻辑计算
ui->radiusLabel->setText(tempStr.setNum(area));//返回给槽
}
on_countBtn_clicked函数定义在类Dialog中,是一个private slots,类Dialog如下所示:
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void on_countBtn_clicked();//计算按钮
private:
Ui::Dialog *ui;
};
这个APP比较简单,也不涉及什么算法。只有dialog.h和dialog.cpp需要修改小小的两个地方。下面来看第二个项目。
仿计算器APP(项目名:second)
结果展示
项目结构
具体思路
使用了布局管理器(QGridLayout)一行4个空,一共5行。用了三个label和12个button ,C键是clear的意思,直接作清空操作。该项目的类名也叫second,second类定义如下所示:
class second : public QWidget {
Q_OBJECT
public:
QString h="";//h用于存放当前的式子
explicit second(QWidget *parent = nullptr);
~second() override;
private:
Ui::second *ui;
//定义各个部件
QLabel *text_content, *answer, *question;
QPushButton *cal,*one,*two,*three,*four,*five,*six,*seven,*eight,*nine,*zero,*clear,*plus,*minus,*cheng,*chu;
private slots:
//计算的核心函数,具体定义在second.cpp中
void CAL();
//为了方便,就不在second.cpp中定义了,但这是不规范的。
//用于定义每个按钮的行为,对应哪个按钮从函数名就可以看出。
void One()
{
h+='1';
question->setText(h);
};
void Two()
{
h+='2';
question->setText(h);
};
void Three()
{
h+='3';
question->setText(h);
};
void Four()
{
h+='4';
question->setText(h);
};
void Five()
{
h+='5';
question->setText(h);
};
void Six()
{
h+='6';
question->setText(h);
};
void Seven()
{
h+='7';
question->setText(h);
};
void Eight()
{
h+='8';
question->setText(h);
};
void Nine()
{
h+='9';
question->setText(h);
};
void Zero()
{
h+='0';
question->setText(h);
};
void Plus()
{
h+='+';
question->setText(h);
};
void Minus()
{
h+='-';
question->setText(h);
};
void Cheng()
{
h+='*';
question->setText(h);
};
void Chu()
{
h+='/';
question->setText(h);
};
void Clear()
{
h="";
question->setText(h);
};
};
接着我要在second.cpp中写上面那个CAL函数的逻辑,及计算逆波兰表达式的函数,其中还有一个change函数,用于计算出逆波兰表达式,而CAL则是计算逆波兰表达式的结果。具体逻辑如下:
//手撕单链表用于表示栈stack,没有用STL。
//定义结点
struct node
{
double data;
node *next;
public:
node();
};
node::node() {}
//定义栈
class stack
{
private:
node* top;
public:
stack() { top = NULL; }//初始化,构造函数
~stack();
void push(double e);//入栈操作
double pop();//退栈操作
double getTop();//取顶部操作
bool isEmpty() { if (top == NULL) return true; else return false; }//判空操作
};
double stack::getTop()
{
if (top != NULL)
return top->data;
}
stack::~stack()
{
node* p;
while (top)
{
p = top->next;
delete top;
top = p;
}
}
void stack::push(double e)
{
node* p = new node;
if (!p)
{
//cout << "内存分配失败" << endl;
return;
}
p->data = e;
p->next = top;
top = p;
}
double stack::pop()
{
if (top == NULL)
{
//cout << "溢出" << endl;
}
double temp = top->data;
node* p = top;
top = top->next;
delete p;
return temp;
}
struct Node
{
double data;
Node *next;
};
class sqqueue
{
private:
Node *front;
Node *rear;
public:
sqqueue();
~sqqueue();
void enqueue(double e);
double dequeue();
bool isEmpty();
double getFront();
};
double sqqueue::getFront()
{
return front->next->data;
}
sqqueue::sqqueue()
{
front = new Node;
front->next = NULL;
rear = front;
}
sqqueue::~sqqueue()
{
Node *p=NULL;
while (front != NULL)
{
p = front;
front = front->next;
delete p;
}
}
void sqqueue::enqueue(double e)
{
Node *s = new Node;
s->data = e;
s->next = rear->next;
rear->next = s;
rear = s;
if (front->next == NULL)
front->next = s;
}
double sqqueue::dequeue()
{
double e;
Node *p = NULL;
if (rear == front)
{
//cout << "下溢" << endl;
}
p = front->next;
e = p->data;
front->next = p->next;
if (p->next == NULL)
rear = front;
delete p;
return e;
}
sqqueue output;
stack s;
stack a;
//计算出具体的逆波兰表达式
void change(std::string str)
{
double num;
double temp;
for (int i = 0; i < str.length();)
{
if (str[i] >= '0'&&str[i] <= '9')
{
temp = str[i++] - '0';
while (i < str.length() && str[i] >= '0'&&str[i] <= '9')
{
temp = temp * 10 + (str[i] - '0');
i++;
}
output.enqueue(temp);
}
else
{
if (((str[i] == '+' || str[i] == '-')&&(s.getTop() == -3|| s.getTop() == -4))|| ((str[i] == '+' || str[i] == '-') && (s.getTop() == -1 || s.getTop() == -2))|| ((str[i] == '*' || str[i] == '/') && (s.getTop() == -3 || s.getTop() == -4)))
{
while (!s.isEmpty())
{
output.enqueue(s.pop());
}
}
switch (str[i])
{
case '+':s.push(-1); break;
case '-':s.push(-2); break;
case '*':s.push(-3); break;
case '/':s.push(-4); break;
default:break;
}
i++;
}
}
while (!s.isEmpty())
{
output.enqueue(s.pop());
}
}
//计算逆波兰表达式的结果
void second::CAL()
{
QString valueStr;
QString tempStr=question->text();//获取信号
std::string str=tempStr.toStdString();//将Qt的Qstring转化为string(C++标准的)
change(str);
double temp;
double r, l;
while (!output.isEmpty())
{
if (output.getFront() >= 0)
{
a.push(output.dequeue());
}
else
{
double x = output.dequeue();
if (x == -1)
{
r = a.pop();
l = a.pop();
temp = l + r;
a.push(temp);
}
else if (x == -2)
{
r = a.pop();
l = a.pop();
temp = l - r;
a.push(temp);
}
else if (x == -3)
{
r = a.pop();
l = a.pop();
temp = l * r;
a.push(temp);
}
else if (x == -4)
{
r = a.pop();
l = a.pop();
temp = l / r;
a.push(temp);
}
}
}
double ans=a.pop();
answer->setText(valueStr.setNum(ans));//传给槽
}
具体的项目可以看我的Github,这是地址: https://github.com/timTianWSRF/Qt_calculator-tim-