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

Github链接

表达式用栈的实现

表达式的生成过程用流程图来展示

我们通过生成一个个a+b型的小表达式,来获得最终符合用户要求的表达式。

首先由用户决定(输入y/n):

  • 表达式中出现数字的绝对值范围
  • 表达式中出现数字的个数
  • 是否允许乘除
  • 是否允许分数
  • 是否允许括号

程序根据用户的输入来生成表达式,可以让用户对题目进行“私人订制”,生成多种多样的表达式。

然后通过对表达式的唯一性和是否除零的检验,如果通过就放入集合中,否则就重新生成。

至于合法性的检验,只要确保每一个a+b型的小表达式合法,则最终的表达式就合法。

代码

/*************************************************************
文件名:Expression.cpp
作者:盖嘉轩 日期:2017/05/09
描述: 定义——类:Expression
主要功能:表达式的生成、计算
作者:盖嘉轩 日期:2017/05/10
*************************************************************/
#include"expression.h"
#include<iostream>
#include<sstream>
#include<vector>
#include<stack>
using namespace std;

Expression::Expression() { }
/*随机生成一个运算符*/
char Expression::RandomOperation(char ifMultiplyDivide)
{
	int tmp;
	if (ifMultiplyDivide == 'y') //允许乘除
	{
		tmp = RandomNumber(1, 4);
		switch (tmp)//随机生成运算符
		{
		case 1:
		{
			return '+';
			break;
		}
		case 2:
		{
			return '-';
			break;
		}
		case 3:
		{
			return '*';
			break;
		}
		case 4:
		{
			return '/';
			break;
		}
		}
	}
	else //不允许乘除
	{
		tmp = RandomNumber(1, 2);
		switch (tmp)
		{
		case 1:
		{
			return '+';
			break;
		}
		case 2:
		{
			return '-';
			break;
		}
		}
	}
}

 /*判断表达式是否唯一,重复为false,唯一为true */
bool Expression::IsOnly(string expression)
{
	int count = 0;
	for (unsigned i = 0; i < m_expressionUint.size(); i++)
	{
		if (expression != m_expressionUint[i])
		{
			count++;
		}
		else
		{
			break;
		}
	}
	if (count == m_expressionUint.size()) //如果为唯一
	{
		return true;
	}
	else// 如果重复
	{
		return false;
	}
}

/*生成一个中缀表达式*/
string Expression::GenerateInfixExpression(int low, int high, int parameterNumber, char ifMultiplyDivide, char ifFraction, char ifBracket)
{
	string expression; 
	for (; ;)
	{
		string parameter1, parameter2; 
		bool ifFirst = true; //是否已生成第一个小表达式,是为true,否为false
		for (int j = 0; j < parameterNumber - 1; j++)
		{
			int ntmp;
			char sign = RandomOperation(ifMultiplyDivide); //运算符

			if (ifFraction == 'y') //允许分数
			{
				ntmp = RandomNumber(1, 3);
				switch (ntmp)
				{
				case 1: //整数和整数
				{
					stringstream sstmp1, sstmp2;
					sstmp1 << RandomNumber(low, high);
					sstmp1 >> parameter1;
					sstmp2 << RandomNumber(low, high);
					sstmp2 >> parameter2;
					sstmp1.clear();
					sstmp2.clear();
					break;
				}
				case 2:  //整数和真分数
				{
					stringstream sstmp;
					sstmp << RandomNumber(low, high);
					sstmp >> parameter1;
					sstmp.clear();
					Fraction fraction2;
					fraction2.GetFraction(low, high);
					fraction2.Simplify();
					parameter2 = fraction2.TransferIntoStringNoInt();
					break;
				}
				case 3: //分数和分数 
				{
					Fraction fraction1, fraction2;
					fraction1.GetFraction(low, high);
					fraction1.Simplify();
					fraction2.GetFraction(low, high);
					fraction2.Simplify();
					parameter1 = fraction1.TransferIntoStringNoInt();
					parameter2 = fraction2.TransferIntoStringNoInt();
					break;
				}
				}
			}
			else //不允许分数
			{
				stringstream sstmp1, sstmp2;
				sstmp1 << RandomNumber(low, high);
				sstmp1 >> parameter1;
				sstmp2 << RandomNumber(low, high);
				sstmp2 >> parameter2;
				sstmp1.clear();
				sstmp2.clear();
			}
			if (ifBracket == 'y') //允许括号
			{
				ntmp = RandomNumber(1, 4);
				switch (ntmp)
				{
				case 1: //无括号
				{
					if (ifFirst)
					{
						expression = parameter1 + sign + parameter2;
						ifFirst = false;
					}
					else
					{
						expression = expression + sign + parameter1;
					}
					break;
				}
				case 2: //无括号
				{
					if (ifFirst)
					{
						expression = parameter2 + sign + parameter1;
						ifFirst = false;
					}
					else
					{
						expression = parameter1 + sign + expression;
					}
					break;
				}
				case 3: //有括号
				{
					if (ifFirst)
					{
						expression = "[" + parameter1 + sign + parameter2 + "]";
						ifFirst = false;
					}
					else
					{
						expression = "[" + expression + sign + parameter1 + "]";
					}
					break;
				}
				case 4: //有括号
				{
					if (ifFirst)
					{
						expression = "[" + parameter2 + sign + parameter1 + "]";
						ifFirst = false;
					}
					else
					{
						expression = "[" + expression + sign + parameter1 + "]";
					}
					break;
				}
				}
			}
			else //不允许括号
			{
				ntmp = RandomNumber(1, 2);
				switch (ntmp)
				{
				case 1:
				{
					if (ifFirst)
					{
						expression = parameter1 + sign + parameter2;
						ifFirst = false;
					}
					else
					{
						expression = expression + sign + parameter1;
					}
					break;
				}
				case 2:
				{
					if (ifFirst)
					{
						expression = parameter2 + sign + parameter1;
						ifFirst = false;
					}
					else
					{
						expression = parameter1 + sign + expression;
					}
				}
				}
			}
		}
		m_infix = expression;
		if ((IsOnly(expression)) && (CalculateResult() != "non_comformance")) //判断新生成的表达式是否重复以及是否出现除0的情况
		{
			m_expressionUint.push_back(expression);
			break;
		}
	}
	return expression;
}

 /*将中缀表达式转化为后缀表达式 */
void Expression::TransferInfixIntoPostfix()
{
	unsigned i = 0;
	int j = 0;
	stack<char> signStack;//符号栈 
	while (i < m_infix.size())
	{
		if ((m_infix[i] >= '0') && (m_infix[i] <= '9'))//判断数字 
		{
			while ((m_infix[i] >= '0') && (m_infix[i] <= '9'))
			{
				m_postfix[j] = m_infix[i];
				i++;
				j++;
			}
			m_postfix[j] = '!'; //标识单个整数
			j++;
		}
		if (m_infix[i] == '(') //判断分数 
		{
			while (m_infix[i] != ')') //将分数作为整体 
			{
				m_postfix[j] = m_infix[i];
				i++;
				j++;
			}
			m_postfix[j] = m_infix[i];
			i++;
			j++;
		}
		if ((m_infix[i] == '+') || (m_infix[i] == '-')) //判断加减
		{
			while ((!signStack.empty()) && (signStack.top() != '['))
			{
				m_postfix[j] = signStack.top();
				j++;
				signStack.pop();
			}
			signStack.push(m_infix[i]);
		}
		if ((m_infix[i] == '*') || (m_infix[i] == '/'))//判断乘除  
		{
			while ((!signStack.empty()) && (signStack.top() != '[') && ((signStack.top() == '*') || (signStack.top() == '/')))
			{
				m_postfix[j] = signStack.top();
				j++;
				signStack.pop();
			}
			signStack.push(m_infix[i]);
		}
		if (m_infix[i] == '[') //判断'['
		{
			signStack.push(m_infix[i]);
		}
		if (m_infix[i] == ']')  //判断']' 
		{
			while (signStack.top() != '[')
			{
				m_postfix[j] = signStack.top();
				j++;
				signStack.pop();
			}
			signStack.pop();
		}
		i++;
	}
	while (!signStack.empty())//当有残余运算符时 
	{
		m_postfix[j] = signStack.top();
		j++;
		signStack.pop();
	}
	m_postfix[j] = '';  //设置终止符
}

 /*计算后缀表达式的值*/
string Expression::CalculateResult()
{
	int i = 0;
	int point = -1; 
	bool ifDivideZero = false; //是否除零,是为true,否为false
	Fraction numberStack[kMax]; //数栈
	TransferInfixIntoPostfix();
	while ((m_postfix[i] != '') && (i<1000))
	{
		if ((m_postfix[i] >= '0') && (m_postfix[i] <= '9'))//整数入栈  
		{
			double k = 0; //int会计算出错
			while ((m_postfix[i] >= '0') && (m_postfix[i] <= '9'))
			{
				k = 10 * k + m_postfix[i] - '0';
				i++;
			}
			point++;
			numberStack[point].TransferIntIntoFraction(k, 1);
		}
		else
			if (m_postfix[i] == '(') //分数入栈
			{
				double up = 0, down = 0;//int会计算出错  
				i++;
				while (m_postfix[i] != '\')
				{
					up = 10 * up + m_postfix[i] - '0';
					i++;
				}
				i++;
				while (m_postfix[i] != ')')
				{
					down = 10 * down + m_postfix[i] - '0';
					i++;
				}
				point++;
				numberStack[point].TransferIntIntoFraction(up, down);
			}
			else //进行计算
			{
				point--;
				switch (m_postfix[i])
				{
				case '+':
				{
					numberStack[point] = numberStack[point] + numberStack[point + 1];
					break;
				}
				case '-':
				{
					numberStack[point] = numberStack[point] - numberStack[point + 1];
					break;
				}
				case '*':
				{
					numberStack[point] = numberStack[point] * numberStack[point + 1];
					break;
				}
				case '/':
				{
					if (numberStack[point + 1].isDivisorZero()) //如果除数为零
					{
						ifDivideZero = true;
					}
					numberStack[point] = numberStack[point] / numberStack[point + 1];
				}
				}
			}
		i++;
	}
	if ((!ifDivideZero) && (numberStack[point].IsInt())) //如果没有除零以及得数为整数
	{
		return numberStack[point].TransferIntoString();
	}
	else
	{
		return "non_comformance";
	}
}

学习MFC

MFC(Microsoft Foundation
Classes),全称微软基础类库,是一个微软公司提供的类库(class libraries),MFC以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。可以用于C++界面编程

优点:

MFC的主要优点是可以用面向对象的方法来调用Windows API,以及应用程序开发的便捷。MFC将很多应用程序开发中常用的功能自动化,并且提供了文档框架视图结构和活动文档这样的便于自定义的应用程序框架。同时,在Visual C++内部也内建了很多对MFC的例如类向导这样的支持以减少软件开发的时间,使用类向导可以生成从hello world这样的简单程序到活动文档服务器这样的复杂程序。MFC的消息映射机制也避免了使用性能较低的庞大虚函数表。

缺点:

虽然MFC的源代码对用户是完全开放的,但是MFC的一些封装过程过于复杂,以致于新用户很难迅速掌握MFC的应用程序框架,以及在调试中定位问题的位置。同时,很多MFC对象不是线程安全的,致使在跨线程访问MFC对象时需要编写额外的代码。另外,MFC的很多类依赖于应用程序向导生成的代码,使得在使用Visual C++中其他类型的应用程序向导生成的工程中添加MFC支持的难度大大增加。

心得

虽然已经做了那么多次的作业了,但是每一次自学新知识还是有一些“混乱”!在网上找一篇合适的博客都要找好久,一旦遇到问题就急得不行,可能我还是需要在历练一下。

原文地址:https://www.cnblogs.com/gjx031602211/p/6925988.html