课程作业六——栈算法的解读与程序的界面设计
课程作业六——栈算法的解读与程序的界面设计
Part.1
本次的课程作业要求是:做到将四则运算的核心部分采取栈的知识进行解决(即表达式生成的合法性检验、表达式结果计算)。我在之前的博客里其实时不时就有提到过以上的内容,这次借此机会就以演示的方式来更直观的去解读一下栈的使用及实现的流程。我们都知道栈的实现原理是先进后出,而这一原理其实就是中缀转后缀实现的核心内容。
首先我们先来以((9*5/3)-5)=10为例进行解读:
首先是算式的生成以与合法性的检验,即检测结果是否是一个整数,当结果非整数型式时,返回重新生成计算式,如果符合,则输出计算式用于用户进行做题。在这个过程中,程序中途调用计算结果的calculateResult函数。
string Expression::generateExpression()
{
for (;;)
{
int h = 1;
int number[4];
string sign[4];
string num_1, num_2;
for (int i = 0;i <= 3;i++)
{
number[i] = randomNumber(); //用于随机生成数字
}
for (int j = 0;j <= 2;j++)
{
sign[j] = randomOperation(); //用于随机生成运算符
}
string equa = "";
for (int i = 0;i <= 2;i++)
{
num_1 = Int_str(number[i]);
num_2 = Int_str(number[i + 1]);
int temp = rand() % 2 + 1;
switch (temp) //用于随机添加进括号,分加入或者不加入两种情形
{
case 1:
{
if (i == 0)
{
equa = num_1 + sign[i] + num_2;
}
else
{
equa = equa + sign[i] + num_1;
}
break;
}
case 2:
{
if (i == 0)
{
equa = "(" + num_1 + sign[i] + num_2 + ")";
}
else
{
equa = "(" + equa + sign[i] + num_1 + ")";
}
break;
}
}
}
double res = calculateResult(equa); //去调用计算结果的calculate.cpp计算结果 //将生成的计算式进行内部结果的运算
if (res == (int)res) //检验输出是否是一个整数型式的结果
{
Res_set(res);
equation = equa;
return equation;
break;
} //如果不符合结果为整数型式,则重新进入生成计算式的循环
}
}
进入计算式结果的求解过程,中间需要调用void transform(string infix, char postfix[])函数以实现中缀转后缀表达式来进行结果的计算,最终return回用于与用户比较的正确结果。
double calculateResult(string infix) //计算后缀表达式的值并且计算生成的运算式的结果
{
int i = 0, point = -1;
char postfix[100];
double figure[100] = {}; // 开一个存放运算操作的数栈
transform(infix, postfix); //调用中缀转后缀的表达式转换代码
while (postfix[i] != '\0')
{
if (postfix[i] >= '0'&&postfix[i] <= '9')
{
double k = 0;
while (postfix[i] >= '0'&&postfix[i] <= '9')
{
k = 10 * k + postfix[i] - '0';
i++;
}
point++;
figure[point] = k;
}
else
{
point--;
switch (postfix[i])
{
case '+':figure[point] = figure[point] + figure[point + 1];break;
case '-':figure[point] = figure[point] - figure[point + 1];break;
case '*':figure[point] = figure[point] * figure[point + 1];break;
case '/':figure[point] = figure[point] / figure[point + 1];break;
}
}
i++;
}
return figure[point];
}
在calculateResult函数的中途引用了以下的代码,实现中缀转后缀的算式转换:
void transform(string infix, char postfix[]) //中缀表达式转为后缀表达式
{
stack <char> sign;
int i = 0, j = 0;
while (i < infix.size())
{
if ((infix[i] >= '0') && (infix[i] <= '9')) //判断数字将其存进数栈
{
while ((infix[i] >= '0') && (infix[i] <= '9'))
{
postfix[j] = infix[i];
i++;
j++;
}
postfix[j] = '!'; //标识单个整数,防止数字混排无法一一识别
j++;
}
if ((infix[i] == '+') || (infix[i] == '-')) //判断'+'、'-'
{
while (!sign.empty() && (sign.top() != '('))
{
postfix[j] = sign.top();
j++;
sign.pop();
}
sign.push(infix[i]);
}
if (infix[i] == '*' || infix[i] == '/') //判断'*'、'/'
{
while ((!sign.empty()) && (sign.top() != '(') && ((sign.top() == '*') || (sign.top() == '/')))
{
postfix[j] = sign.top();
j++;
sign.pop();
}
sign.push(infix[i]);
}
if (infix[i] == '(')
sign.push(infix[i]); //判断'('
if (infix[i] == ')') //判断')'
{
while (sign.top() != '(')
{
postfix[j] = sign.top();
j++;
sign.pop();
}
sign.pop();
}
i++;
}
while (!sign.empty()) //转出符号栈中剩余的运算符
{
postfix[j] = sign.top();
j++;
sign.pop();
}
postfix[j] = '\0'; //补上一个终止符
}
用于核对用户输入的结果是否与内部计算的结果相同,正确返回true,错误返回false。
bool checkanswer(int res, int ans)
{
if (res == ans)
{
return true;
}
else
{
return false;
}
}
Part.2
在界面的设计过程中,我选择使用Qt框架进行目标的实现。Qt支持在.ui文件中直接拖拽控件进行使用让我觉得很有意思,当然这只是简单的图形排版,要实现内部的运行还是需要代码的实现来写好槽和信号。我是以边学边做的形式,初出茅庐的我发现使用起Qt来还是不太容易的,因为资料全都是英文,这对我来说算是一个不小的挑战。我还在学习之中,中途以示例练练手并基本设计了一下自己程序该有的模样,顺带添上了一个程序logo,说实话很有趣。以下是我学习过程的截图:
以上就是我本次作业的全部成果,后期还要抓紧学好Qt的代码实现,还不会的有那么多,所以要走的路还有很远,谢谢观赏,以上。