第四次作业的完善

——下定决心开始行动后,你会发现问题并非有想象中的那么难,问题照样有理可寻。过程中也曾迷茫,甚至想放弃,但既然开始了总不能半途而废吧。

——时间挤一挤真的还是会有的。

github链接
接下来的是我的解题思路:

1.因为我们输入的式子是中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。
因此我先将中缀表达式转变为前缀表达式。(过程中我参考了以下博客 参考博客 )。
(期间我在转换的前缀表达式的过程中,忘记了将括号剔除,导致了程序无法正常运行。。。在这上花了好多时间。)

2.转化成前缀表达式之后就可以开始计算了:
从右到左遍历表达式的每个数字和符号,遇到是数字就进栈,遇到的是符号,就将栈顶的两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

3.其中让我最懵的就是对负数的判断处理,这也是我考虑了最久的问题,后来在同学的帮助下终于攻克了该难关。

如下是主要代码:

int Calculation::level(string c) //判断运算符号优先级 
{
int q;
if(c=="+" || c=="-")
{
	q=1;
}
if(c=="*" || c=="/")
{
	q=2;
}

return (q);
}

bool Calculation::isOperator(string s) //判断是否是四则运算符号 
{
if (s=="+" || s=="-" ||s== "*" ||s=="/")
	return true;
else
	return false;
}



double Calculation::output(queue<string> strs)
{    
stack<string> ch;  // 放队列strs的逆表达式
stack<string> s1; //运算符栈
stack<string> s2; //储存中间元素的栈
stack<string> ch1;//放前缀表达式的逆式子
stack<double> out; //放运算结果的栈
string temp;


while(!strs.empty()) // 将scan中返回的队列按逆序的方式压入栈ch中 
{
	ch.push(strs.front()) ;
	strs.pop();

}

while(!ch.empty())
{
	temp=ch.top();

	ch.pop();

	if(isOperator(temp))
	{

		ex:;

		if(s1.empty())
		{
			s1.push(temp);
		}
        else if (s1.top() == ")")
        {
            s1.push(temp);
		}   


		else if(level(temp)>=level(s1.top()))
		{

			s1.push(temp);

		}

		else
		{
			s2.push(s1.top());
			s1.pop();

			goto ex;
		}
	}

	else if(temp=="(")
	{
		while(s1.top()!=")")
		{
			s2.push(s1.top());
			s1.pop();
		}

        s1.pop();
	}

	else if(temp==")")
	{
		s1.push(temp);
	}

	else
	{
		s2.push(temp) ;
	}


}


while(!s1.empty()) //栈s1不为空则把s1中剩下的所有元素压入栈s2中 
{
	s2.push(s1.top());
	s1.pop();
}


	// 此时已得到前缀表达式 

while(!s2.empty()) //将前缀表达式的逆序逐个压入栈ch1中 
{
	ch1.push((s2.top())) ;
	s2.pop();
}

  

while(!ch1.empty()) //开始计算
{
	double x,y,z;
	string symble;   
	symble=ch1.top(); //将栈顶元素赋给字符串
	ch1.pop();



 	if(symble =="+")
	{
		x=out.top();
		out.pop();
		y=out.top();
		out.pop();
		z=x+y;
		out.push(z);
	}
	else if(symble == "-")
	{
		x=out.top();
		out.pop();
		y=out.top();
		out.pop();
		z=x-y;
		out.push(z);

	}
	else if(symble == "*")
	{
		x=out.top();
		out.pop();
		y=out.top();
		out.pop();
		z=x*y;
		out.push(z);
	}
	else if(symble == "/")
	{
		x=out.top();
		out.pop();
		y=out.top();
		out.pop();
		z=x/y;
		out.push(z);
	}

	else // 将字符串中的数字转成double型 
	{
		stringstream stream;
		double number;
		stream<<symble;
		stream>>number;
		out.push(number);
		stream.clear();
	}
}

double num=0;
num=out.top();
out.pop();
return num;

}

实现效果:

收获:

1.cmd命令行对于我来说也是陌生的,因此参考资料(参考资料 ),通过查看资料自己对于命令行有了基础的了解。

2.这次的作业也让我对stack栈有所了解,能够比较熟练应用该数据结构。

3.运用sstream将字符串中的数字转为double型。(可参考资料 )

原文地址:https://www.cnblogs.com/cjqcjq/p/5398786.html