第四次作业--计算器简单计算

作业要求

Github进入窗口

前言:自寒假弄好计算器雏形以来,还有很多的不足,特别在这次作业,我发现了上次作业的有一些错误没找出来,在这次作业就有了一定的进展,为了完成作业,去看了很多网上写的博客,关于计算机的四则运算,还了解了stack和sstream的用法(虽然用的并不是很熟练),但是最终还是在参考了网上博客,完成了此次作业的要求和计算器的简单四则运算的实现.........

前期准备:我去网上弄懂了stack的用法,(请参考),以及sstream的用法,这就是用来处理字符到数字的转化器吧,(请参考这里)。学到这里,差不多明白了他们的用法,也想着去实现计算器的计算,但是,我还想到了要考虑一些计算的优先级问题,这就让我有点不明白了,stack能实现吗?如何实现呢?这就是我所要考虑的问题了。后来在博客上看了一篇关于前缀、中缀、后缀表达式的文章就大概明白了一点,(请参考),琢磨了好几天,参考了一篇博客的做法,将Scan类传出来的队列按从左到右,将表达式从中缀表达式转化为后缀表达式进行计算。
(我参考的博客做法)

Debug过程的感受:当我参考博客做好了作业,我发现还是有误的,首先是就是当我输入的表达式为:-1000+32*(20+2),程序直接不能计算,直接退出,在同学帮助下载栈中先push一个0进去就不会了,这个问题解决后,新的问题又接踵而来,就是括号处理问题,偶尔可以,偶尔不可以,这就让我很焦灼,这个bug让我找了一整天都没找到,我也让同学啊朋友啊帮我找,可是还是没有效果,就在昨天晚上,我室友突然发现我在Scan类中的队列没处理好,要判断temp是不是为空,空的话就不用push进去,否则才做相应的处理,
如图所示:

原本我是没做这个判断的。
(PS:原本我Scan类是没有返回一个队列的,在这次作业中,我发现没有返回队列很难实现功能,故将原来的Scan类返回一个队列。)

计算的主要代码:



judge a; /*定义一个judge对象来调用里面的方法*/

/*从中缀表达式到后缀表达式(逆波兰式),并且计算*/

int calcu::Calculation(queue<string>key)
{
	/*运算符优先算法*/
	stack<string>character;   /*只处理+ - # / ()运算*/
	stack<int>num;
	string alpa;
	int tmp;
	character.push("#");   /*用来表示开始结束的*/
	key.push("#");        /*来表示开始结束的*/
	num.push(0); 
	alpa = key.front();
	key.pop();
	//如果##配对,表达式求值完成
	for(;alpa != "#" || character.top() != "#";)
	{
		if (a.Punction(alpa)==0)
		{
			stringstream ss;
			ss<<alpa;          /*操作数入栈*/
			ss>>tmp;         /*将String转化为int*/
			num.push(tmp);
			alpa=key.front();
			key.pop();
		}
		else
		{
			/*比较栈顶操作符和新取得的操作符的优先关系*/
			int pa=a.Precede(character.top(), alpa);
			if(pa==1) /*栈顶优先权低*/
			{
				character.push(alpa);
				alpa = key.front();
				key.pop();
			}
			else if(pa==0)/*括号配对,栈顶括号弹出*/
			{
				character.pop();
				alpa = key.front();
				key.pop();
			}
			else if(pa==2)/*栈顶优先权高,先弹出,计算,结果操作数入栈*/
			{
				string QAT = character.top();
				character.pop();
				int num2 = num.top();/*第二个操作数在前*/
				num.pop();
				int num1 = num.top();
				num.pop();
				int Newnum= a.Operate(num1, QAT, num2);
				num.push(Newnum);
			}
		}
	}/*end of while*/
	/*操作数栈的唯一元素即为计算结果*/
	return num.top();
}

这段代码是模仿上述有说的一篇博客,边理解边完成实现的。

最后的实现:

作业的不足:就是不能自己完完整整自己敲出代码,还要模仿博客,虽然这不好,但是从中我也学到了很多,至少我弄懂了什么是前缀表达式,中缀表达式和后缀表达式,以及他们之间的转化。还有不足是该代码只能实现整型的加减乘除。还有就是当碰到除数为0的时候没有做判断,比如说:123+23/0+23-7*(3+3),有个除数为0的没有去做判断。另外呢就是当遇到 -1-(-2)+3 这样的表达式时也无法操作。

感受:改代码需要有耐心,学习敲代码很重要,当一个人敲的代码到了一定的量后,你会发现自己在去实现一个程序的时候很简单,在debug过程中,你可以找到很多的以后要注意的问题,这就是在一个过程中收获的东西,还有,要学会找资料,不要指望着别人帮你资料。还是自己好好努力,有付出就有收获!!!fighting!!!!我不在乎别人怎么看待自己,我只知道自己已经尽力了,自己进步了就好!!!

4月27日 最新更新:

在处理字符串入队前先判断‘(’的下一个字符是不是‘-’,如果是的话在它们之间加入一个‘0’,这样就避免了两个运算符在一起使得计算时识别出现故障。



queue<string>key;/*设全局的队列queue*/
queue<string>Scan::ToStringQueue(string input)
{
	int len=input.length();    /*测出字符串的长度*/
	string tmp="";
	for(int i=0;i<len;i++)
	{
		if(input[i]=='('&&input[i+1]=='-')
		{
			tmp+=input[i];
			tmp+='0';
		}
		else
		{
			tmp+=input[i];
		}
	} 
	int l=tmp.length();
	input="";
	input=tmp;
	tmp="";
	for (int i=0; i<l; i++)
	{
		/*如果数字的位数超过10 就产生错误;*/
		if (count>10)
		{
			cout<<"Error"<<endl;
			break;
		}
		/*判断是否有字符*/
		if (input[i]=='-' || input[i]=='+' || input[i]=='(' || input[i]==')' || input[i]=='/' || input[i]=='*')
		{
			count=0;
			/*将已有的数据存入队列*/
			if (tmp!="")
			{
				key.push(tmp);
			}
			/*置空*/
			tmp="";
			tmp+=input[i];
			/*讲一个一个不同于数字的运算符存入队列*/
			key.push(tmp);
			tmp="";       /*再次置空*/
		}
		else if (input[i]>=0||input[i]<=9)     /*判断是数字*/
		{
			count++;          /*计算连续数字的个数*/
			tmp+=input[i];        /*将连续数字存在一起*/
			continue;
		}
	}
	if(tmp!="")
	{
		key.push(tmp);          /*处理最后面的数字传入队列*/
		tmp="";
	}


运行如下:

当然我在测试数据时有--1--1+-1这样的情况就解决不了了,我在慢慢的去改进。

4月28日更新(解决4月27的遗留问题):



	/*=============================================================== 
	
	对输入的字符串在入队之前先做处理,判断在'('的下一个是不是'-',如果
	是的话就在他们之间加入一个'0',处理完后就对处理后的字符串进行入队处
	理。 
	
	================================================================*/
	for(int i=0;i<len;i++)
	{
		if(input[i]=='('&&input[i+1]=='-')
		{
			tmp+=input[i];
			tmp+='0';
		}
		else if(input[i]=='-'&&input[i+1]=='-')
		{
			tmp+='+';
			i++;
		}
		else if(input[i]=='-'&&input[i+1]=='+')
		{
			tmp+=input[i];
			i++;
		}
		else if(input[i]=='+'&&input[i+1]=='-')
		{
			tmp+=input[i];
			tmp+='0';
		}
		else if(input[i]=='+'&&input[i+1]=='+')
		{
			tmp+=input[i];
			i++;
		}
		else if(input[i]==')'&&input[i+1]=='(')
		{
			tmp+=input[i];
			tmp+='*';
		}
		else if(input[i]>='0'&&input[i]<='9'&&input[i+1]=='(')
		{
			tmp+=input[i];
			tmp+='*';
		}
		else
		{
			tmp+=input[i];
		}
	} 



就是对一些特例进行判断,若发现'-' '-'就用一个'+';如果遇到'+ -'就在'-'之前加个'0';若遇到'- +'就用一个'-'代替就好了;

运行如图:

努力的结果,继续加油,新的数据实时更新!!!!

posted @ 2016-04-11 19:13  Sxiaopeng  Views(313)  Comments(7Edit  收藏  举报