1. 程式人生 > >資料結構第二次作業(表示式求值【棧模擬】)

資料結構第二次作業(表示式求值【棧模擬】)

實驗題目:棧的應用-算術表示式求值                      

實驗目的

1.掌握棧的定義及實現;

2.掌握利用棧求解算術表示式的方法。

實驗內容:

通過修改完善教材中的演算法3.4,利用棧來實現算術表示式求值的演算法。對演算法3.4中呼叫的幾個函式要給出其實現過程:

(1) 函式In(c):判斷c是否為運算子;

(2) 函式Precede(t1,t2):判斷運算子t1和t2的優先順序;

(3) 函式Operate(a,theta,b):對a和b進行二元運算theta。

程式執行時,輸入合法的算術表示式(中間值及最終結果要在0~9之間,可以包括加減乘除和括號),便可輸出相應的計算結果。如下圖:

實驗提示 (僅供參考,每個函式的具體實現可以有多種方法,希望有創新)

1. 將棧的定義和實現單獨儲存在標頭檔案“stack.h”中,然後在表示式求值的源程式中包含此標頭檔案(即#include“stack.h”)。

2.表示式求值源程式的具體實現

(1) 主函式如下:

void main()

 {

   Printf(“請輸入算術表示式,並以#結束.\n”);

  Printf(“the result of expression is:%d\n”,EvaluateExpression());

 }

(2) 函式EvaluateExpression的實現見演算法3.22

(3)

函式In(c)的實現可以採用以下方式:

Status In(SElemType c)//應在前面有定義typedef char SElemType;

 { // 判斷c是否為運算子

   switch(c)

   {

     case'+':return TRUE;

     ……//補充完整

default:return FALSE;

   }

 }

(4) 函式Precede(t1,t2)的實現可以採用以下形式:

SElemType Precede(SElemType t1,SElemType t2)

 { //根據教材表3.1,判斷兩個運算子的優先關係

   SElemType f;

   switch(t2)

   {

     case '+':

     case '-':if(t1=='('||t1=='#')

                f='<';

              else

                f='>';

              break;

……//補充完整

}

   return f;

}

(5) 函式Operate(a,theta,b)的實現可以採用以下方式:

SElemType Operate(SElemType a,SElemType theta,SElemType b)

 {

   SElemType c;

   a=a-48;

   b=b-48;

   switch(theta)

   {

     case'+':c=a+b+48;

             break;

……//補充完整

   }

   return c;

 }

選做內容:進一步改進,使表示式的中間值及最終結果不侷限於0~9之間的個位數。(如果完成要在實驗報告中註明),如下圖:

實驗要求

(1) 程式要新增適當的註釋,程式的書寫要採用縮排格式

(2) 程式要具在一定的健壯性,即當輸入資料非法時, 程式也能適當地做出反應。

(3) 程式要做到介面友好,在程式執行時使用者可以根據相應的提示資訊進行操作。

(4) 根據實驗報告模板詳細書寫實驗報告,在實驗報告中給出表示式求值演算法的流程圖


#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stack>
#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;

int In(char ch) // 判斷輸入字元是否為運算子 
{
	if(ch=='+')	return OK;
	if(ch=='-')	return OK;
	if(ch=='*')	return OK;
	if(ch=='/')	return OK;
	if(ch=='(')	return OK;
	if(ch==')')	return OK;
	if(ch=='#')	return OVERFLOW;
	return ERROR;
}

char Precede(char a,char b) // 比較符號 a與符號 b的優先順序.如 a 優於 b,則返回 ' > ',否則返回 ' < ' 或 ' = ' 
{
	if(b=='+')
	{
		if(a=='('||a=='#')	return '<';
		return '>';
	}
	if(b=='-')
	{
		if(a=='('||a=='#')	return '<';
		return '>';
	}
	if(b=='*')
	{
		if(a=='*'||a=='/'||a==')')	return '>';
		return '<';
	}
	if(b=='/')
	{
		if(a=='*'||a=='/'||a==')')	return '>';
		return '<';
	}
	if(b=='(')	return '<';
	if(b==')')
	{
		if(a=='(')	return '=';
		return '>';
	}
	if(b=='#')
	{
		if(a=='#')	return '=';
		return '>';
	}
}

double Operate(double a,char theta,double b) // 把 a、b進行二元運算 
{
	if(theta=='+')	return a+b;
	if(theta=='-')	return a-b;
	if(theta=='*')	return a*b;
	if(theta=='/')	return a/b;
}

double EvaluateExpression() // 計算過程 
{
	char str[10010];
	stack<double> OPND;
	stack<char> OPTR;
	scanf("%s",str);
	OPTR.push('#');
	double a,b,shu=0;
	int flag=0;
	char theta;
	for(int i=0;str[i];i++)
	{
		if(In(str[i])==0)
		{
			shu=shu*10+str[i]-'0';
			flag=1;
		}
		else
		{
			if(flag)
			{
				OPND.push(shu);
				shu=0;
				flag=0;
			}
			switch(Precede(OPTR.top(),str[i]))
			{
				case '<':
					OPTR.push(str[i]);
					break;
				case '>':
					theta=OPTR.top();	OPTR.pop();
					b=OPND.top();	OPND.pop();
					a=OPND.top();	OPND.pop();
					OPND.push(Operate(a,theta,b));
					i--; // 這裡是因為判斷的該符號 str[i] 還沒有入棧,故需要回去判斷一下 
					break;
				case '=':
					OPTR.pop();
					break;
			}
		}
	}
	return OPND.top();
}

int main()
{
	printf("\n************************************************************************\n\n");
	puts("溫馨提醒:\n");
	puts("    為了方便,請您在輸入表示式的結尾加一個符號 '#',以判斷您的輸入完成");
	puts("\n    如若忘了輸入結束字元 '#',結果可能有誤"); 
	printf("\n************************************************************************\n\n");
	puts("\n請輸入您想要計算的表示式:\n");
	printf("\n計算結果為:%.2lf\n",EvaluateExpression());
	puts("\n\n\n\n謝謝您的使用,請按任意鍵退出");
	system("pause");
	return 0;
}