中缀表达式如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
#include
#include
#include
#include
#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;
}