溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

表達(dá)式求值

發(fā)布時(shí)間:2020-07-17 01:07:49 來(lái)源:網(wǎng)絡(luò) 閱讀:639 作者:我是你帆哥 欄目:編程語(yǔ)言

中綴表達(dá)式:

       把運(yùn)算符放在參與運(yùn)算的兩個(gè)操作數(shù)中間的表達(dá)式稱(chēng)作中綴表達(dá)式例:“3+4*5-6/2”,因?yàn)橹芯Y表達(dá)式計(jì)算時(shí)必須按照優(yōu)先級(jí)從左向右計(jì)算,所以計(jì)算機(jī)在進(jìn)行中綴表達(dá)式求值時(shí)比較麻煩,而后綴表達(dá)式求值比較方便。


后綴表達(dá)式:

        把運(yùn)算符放在參與運(yùn)算的兩個(gè)操作數(shù)后面的表達(dá)式稱(chēng)作后綴表達(dá)式。


例:中綴表達(dá)式:3+4*5-6/2

       轉(zhuǎn)換成后綴表達(dá)式: 3  4  5 * + 6  2  /  -


        中綴表達(dá)式:9-8*(4-3)

        轉(zhuǎn)換成后綴表達(dá)式: 9   8   4  3  -  *  -


轉(zhuǎn)換規(guī)則:

        按照優(yōu)先級(jí),把每個(gè)運(yùn)算符都移到它的兩個(gè)操作數(shù)的后面,再刪除所有的括號(hào)


后綴表達(dá)式的求值:

        從左向右一次掃描后綴表達(dá)式,遇到運(yùn)算符將將它前面的兩個(gè)運(yùn)算數(shù)取出并計(jì)算,并將結(jié)果帶入后綴表達(dá)式,直到掃描到最后一個(gè)后綴表達(dá)式。


表達(dá)式求值:

       表達(dá)式求值是棧應(yīng)用的一個(gè)基本例子,輸入一個(gè)中綴表達(dá)式,求取相應(yīng)的結(jié)果。因?yàn)橛?jì)算機(jī)不會(huì)算中綴表達(dá)式,所以我們先要將中綴表達(dá)式轉(zhuǎn)換成相應(yīng)的后綴表達(dá)式再進(jìn)行計(jì)算。要轉(zhuǎn)成相應(yīng)的后綴表達(dá)式,我們應(yīng)該創(chuàng)建兩個(gè)棧,一個(gè)用來(lái)存放操作數(shù),一個(gè)用來(lái)存放運(yùn)算符。


中綴表達(dá)式求值的算法

         從左向右掃描中綴表達(dá)式,若遇到操作數(shù),則直接壓入運(yùn)算數(shù)棧,若遇到符號(hào),則與運(yùn)算符棧的棧頂元素比較,若讀取符號(hào)的優(yōu)先級(jí)高,則讀取的符號(hào)進(jìn)棧;否則讓運(yùn)算符棧的棧頂符號(hào)退棧并且將運(yùn)算數(shù)棧最上面的兩個(gè)元素退棧,然后將運(yùn)算的結(jié)果壓入運(yùn)算數(shù)棧,一直這樣循環(huán)直到讀取的符號(hào)的優(yōu)先級(jí)高于運(yùn)算符棧頂元素。

因?yàn)槊孔x取一個(gè)符號(hào)就要與運(yùn)算符棧的棧頂元素進(jìn)行優(yōu)先級(jí)比較,我們不能每次都寫(xiě)一大堆if else語(yǔ)句,所以我們可以將運(yùn)算符的優(yōu)先級(jí)的結(jié)果放到一個(gè)二維數(shù)組中,然后利用查表法,判斷優(yōu)先級(jí)。

因?yàn)楫?dāng)我們讀取第一個(gè)符號(hào)時(shí),運(yùn)算符棧還是個(gè)空棧,為了方便比較,我們?cè)跅5讐喝胍粋€(gè)#,并規(guī)定#的優(yōu)先級(jí)最低,并將“#”作為表達(dá)式輸入結(jié)束的標(biāo)志。

為了方便索引:我們?cè)賱?chuàng)建一個(gè)一維數(shù)組,

char arr[7] = { '+' , '-', '*', '/', '(', ')', '#' };通過(guò)它來(lái)找到棧頂符號(hào)和讀取符號(hào)在優(yōu)先級(jí)數(shù)組中的位置。

表達(dá)式求值

實(shí)現(xiàn):輸入一個(gè)合法的中綴表達(dá)式,只包含“+ - * /”四種運(yùn)算符,并以“#”作為結(jié)束標(biāo)志。


//函數(shù)聲明:

#include<stdio.h>
#include<stdlib.h>

#define STACK_INIT_MEMORY 20               //初始時(shí)開(kāi)辟棧的內(nèi)存大小
#define STACK_GROW_MEMORY 10               //當(dāng)棧滿(mǎn)時(shí),追加內(nèi)存的大小

const char arr[7];              //聲明一個(gè)存放運(yùn)算符的一維數(shù)組,作為索引
void init_priority_list(char list[][7]);      //初始化符號(hào)表

typedef struct stack_num            //聲明一個(gè)存放運(yùn)算數(shù)的結(jié)構(gòu)體類(lèi)型
{
	int *esp;                //棧頂指針
	int *ebp;                //棧底指針
	int size;                 //記錄當(dāng)前??臻g最多能存幾個(gè)元素
}stack_num;
void creatstack_num(stack_num *S);          //創(chuàng)建存放運(yùn)算數(shù)的棧
void push_num(stack_num *S, int x);         //將參數(shù)x中的數(shù)壓入運(yùn)算數(shù)棧中
int pop_num(stack_num *S, int *x);         //彈出棧頂元素,并通過(guò)形參x帶回

typedef struct stackpop_opreation           //聲明一個(gè)存放運(yùn)算符的結(jié)構(gòu)體類(lèi)型
{
	char *esp;                   //棧頂指針
	char *ebp;                   //棧底指針
	int size;                    //記錄當(dāng)前??臻g最多能存幾個(gè)元素
}stack_operation;
void creatstack_operation(stack_operation *S);      //創(chuàng)建一個(gè)存放運(yùn)算符的棧
void push_operation(stack_operation *S, char symbol);  //將符號(hào)壓入運(yùn)算符棧中
int pop_opreation(stack_operation *S, char *top);    //將運(yùn)算符棧中的棧頂元素彈出




//函數(shù)實(shí)現(xiàn):

char judge_priority(stack_operation* S, char c);       //判斷讀取的運(yùn)算符與棧頂符號(hào)的優(yōu)先級(jí),并返回
int operation(int a, char symbol, int b);          //對(duì)運(yùn)算數(shù)進(jìn)行相的運(yùn)算,并將結(jié)果返回
int judge_num(char c);          //判斷讀取的是符號(hào)還是數(shù)字,如果是數(shù)字返回1


#include"expression.h"

const char arr[7] = { '+', '-', '*', '/', '(', ')', '#' };     //通過(guò)arr[7]來(lái)查找list[][]中的優(yōu)先級(jí)

void init_priority_list(char list[][7])          //初始化優(yōu)先級(jí)列表
{
	int arr2[7] = { 1, 1, 2, 2, 3, 0, -1 };    //列作為棧頂元素,行代表讀取的運(yùn)算符
	for (int i = 0; i < 7; i++)
	{
		for (int j = 0; j < 7; j++)
		{
			if ((i == 4 && j == 5) || (i == 6 && j == 6)  //令'('與‘)’,‘#’與‘#’優(yōu)先級(jí)相同
				list[i][j] = '=';
			else
			{
				if (arr2[i] >= arr2[j])
					list[i][j] = '>';         //棧頂優(yōu)先級(jí)高
				else if (arr2[i] <= arr2[j])
					list[i][j] = '<';     //讀取的運(yùn)算符優(yōu)先級(jí)高
			}

		}
	}
}

void creatstack_num(stack_num *S)              //創(chuàng)建運(yùn)算數(shù)棧
{
	S->ebp = (int *)malloc(sizeof(int)* STACK_INIT_MEMORY);
	if (S->ebp == NULL)           //判斷動(dòng)態(tài)內(nèi)存是否開(kāi)辟成功
		exit(1);
	S->size = STACK_INIT_MEMORY;             
	S->esp = S->ebp;            //讓棧頂指針指向棧底
}
void push_num(stack_num *S, int x)
{
	if (S->esp - S->ebp >= S->size)       //判斷當(dāng)前棧是否已滿(mǎn)
	{                         //棧滿(mǎn)追加空間
		S->ebp = (int *)realloc(S->ebp, sizeof(int)*(S->size + STACK_GROW_MEMORY));
		if (S->ebp == NULL)
			exit(1);
		S->esp = S->ebp + S->size;  //讓棧頂指針向后偏移指向要入棧的位置
		S->size += STACK_GROW_MEMORY;  //更新棧的size
	}
	*S->esp++ = x;
}
int pop_num(stack_num *S, int *x)               
{
	if (S->esp == S->ebp)
		return 0;           //如果是空棧,則返回0
	else
	{
		*x = *--S->esp;
		return 1;                                             //如果彈出成功,返回1,并將彈出的元素保存在x中帶回
	}
}




void creatstack_operation(stack_operation *S)           //創(chuàng)建運(yùn)算符棧
{
	S->ebp = (char *)malloc(sizeof(char)*STACK_INIT_MEMORY);
	if (S->ebp == NULL)
		exit(1);                                               //判斷動(dòng)態(tài)內(nèi)存是否開(kāi)辟成功
	S->size = STACK_INIT_MEMORY;
	S->esp = S->ebp;
}
void push_operation(stack_operation *S, char symbol)
{
	if (S->esp - S->ebp >= S->size)                            //如果棧滿(mǎn)則追加空間
	{
		S->ebp = (char *)realloc(S->ebp, sizeof(char)*(S->size += STACK_GROW_MEMORY));
		if (S->ebp == NULL)
			exit(1);
		S->ebp = S->ebp + S->size - STACK_GROW_MEMORY;
	}
	*S->esp++ = symbol;
}
int pop_opreation(stack_operation *S, char *top)
{
	if (S->esp == S->ebp)
		return 0;                                                                   //如果棧是空棧,則返回0
	else
		*top = *--S->esp;        //否則將彈出的勻速保存在top中帶回
	return 1;
}


char judge_priority(stack_operation* S, char c)     //判斷棧頂運(yùn)算符與讀取的運(yùn)算符的優(yōu)先級(jí)
{
	char list[7][7];
	init_priority_list(list);           //初始化優(yōu)先級(jí)表
	int line = 0;                                  
	int row = 0;
	for (line = 0; line < 7; line++)
	{
		if (arr[line] == *(S->esp - 1))        //將棧頂符號(hào)在arr[]中的位置作為行下標(biāo)
			break;
	}
	for (row = 0; row < 7; row++)
	{
		if (arr[row] == c)      //將讀取的運(yùn)算符在arr[]中的位置作為列下標(biāo)
			break;
	}
	return list[line][row];      //通過(guò)優(yōu)先級(jí)表,返回優(yōu)先級(jí)關(guān)系
}


int operation(int a, char symbol, int b)        
{
	int ret = 0;
	switch (symbol)
	{
	case '+':
		ret = a + b;
		break;
	case '-':
		ret = a - b;
		break;
	case '*':
		ret = a*b;
		break;
	case '/':
		ret = a / b;
		break;
	default:
		break;
	}
	return ret;
}


int judge_num(char c)             //判斷讀取的是不是數(shù)字
{
	int i = 0;
	for (i = 0; i < 7; i++)
	{
		if (arr[i] == c)                        
			break;
	}
	if (i == 7)
		return 1;            //如果是數(shù)字則返回1
	else
		return 0;                 //如果不是數(shù)字則返回0
}



#include"expression.h"
int main()
{

	stack_num num_stack;
	creatstack_num(&num_stack);               //建立一個(gè)運(yùn)算數(shù)棧
	stack_operation operator_stack;
	creatstack_operation(&operator_stack);         //建立一個(gè)運(yùn)算符棧
	int c;
	char symbol;
	int a = 0;
	int b = 0;
	int ret = 0;
	push_operation(&operator_stack, '#');       //將‘#’入棧,作為運(yùn)算符棧的棧底
	c=getchar();
	while (c!='#'||*(operator_stack.esp-1)!='#')     //接受表達(dá)式并且判斷表達(dá)式是否輸入完畢
	{	
		if (judge_num(c))            //如果是數(shù)字則進(jìn)入運(yùn)算數(shù)棧
		{
			int num = 0;
			while (judge_num(c))        //把連續(xù)的char類(lèi)型的數(shù)字全部讀取并轉(zhuǎn)化成相應(yīng)的整數(shù)
			{
				num = num * 10 + (c-'0');   //因?yàn)檫@是的運(yùn)算數(shù)是char類(lèi)型,所以先要轉(zhuǎn)換成int
				c = getchar();
			}
			push_num(&num_stack,num);       //將運(yùn)算數(shù)入棧
		}
		else                                                        
		{
			switch (judge_priority(&operator_stack,c))   //判斷讀取的運(yùn)算符與棧頂符號(hào)的優(yōu)先級(jí)關(guān)系
			{
			case '<':      //如果讀取的符號(hào)優(yōu)先級(jí)高,則直接進(jìn)入運(yùn)算符棧
				push_operation(&operator_stack, c);
				c=getchar();
				break;
			case '>':           //如果讀取的符號(hào)優(yōu)先級(jí)低,則棧頂符號(hào)退棧,將運(yùn)算結(jié)果入棧
				pop_opreation(&operator_stack, &symbol); //則棧頂符號(hào)退棧
				pop_num(&num_stack, &b);                
				pop_num(&num_stack, &a)        // 將運(yùn)算數(shù)棧棧頂?shù)膬蓚€(gè)元素彈出
				ret=operation(a, symbol, b);  //將這兩個(gè)元素進(jìn)行運(yùn)算
				push_num(&num_stack, ret);     //將運(yùn)算結(jié)果入棧
				break;
			case '=':     //當(dāng)讀取到“)”時(shí)則一直退棧直到遇到“(”
				pop_opreation(&operator_stack, &symbol);
				c=getchar();
				break;
			default:
				break;
			}
		}		

	}
	printf("%d\n", *(num_stack.esp-1));     //將運(yùn)算數(shù)棧最后剩下的數(shù)輸出
	system("pause");
	free(num_stack.ebp);
	free(operator_stack.ebp);
	return 0;
}


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI