棧的操作和c語言實現算術表示式求值

2021-06-26 21:30:01 字數 4091 閱讀 9740

棧是一種特殊的線性表,按照「後進先出」的原則處理資料。

棧的基本操作有兩種:一種是入棧(push),即把資料儲存到棧頂,注意在入棧前應該先檢查棧是否已滿,如滿則不能入棧操作,未滿則修改棧頂指標,使其向上移動乙個元素的位置,然後將資料儲存到棧頂指標所指的位置。 一種是出棧(pop),即把棧頂資料彈出,注意在出棧之前檢查棧是否為空,如果棧為空沒有資料則提示不能進行出棧操作,若不空,則修改棧頂指標,使其指向棧中的下乙個元素。

1.編寫操作棧的標頭檔案  

typedef struct stack

seqstack;

其中data定義棧中元素的資料型別,size表示棧的最大容量,size+1表示棧的資料從下標為1開始,當top為0時,表示棧為空。

2.初始化棧

seqstack *seqstackinit()

return null; //申請記憶體失敗

}

初始化棧需要做兩件事,首先按照size指定的大小申請一片記憶體空間,儲存棧中資料,然後設定棧頂指標的值為0,表示空棧。

3.判斷棧的狀態

int seqstackisempty(seqstack *s)  //棧是否為空

int seqstackisfull(seqstack *s) //棧是否滿

對棧操作前先判斷棧的狀態,入棧前棧是否滿,出棧前棧是否為空。

4.清空棧  釋放棧所佔的記憶體空間

void seqstackclear(seqstack *s)

void seqstackfree(seqstack *s) //釋放棧的空間

清空棧時,即把棧頂指標top置0,釋放棧時,因為棧是用malloc函式分配的,所以不使用時用free函式釋放分配的記憶體空間。

5.入棧操作

int seqstackpush(seqstack *s,data data)

s->data[++s->top]=data; //修改棧頂指標,把元素入棧

return 1;

}

入棧時,判斷若top已經滿了(s->top==size),則top+1就超出棧的最大記憶體空間,提示棧溢位,做出錯處理。若沒有溢位,則棧頂指標向上移動一位,把資料放入其中,即入棧。

6.出棧操作

int seqstackpop(seqstack *s)     //出棧

return (s->data[s->top--]); //從棧頂彈出元素

}

出棧與入棧相反,從棧頂彈出乙個資料元素。先判斷top是否為0,若為0,則表示空棧,提示出錯,若不為0,修改棧頂指標減一,即往下移動一位,返回此時棧頂指標所指位置,原來棧頂元素彈出,即出棧。

7.獲取棧頂元素

data seqstackpeek(seqstack *s)  //讀出棧頂元素

return (s->data[s->top]); //返回棧頂元素

}

在出棧操作中,是把原來的棧頂元素彈出(拋棄了),即出棧後棧頂元素就不存在了,若只是讀取一下棧頂的元素而不刪除,就不需要將top指標往下移動,不修改指標位置,這樣返回棧頂後棧頂資料元素還在。

以上為棧的基本操作,下面舉乙個實用例子深入理解棧的相關操作。

棧的實際運用:算術表示式求值

在計算機中輸入乙個算式如:(2+3)*5  容易知道先計算2+3=5,再將5*5=25,,但計算機在讀入算式時的具體過程是怎樣的?

計算機先逐步掃瞄:先是(括號,這時不知道右括號在**出現,所以先儲存起來,然後是2,也不知道該字元下一位是什麼,也先儲存,然後是+,這時知道是加上乙個數,但不知道加什麼,先儲存起來,然後是3,這時知道是2+3,直接相加嗎?不能,如果3後面是*,或者/的高優先順序話就先計算,所以也先儲存,然後是),這時括號內的2+3就可以取出運算了,得出結果5後再儲存起來(由此可以看出加減的優先順序大於()的優先順序),然後是*,儲存起來,然後是5,儲存起來,然後是=號,表示整個算式結束了,將2+3得到的5與5相乘,輸出最終結果。

由上分析可知,程式需要儲存運算元,儲存運算子(+,-,*,/,=,(,)),還需要確定優先順序(乘除大於加減,加減大於括號,括號可以改變優先順序的順序,相同優先順序從左往右計算)。

為了簡化程式,只考慮加減乘除四則運算。

首先呼叫庫函式:

#include#include#include#define size 50

typedef int data; //定義棧元素型別

#include "biaodashi.h"

第六行引用最開始的棧的基本操作程式為標頭檔案,

具體函式模組分析:

1.每次讀取檢查字元是否為運算子

int isoperator(char c)    //檢查字元是否為運算子

}

定義isoperator函式,如果字元為+,-,*,/,(,),=,運算子,則返回1,否則返回0,。

2.比較運算子的優先順序:

注:在計算表示式時,為了方便判斷增設「=」為表示式定界符,即以=表示開始,=表示結束

int pri(char oper1,char oper2)     //判斷兩個運算子的優先順序

//如果oper1>oper2返回1 如果oper1oper2

break;

case '*':

case '/':

if(oper1=='*'||oper1=='/'||oper1==')')

pri=1; //oper1>oper2

else

pri=-1; //oper1oper2

break;

} return pri;

}

在該函式中對oper1和oper2兩個運算子比較,34到40行表示:oper2為+或-號,

若oper1為(或=號,

oper1oper2,pri=1。41到47行同理。48到55行表示:oper2等於(時,若oper1等於),即)(,這樣右括號後直接左括號是不對的,oper2等於(,

若oper1不為),則oper1oper2,pri=1。  最後返回pri。

3.對於優先順序高的運算子,需要將運算子兩側的資料進行計算,

int calc(int a,int oper,int b)  //計算兩個運算元的結果

} }

當為除數時,注意考慮除數不能為0,

4.寫好以上函式部分,就可以開始計算表示式的值:

int calcexp(char exp)   //表示式計算函式

switch(pri(x,c)) //判斷運算子優先順序

}else if(c>='0'&&c<='9') //如果輸出的字元在0到9之間

else

x=seqstackpeek(stackoper); //獲取棧頂操作符

} q=seqstackpop(stackdata);

seqstackfree(stackoper);

seqstackfree(stackdata); //釋放記憶體占用空間

return q; //出棧,返回結果

}

該部分註解:  

首先是以乙個字串exp為引數,返回乙個整型數(即表示式的結果),乙個標誌變數flag,作用是處理當運算元是多位數時處理多位數的情況(**一次只能從表示式中獲取乙個字元),當運算元是多位數就把每一位獲取後再入棧。flag為0表示沒有運算元入棧,為1表示有運算元需要入棧。

然後將變數x為「=」,將該符號作為表示式的第乙個運算子入棧,然後迴圈諸葛處理表示式字串中的每乙個字元,直到遇到表示式的結束字元「=」為止。

5.主函式

int main()

最後編譯結果:

算術表示式求值(C語言棧)

題目描述 表示式計算是實現程式語言的基本問題之一,也是棧的應用的乙個典型例子。設計乙個程式,演示用運算子優先法對算數表示式求值的過程。基本要求 以字串行的形式從終端輸入語法正確的 不含變數的整數表示式。利用教科書表3.1給出的運算子優先關係,實現對算數四則混合運算表示式的求值,並仿照教科書的例3.1...

順序棧實現表示式求值(C語言實現) 棧

表示式求值一定會出現表示式中運算子的優先順序問題。運算規則 先乘除,後加減 從左算到右 先括號內,後括號外 運算子優先表 上面 中有一些比較特殊的位置 相等 左括號遇到右括號相等說明左右括號匹配。和 遇到的時候也是 我們在表示式的左邊人為的加上乙個 在表示式掃瞄完成之後再加上乙個 表示表示式掃瞄完了...

c語言算術表示式

c語言基本算數運算子如下表 加法運算子 雙目運算子,即應有兩個量參與加法運算。如a b,4 8等。具有右結合性。減法運算子 雙目運算子。但 也可作負值運算子,此時為單目運算,如 x,5等具有左結合性。乘法運算子 雙目運算子,具有左結合性。除法運算子 雙目運算子,具有左結合性。參與運算量均為整型時,結...