中綴表達式如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;
}