表达式求值的另一种方法

表达式求值除了用文法实现之外,还可以直接用栈,将中缀表达式转化为后缀表达式。然后再用求表达式的值就轻而易举了。

下面贴程序源码:(可能有点长,呵呵:)

main.cpp

 

#include"stack.cpp"
#include"stack.h"
#include<iostream>
using namespace std;
/*
*  该函数有两个功能
*  1. 输入中缀表达式
*  2. 将中缀表达式转化为后缀表达式
*  形参为两个指针分别指向两个数组(一个储存数字,一个储存运算符)
*  返回值是数字和运算符的总个数(若转化出错,返回-1)
*/
int change(double *Darra,char *Carra)
{
    int num = 0;									//记录式子中数字和运算符总数
	char ch;										//暂时存储,输入字符 
    double dou;										//暂时存储,输入数字 
	Stack<char>   mychar;							//存储运算符
	bool wchar = false;                             //是否有非法字符
	cout<<"请输入表达式(为了方便可以带空格),并以'='号结束:\n"<<endl;
	while( cin>>ch, '='!=ch )
	{
		switch(ch)
		{
		case '0':            case '5':
		case '1':            case '6':
		case '2':            case '7':
		case '3':            case '8':
		case '4':            case '9':
				num++;
				cin.putback(ch);					//如果是数字,扔回去,用double型数据装
				cin>>dou;
				cout<<dou<<ends;                    //后缀表达式部分输出
			    Darra[num] = dou;
		        break;
		case '+':
		case '-':
		case '*':
		case '/':
                while(  (!mychar.Isempty()) &&      //栈非空
					    (mychar.Top()!='(') &&      //栈顶元素不是空括号
						( (mychar.Top()=='*') || (mychar.Top()=='/') || (ch == '+') || (ch == '-') )  )
					                                //栈顶运算符优先级不低于输入的运算符
													//满足以上三个条件,将栈中元素全部弹出
				{
					num++;
					cout<<mychar.Top()<<ends;		//后缀表达式部分输出
					Carra[num] = mychar.Top();
					mychar.Pop();
				}
				mychar.Push(ch);					//若不满足,则将出入运算符压入栈中
			    break;
		case '(':
			    /*
				*   尝试解决省略*的运算不成功
			    if('\0' == Carra[num] && num != 0)
				{
					num++;
					cout<<'*'<<ends;
					Carra[num] = '*';
				}
				*/
			    mychar.Push('(');					//遇到开括号压入栈
                break;
		case ')':									
			    if(mychar.Isempty())				//判断括号是否匹配
				{
					cout<<"\n\n有多余的')'..."<<endl;
					return -1;
				}
				while(!mychar.Isempty())			//遇到闭括号,将栈中元素弹出
				{
					if('(' == mychar.Top())			//直至遇到开括号
					{
						mychar.Pop();
						break;
					}
					else							//如果栈为空,任然没有开括号,则执行弹出操作时,会出现错误,退出系统
					{
						num++;
						cout<<mychar.Top()<<ends;	//后缀表达式部分输出
						Carra[num] = mychar.Top();
						mychar.Pop();
					}
				}
                break;
		case ' ':
			    break;
		default:                                    //检测非法字符
			    wchar = true;
		}

	}
	 while(!mychar.Isempty())						//将栈中剩余运算符输出
		{
		    if('(' == mychar.Top())                 //括号不匹配
			{
				cout<<"\n\n有多余的'('..."<<endl;
				return -1;
			}
		    num++;
			cout<<mychar.Top()<<ends;				//后缀表达式部分输出
			Carra[num] = mychar.Top();
			mychar.Pop();
		}
	    if(0 == num)                                //没有任何表达式输入                      
		{
			cout<<"\n\n您没有输入任何表达式..."<<endl;
		    return -1;
		}
	if(wchar)                                      
	{
		cout<<"(字串中有非法字符)";
	}
	 cout<<endl<<"\n以上为中缀表达式和相应的后缀表达式,";
	return num;
}

/*
*  运算函数,将储存在数组中的符号和数字(后缀表达式)取出,计算成结果返回
*  形参:   储存有后缀表达式的两个数组首地址(此处若用栈,则后缀表达式从栈中输出时,其顺序完全反相),后缀表达式的长度
*  返回值: 后缀表达式的计算结果
*/
double Compute(char *Carra,double *Darra, int num)
{
	int i = 1;										//取后缀表达式的辅助变量
	double d1,d2;									//暂存栈中弹出的两个变量
	Stack<double> Res;								//运算栈,储存数字
	while( i <= num )								
	{
	    if(Carra[i] == '\0')						//如果i处是无效运算符,说明后缀表达式中,i处对应的应该是数字
		{
				Res.Push(Darra[i]);					//数字入栈
		}
		else                                        //如果是运算符
		{
			   d1 = Res.Top();  
			   Res.Pop();
			   d2 = Res.Top();   
			   Res.Pop();							//从栈顶弹出两个数据进行计算  
			   switch(Carra[i])
			   {
			   case '+':
                   Res.Push(d1+d2);					//计算后压回栈
				   break;
			   case '-':
				   Res.Push(d2-d1);
				   break;
			   case '*':
				   Res.Push(d1*d2);
				   break;
			   case '/':
				   if(0 == d1)
				   {
					   cout<<"请注意分母不能为零..."<<endl;
					   system("pause");
					   exit(0);
				   }
				   Res.Push(d2/d1);
				   break;
			   default:
				   cout<<"(Compute)运算符匹配出错了..."<<endl;
				   exit(0);
			   }
		}
        i++;
	}
	return Res.Top();								//弹出栈中最后一个数字(计算结果)
}


int main()
{
	int i;
	double Darra[S_size];							//装入数据
	char Carra[S_size];								//装入运算符
	for(i=0; i<S_size; i++)							//将储存运算符的数组做一个标记,以明确该下标所对应的是数字还是运算符
		Carra[i] = '\0';                            //若检测到Carra[i] = '\0',则说明Carra[i]中没有存入运算符,而Darra[i]中存储了一个数字

	cout<<"*************************  一个简单表达式计算程序 *************************"<<endl;
	cout<<"                                                                  ——by HQ"<<endl;
	cout<<"注意:请写全表达式,不要省略'*',写负数时请写成 '0 - x'的形式.\n"<<endl;

	if( ( i = change(Darra,Carra) )== -1 )			//判断转换是否成功
	{
       cout<<"\n转换失败..."<<endl;
	   system("pause");
	   exit(0);
	}
	else
	{
		 cout<<"其计算结果为:\n"<<endl;
		 cout<<Compute(Carra,Darra,i)<<endl;		//计算并输出结果
	}
	system("pause");
	return 0;
}

stack.cpp

 

 

/*
*    模板类(栈)的实现
*/
#ifndef Stack_cpp
#define Stack_cpp

#include"Stack.h"

template<class T>
Stack<T>::Stack()
{
    top = -1;
}

template<class T>
bool Stack<T>::Isempty()       // If the stack is empty, return true; otherwise return false.
{
	if(-1 == top)
	{
		return true;
	}
	else
	{
		return false;
	}
}

template<class T>
void Stack<T>::Pop()           // Pop an element from the top of the stack 
{
	if(top == -1)
	{
		cout<<"弹出栈出错..."<<endl;
     	exit(0);
	}
	top--;
}

template<class T>
void Stack<T>::Push(T ele)     // Push this element into the stack.
{
	if(top > S_size)
	{
		cout<<"栈溢出..."<<endl;
		exit(0);
	}
	top++;
    elem[top] = ele;
}

template<class T>
T Stack<T>::Top()              // Return the top element of the stack.
{
	if(-1 == top)
	{
       cout<<"已至栈底..."<<endl;
	   //exit(0);
	}
	return elem[top];
}

template<class T>
int Stack<T>::Size()           //Return the number of the elements in the stack.
{
	return top;
}

template<class T>              // clear all the elements in the stack
void Stack<T>::clear()
{
	top = -1;
}
#endif


stack.h

 

 

/*
*    模板类(栈)
*/

#ifndef Stack_h
#define Stack_h

#define S_size  50                         //the size of the stack

template<class T>
class Stack
{
public:
	Stack();
   	void Pop();                            // Pop an element from the top of the stack 
 	void Push(T elem);                     // Push this element into the stack.
 	T Top();                               // Return the top element of the stack.
 	bool Isempty();                        // If the stack is empty, return true; otherwise return false.
 	int Size();                            // Return the number of the elements in the stack.
	void clear();                          // clear all the elements in the stack
private:
    T elem[S_size];
	int top;
};

#endif


运行结果:

 



 

posted @ 2013-03-24 20:29  xinyuyuanm  阅读(329)  评论(0编辑  收藏  举报