實驗題目:棧的應用-算術表達式求值
實驗環境: Visual C++ 6.0
實驗目的 :
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) 根據實驗報告模板詳細書寫實驗報告,在實驗報告中給出 表達式求值算法的流程圖 。
(5) 上傳源程序到Sakai網絡教學平台。順序表的源程序保存為 calculator.cpp。
#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<string.h> #define OVERFLOW -2 #define MAXSIZE 100 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #include<iostream> using namespace std; typedef int Status; typedef char SElemType; //--------順序棧的存儲結構------ typedef struct { SElemType *base; //棧底指針 SElemType *top; //棧頂指針 int stacksize; //占可用的最大容量 }SqStack; Status InitStack (SqStack &S) {//構造一個空棧 S.base=new SElemType[MAXSIZE]; //為順序棧動態分配一個最大容量為MAXSIZE的數組空間 if (!S.base) exit(OVERFLOW); //動態分配失敗 S.top=S.base; //top初始為base,空棧 S.stacksize=MAXSIZE; //stacksize置為棧的最大容量MAXSIZE return OK; } Status Push(SqStack &S,SElemType e) {//插入元素e為新的棧頂元素 if(S.top-S.base==S.stacksize) return ERROR; //棧滿 *S.top++=e; //元素e壓入棧頂,棧頂指針加1 return OK; } Status Pop(SqStack &S,SElemType &e) {//刪除s的棧頂元素,用e返回其 if (S.top==S.base) return ERROR; //棧頂 e=*--S.top; // 棧頂指針減1,將棧頂元素為e return OK; } SElemType GetTop(SqStack S) {//返回S的棧頂元素,不修改棧頂指針、 if(S.top!=S.base) //棧非空 return *(S.top-1); //返回棧頂元素的值,棧頂指針不變 } Status In(SElemType c) { switch(c) //判斷讀入的字符是哪一種運算符, { case '+': return TRUE; break; case '-': return TRUE; break; case '*': return TRUE; break; case '/': return TRUE; break; case '(': return TRUE; break; case ')': return TRUE; break; case '#': return TRUE; break; default: return FALSE; } } SElemType Precede(SElemType t1,SElemType t2) { SElemType f; switch(t2) //判斷運算符棧的棧頂元素和讀入的運算符之間誰的優先級更高,並返回結果 { case '+': if (t1=='('||t1=='#') f='<'; else f='>'; break; case '-': if (t1=='('||t1=='#') f='<'; else f='>'; break; case '*': if (t1=='+'||t1=='-'||t1=='('||t1=='#') f='<'; else f='>'; break; case '/': if (t1=='+'||t1=='-'||t1=='('||t1=='#') f='<'; else f='>'; break; case '(': if (t1=='+'||t1=='-'||t1=='('||t1=='#'||t1=='*'||t1=='/') f='<'; break; case ')': if (t1=='+'||t1=='-'||t1=='*'||t1=='/'||t1==')') f='>'; else if (t1=='(') f='='; break; case '#': if (t1=='#') f='='; else f='>'; break; default: cout<<"輸入超出范圍。。。"; } return f; } SElemType Operate(SElemType a,SElemType theta,SElemType b) { SElemType c; a=a-'0'; //因為a,b均為字符型,所以轉化成int型 b=b-'0'; switch(theta) { case '+': c=a+b+'0';break; //再將計算的結果轉化為字符型 case '-': c=a-b+'0';break; case '*': c=a*b+'0';break; case '/': c=a/b+'0';break; } return c; //返回計算結果 } char EvaluateExpression() {//算數表達式求值的算符優先算法,設OPTR和 OPND分別為運算符棧和操作數棧 SqStack OPND,OPTR; char ch,theta,a,b,c,x,w; InitStack(OPND); //初始化OPND棧 InitStack(OPTR); //初始化OPTR棧 Push(OPTR,'#'); //將表達式起始符“#”OPTR棧 cin>>ch; while (ch!='#'||GetTop(OPTR)!='#') //表達式沒有掃描完畢或者OPTR的棧頂元素不為“#” { if (!In(ch)) //判斷ch是不是運算符,不是則壓入OPND棧 { Push(OPND,ch); cin>>ch; } else switch(Precede(GetTop(OPTR),ch)) // 比較OPTR的棧頂元素和ch的優先級 { case '<': Push(OPTR,ch); //當前字符ch壓入OPTR棧 ,讀入下一個字符ch cin>>ch; break; case '>': Pop(OPTR,theta); //彈出OPTR棧頂的運算符 Pop(OPND,b); //彈出OPND棧頂的運算數, Pop(OPND,a); //彈出OPND棧頂的運算數, Push(OPND,Operate(a,theta,b)); //將運算結果壓入OPND棧 break; case '=': //OPTR的棧頂元素是“(”且ch是“)” Pop(OPTR,x); //彈出OPTR棧頂的"(", cin>>ch; //讀入下一個字符ch break; } } return GetTop(OPND); //OPND棧頂元素即為表達式求值結果 } int main() { char w; cout<<"請輸入算數表達式,並以#結束\n"; w=EvaluateExpression(); //將運算結果賦值給w w=w-48; //將字符轉換成數字 printf("The result of expression is %d\n",w); }