中綴表達式轉換爲後綴表達式並求值(棧的使用)


 中綴表達式如2*3+(4-3), 其運算符一般出現在操作數之間, 因此稱爲中綴表達式,也就是大家編程中寫的表達

式。編譯系統不考慮表達式的優先級別, 只是對表達式從左到右進行掃描, 當遇到運算符時, 就把其前面的兩

個操作數取出, 進行操作。爲達到上述目的, 就要將中綴表達式進行改寫,變爲後綴表達式 如上面的表達式

2*3+(4-3), 就變爲2 3 * 4 3 - + ;

後綴表達式中不含有括號, 且後綴表達式的操作數和中綴表達式的操作數排列次序完全相同, 只是運算符的

次序發生了改變。我們實現的時候,只需要用一個特定工作方式的數據結構(棧),就可以實現。

其中stack op;用來存放運算符棧。數組ans用來存放後綴表達式。

算法思想:

從左到右掃描中綴表達式,是操作數就放進數組ans的末尾。

如果是運算符的話,分爲下面3種情況:

1)如果是‘(’直接壓入op棧。

2)如果是‘)’,依次從op棧彈出運算符加到數組ans的末尾,知道遇到'(';

3) 如果是非括號,比較掃描到的運算符,和op棧頂的運算符。如果掃描到的運算符優先級高於棧頂運算符

則,把運算符壓入棧。否則的話,就依次把棧中運算符彈出加到數組ans的末尾,直到遇到優先級低於掃描

到的運算符或棧空,並且把掃描到的運算符壓入棧中。

就這樣依次掃描,知道結束爲止。

如果掃描結束,棧中還有元素,則依次彈出加到數組ans的末尾,就得到了後綴表達式。

下面是程序代碼和問題描述:

問題描述:
請編寫程序將一箇中綴表達式轉換爲後綴表達式。
輸入
僅一行,是一箇中綴表達式。輸入的符號中只有這些基本符號“0123456789+-*/()”,並且不會出現形如2*-3的格式,所有數字都是個位數,“/”表示整除運算。
輸出
僅一行,是轉換後的後綴表達式。數字之間、運算符之間、數字和運算符之間都用一個空格隔開(參見樣例)。
樣例
.in
8-(3+2*6)/5+4
.out
8 3 2 6 * + 5 / - 4 +


以下附全部代碼

/*
 * =====================================================================================
 *
 *       Filename:  math.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2013年09月12日 22時45分49秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  gaoyuan, 
 *        Company:  Class 1204 of Computer Science and Technology
 *
 * =====================================================================================
 */

#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXSIZE 100

typedef struct number
{
	int num[MAXSIZE];
	int len;
}Number;

typedef struct operate
{
	char operate[MAXSIZE];
	int len;
}Operate;

int empty_num(Number *s)
{
	if (s->len == -1)
	{
		return 1;
	}

	return 0;
}

int push_num(Number *s, int x)
{
	if (s->len == MAXSIZE - 1)
	{
		return 0;
	}
	else
	{
		s->len++;
		s->num[s->len] = x;
		return 1;
	}
}

int pop_num(Number *s, int * data)
{
	if (empty_num(s) == 1)
	{
		return 0;
	}
	else 
	{
		*data = s->num[s->len];
		s->len--;
		return 1;
	}
}

int top_number(Number *s, int *data)
{
	if (empty_num(s) == 1)
	{
		return 0;
	}

	else 
	{
		*data = s->num[s->len];
		return 1;
	}
}
Number * init_number()
{
	Number *m;

	m = malloc(sizeof(Number));
	m->len = -1;

	return m;
}

int empty_operate(Operate *s)
{
	if (s->len == -1)
	{
		return 1;
	}

	return 0;
}

int push_operate(Operate *s, char oper)
{
	if (s->len == MAXSIZE - 1)
	{
		return 0;
	}

	else
	{
		s->len++;
		s->operate[s->len] = oper;
		return 1;
	}
}

int pop_operate(Operate *s, char *oper)
{
	if (empty_operate(s) == 1)
	{
		return 0;
	}

	else 
	{
		*oper = s->operate[s->len];
		s->len--;
		return 1;
	}
}

char top_operate(Operate *s)
{
	if (s->len == -1)
	{
		return 'n';
	}

	else
	{
		return s->operate[s->len];
	}
}

Operate * init_operate()
{
	Operate *m;

	m = malloc(sizeof(Operate));
	m->len = -1;

	return m;
}

int if_operte(char c)
{
	if (c == '*' || c == '+' || c == '-' || c == '/' || c == '(' || c == ')')
	{
		return 1;
	}

	return 0;
}

int level(char a)
{
	if (a == '+' || a == '-')
	{
		return 1;
	}

	else if (a == '*' || a == '/')
	{
		return 2;
	}

	else if (a == '(' || a == ')')
	{
		return 3;
	}

	else if (a == '=')
	{
		return 0;
	}
}

int judge_level(char a, char b)
{
		return (level(a) - level(b));
}
void translate(char * quest, char * ans ,int n)
{
	Operate *tmp;
	char c;

	tmp = init_operate();
	push_operate(tmp, '=');

	while (n--)
	{
//		printf("%c\n", *quest);
		if ((*quest) >= '0' && (*quest) <= '9')
		{
			*ans++ = *quest;
		}

		else if ((*quest) == '(')   //如果是(,直接壓棧
		{
			push_operate(tmp, (*quest));
		//	printf("ya %c\n", top_operate(tmp));
		}

		else if ((*quest) == ')')  //如果是),彈棧到數組,直到遇到(
		{
			while (top_operate(tmp) != '(')
			{
				pop_operate(tmp, &c);
				*ans++ = c;
		//		printf("c = %c\n", c);
				*ans++ = ' ';
		//		printf("ding %c %d\n", top_operate(tmp), tmp->len);
		//		getchar();
			}
			pop_operate(tmp, &c);
		}

		else if (if_operte(*quest) == 1)
		{
			if (top_operate(tmp) == '(')
			{
				push_operate(tmp, *quest);
			}

			else if (judge_level(*quest, top_operate(tmp)) > 0)  //如果掃描到的運算符優先級高於棧頂優先級,將運算符壓棧
			{
				push_operate(tmp, *quest);
			}

			else if (judge_level(*quest, top_operate(tmp)) <= 0)  //如果掃描到的運算符優先級低於或等於棧頂優先級,依次彈出棧頂元素到數組,直到遇到優先級比掃描到的優先級低的
			{
				while (judge_level((*quest), top_operate(tmp)) <= 0 && (top_operate(tmp) != '='))
				{
					pop_operate(tmp, &c);
		//			printf("tan %c\n", c);
					*ans++ = c;
					*ans++ = ' ';
			//		*ans++ = *quest;
				}
				push_operate(tmp, *quest);
		//		printf("棧頂%c\n", top_operate(tmp));

			}
		}

		if (( if_operte(*quest)  == 0) &&  (if_operte(*(quest + 1)) == 1))
		{
			*ans++ = ' ';
		}
		quest++;
	}

//	printf("剩餘%d\n", tmp->len);
	while (tmp->len != 0)
	{
		pop_operate(tmp, &c);
		*ans++ = c;
		*ans++ = ' ';
	}

	*ans = '\0';
}

int calculate (int num1, int num2, char ope)
{
	int result;
	
	switch (ope)
	{
		case '*':
			result = num1 * num2;
			break;
		case '/':
			result = num1 / num2;
			break;
		case '+':
			result = num1 + num2;
			break;
		case '-':
			result = num1 - num2;
			break;
	}

	return result;
}

void result (char * string, int n)
{
	char exp;
	char *p;
	int num, num3;
	int num1, num2;
	int i = 0, j = 0;
	int flag = 0;
	int tmp[MAXSIZE];
	char ope[MAXSIZE];
	Operate *operate;
	Number  *number;


	operate = init_operate();
	number  = init_number();
	p = string;

	while (*p != '\0')
	{
		num = 0;
		flag = 0;


		while ((*p) >= '0' && (*p) <= '9')
		{
			flag = 1;
			num = (*p - '0') + num * 10;
			p++;
		}

		if (flag == 1)
		{
			tmp[i++] = num;
			push_num(number, num);
		//	printf("壓棧%d大小%d\n", num, number->len);
		}

		if (if_operte(*p) == 1)
		{
			pop_num(number, &num1);
			pop_num(number, &num2);


		//	printf("彈出%d %d\n", num1, num2);
		//	printf("還剩%d\n", number->len);
			push_num(number, calculate(num2, num1, *p));
			top_number(number, &num3);
		///	printf("%d %c %d = %d\n", num2, *p, num1, num3);
		//	printf("壓棧%d\n", calculate(num2, num1, *p));
		
		}

		p++;
	}

	top_number(number, &num);
	printf("結果是%d\n", num);

}

int main(int argc, char *argv[])
{
	char string1[100];
	char string2[100];

	char *p, *q;

	printf("請輸入\n");
	scanf("%s", string1);
//	printf("%s\n", string1);
	string1[strlen(string1)] = '\0';
//	printf("完了\n");

	p = string1;
	q = string2;

	translate(p, q, strlen(string1));

	printf("後綴表達式爲\n%s\n", string2);
	string2[strlen(string2)] = '\0';

	result(string2, strlen(string2));


	return EXIT_SUCCESS;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章