《面向对象程序设计》课程作业(六)

GitHub

关于Qt的学习

定义

Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能。

Qt教程

由于此次作业没有要求编码所以暂且研读了上面的教程,至于实践只是简单的打了教程中的样例。

目前看到了信号槽部分,略抽象有点难以理解,还在努力啃当中。

(helloworld的测试)

(信号槽的测试)

关于核心部分用栈实现

思路

关于栈的运用,这里主要是通过把原来中缀表达式转换成后缀表达式,然后计算求值。

  • 前缀表达式:-*a+bcd

  • 中缀表达式:a*b+c-d

  • 后缀表达式:abc+*d-

规则为:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

通过规则可以看出,栈的后进先出特点可以很好的满足后缀表达式的运算规则。而关键点在于后缀表达式的转换,如果转换成功了,那么计算其实很容易,依次计算即可。

运行截图

(关于转换后的后缀表达式测试)

(关于结果测试)

相关代码

算式生成

void Expression::randomNumber()
{
		digit = rand() % 3 + 4;   //数字的个数 
		for (int i = 0; i<digit; i++)
		{
			nums[i] = rand() % 9 + 1;    // 数字
		}
}

void Expression::randomOperation()
{
char c[] = "+-*/";
	for (int i = 0; i<digit; i++)
	{
		signs[i] = c[rand() % 4]; //符号
	}
	signs[digit] = '=';
}


void Expression::generateExpression()
{
stringstream str;
bracketNum = 1;//=rand()%2;    //括号个数 
if (bracketNum == 1)
{
	braO = rand() % (digit - 2) + 1;
	braT = braO + rand() % (digit - braO) + 1;
	//braO是第一个括号的位置,braT是第二个括号的位置
}
for (int i = 0; i<digit; i++)
{
	if (bracketNum != 0 && i == braO - 1)
		str << "(";
	str << nums[i];
	if (bracketNum != 0 && i == braT - 1)
		str << ")";
	if (i != digit - 1)
		str << signs[i + 1];
}
str >> equ;
//cout << equ<<"=";
}

计算结果

double Answer::calculateResult(Expression &c)
{
stack<double> stan;//数字栈 存储计算结果
stack<char> stac;//符号栈 存储符号
int length1, lenth, i, j;
string hzequ;//后缀表达式
length1 = c.equ.length();//生成的算式长度 
hzequ.clear();

for (i = 0; i<length1; i++)
{
	if (c.equ[i] <= '9'&&c.equ[i] >= '0') //如果是数字则入栈
	{
		hzequ.push_back(c.equ[i]); 
	}
	else
	{
		if (stac.size() == 0 || c.equ[i] == '(') //第一个符号或者左括号入栈
		{
			stac.push(c.equ[i]);
		}
		else
		{
			char temp1 = stac.top(); //之前的符号
			if (c.equ[i] == ')')  //如果当前符号是右括号 则符号栈内的依次出栈
			{
				lenth = stac.size();
				while (lenth)
				{
					char temp2 = stac.top();
					stac.pop();
					if (temp2 == '(')
						break;
					else
						hzequ.push_back(temp2);
					lenth--;
				}
			}
			else  //+-*/的情况 这个情况比较多比较复杂 需要判断当前符号和上一级符号的优先级
			{
				if (temp1 == '*' || temp1 == '/' || temp1 == '-' || temp1 == '+')
				{
					if ((c.equ[i] == '*' || c.equ[i] == '/'))
					{
						if (temp1 != '/'&&temp1 != '*')
							stac.push(c.equ[i]);
						else
						{
							hzequ.push_back(temp1);
							stac.pop();
						stac.push(c.equ[i]);
						}
					}
					else
					{
						lenth = stac.size();
						while (lenth)
						{
							char temp = stac.top();
							if (temp != '(')
							{
								hzequ.push_back(temp);
								stac.pop();
							}
							lenth--;
						}
						stac.push(c.equ[i]);
					}
				}
				else
				{
					stac.push(c.equ[i]);
				}
			}
		}
	}
}

if (stac.size() != 0)
{
	lenth = stac.size();
	while (lenth)
	{
		char temp = stac.top();
		hzequ.push_back(temp);
		stac.pop();
		lenth--;
	}
}
//cout <<endl<< hzequ << endl;

//由后缀表达式计算算式值
int hzlength = hzequ.size();
double t1, t2,t3;
for (i = 0; i<hzlength; i++)
{
	if (hzequ[i] <= '9'&&hzequ[i] >= '0')
	{
		double number = hzequ[i] - '0';
		stan.push(number);
	}
	else
	{
		t1 = stan.top();
		stan.pop();
		t2 = stan.top();
		stan.pop();
		switch (hzequ[i])
		{
		case '+':t3 = t1 + t2; break;
		case '-':t3 = t2 - t1; break;
		case '*':t3 = t1*t2; break;
		case '/':t3 = t2 / t1; break;
		default:break;
		}
		stan.push(t3);
	}
}
//cout << stan.top() << endl;
result = stan.top();
return result;
}

关于此次作业的感想

由于是初次接触后缀表达式,所以在转换上花了一定的功夫,研读了百度上的文章,模仿写了转换,但还是出了一堆的bug,其中遇到了*/优先级以及括号各种不匹配的问题,感觉我是在一步一步改bug的途中加深了对后缀表达式的认识。

另外关于Qt的学习,在安装上就遇到了挫折,校园网崩盘导致我装了大概五六次才成功,以及初次运行就出现编译器问题,还是要慢慢来吧。

经过这次作业觉得自己自学能力以及钻研能力还是有待提高,在此也特别感谢王源同学的耐心指导,向优秀的同学学习。

posted @ 2017-05-31 21:59  wood崽  阅读(313)  评论(0编辑  收藏  举报