利用栈求表达式的值
(1)问题描述
用c或c++语言编写程序实现表达式求值,即验证某算术表达式的正确性,若正确,则计算该算术表达式的值。表达式从键盘输入后,按以下方法对该表达式中成份逐个进行分析:
(1)若是数字,则判断该数字的合法性。若合法,则压入数据到堆栈中。
(2)若是规定的运算符,则根据规则进行处理。在处理过程中,将计算该表达式的值。
(3)若是其它字符,则返回错误信息。
若上述处理过程中没有发现错误,则认为该表达式合法,并打印处理结果。
(2)要求
用栈数据结构实现,且程序中应主要编写如下几个功能函数:
void initstack():初始化栈。
int Make_str():语法检查并计算。
int push_operate(int operate):将操作码压入堆栈。
int push_num(double num):将操作数压入堆栈。
int procede(int operate):处理操作码。
int change_opnd(int operate):将字符型操作码转换成优先级。
int push_opnd(int operate):将操作码压入堆栈。
int pop_opnd():将操作码弹出堆栈。
int caculate(int cur_opnd):简单计算+,-,*,/,(,)。
double pop_num():弹出操作数。
- 主要任务和目标
用c语言编写程序实现表达式求值,输入形式为0到9数字和基础运算符,输出的形式为数字,程序能实现的功能为整数与整数的加减乘除和带括号运算。
测试数据:
(1)结尾必须输入‘#’字符,若没有输入,则重新输入。
(2)若是数字,则判断该数字的合法性。若合法,则压入数据到堆栈中。
(3)若是规定的运算符,则根据规则进行处理。在处理过程中,将计算该表达式的值。
(4)若是其它字符,则返回错误信息,并重新输入。
(5)若数字与运算符皆合法,则判断运算表达式是否合法,若不合法则重新输入。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#define SIZE 50
typedef int Elemtype;
//数字栈结构体
typedef struct {
Elemtype elem[SIZE];
int top;
int base;
} SeqStack;
//运算符结构体
typedef struct {
char a[SIZE];
char top;
char base;
} SqStack;
//初始化
void Init1(SeqStack *S1) {
S1->top = -1;
}
void Init2(SqStack *S2) {
S2->top = -1;
}
//入栈
int Push1(SeqStack *S1, Elemtype x) {
if (S1->top == SIZE - 1)
return false;
S1->top++;
S1->elem[S1->top] = x;
return true;
}
int Push2(SqStack *S2, char x) {
if (S2->top == SIZE - 1)
return false;
S2->top++;
S2->a[S2->top] = x;
return true;
}
//出栈
int Pop1(SeqStack *S1, Elemtype *x) {
if (S1->top == -1)
return false;
else {
*x = S1->elem[S1->top];
S1->top--;
return true;
}
}
int Pop2(SqStack *S2, char *x) {
if (S2->top == SIZE - 1)
return false;
else {
*x = S2->a[S2->top];
S2->top--;
return true;
}
}
//读栈顶元素
int GetTop1(SeqStack *S1 ) {
Elemtype x;
if (S1->top == -1)
return false;
else {
x = S1->elem[S1->top];
return x;
}
}
int GetTop2(SqStack *S2) {
char x;
if (S2->top == -1)
return false;
else {
x = S2->a[S2->top];
return x;
}
}
//判断字符是否合法
int IsStr(char c) {
int a;
switch (c) {//是运算符返回1 其他返回-1
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
a = 1;
break;
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
a = 0;
break;
default: {
a = -1;
break;
}
}
return a;
}
char Precede(char a, char b) {
//比较运算符的优先级
char f;
if (a == '+' || a == '-') {
if (b == '+' || b == '-' || b == ')' || b == '#')
f = '>';
else if (b == '*' || b == '/' || b == '(')
f = '<';
} else if (a == '*' || a == '/') {
if (b == '+' || b == '-' || b == '*' || b == '/' || b == ')' || b == '#')
f = '>';
else if (b == '(')
f = '<';
} else if (a == '(') {
if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(')
f = '<';
else if (b == ')')
f = '=';
} else if (a == ')') {
if (b == '+' || b == '-' || b == '*' || b == '/' || b == ')' || b == '#')
f = '>';
} else if (a == '#') {
if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(')
f = '<';
else if (b == '#')
f = '=';
} else
f = '!';
return f;
}
int Operate(int i, char theta, int j) {
//计算a(theta)b结果
int result;
switch (theta) {
case '+':
result = i + j;
break;
case '-':
result = i - j;
break;
case '*':
result = i * j;
break;
case '/':
result = i / j;
break;
}
return result;
}
//计算表达式
int Parse() {
SeqStack S1;
SqStack S2;
Init1(&S1);
Init2(&S2);
int IsStr(char c);
char ch[SIZE];
int a, b, c, tot;
char x, oper;
int t = 0;//遍历字符数组
flag:
int i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, len = 0;
printf("提示:输入表达式请在英文状态下输入,字符之间不能出现空格,结尾请输入‘#’字符\n");
printf("输入:");
scanf("%s", ch);
while (ch[i] != '\0') {
len++;
i++;
}
if (ch[len - 1] != '#') {
printf("结尾未输入‘#’,请重新输入\n");
free(ch);
goto flag;
}
while (ch[m] != '\0') {
if (IsStr(ch[m]) == -1) {
printf("输入错误字符!\n");
goto flag;
}
m++;
}
while (ch[k] != '\0') {
if (ch[k] == '/' && ch[k + 1] == '0') {
printf("除数不能为零!\n");
goto flag;
}
k++;
}
while (ch[n] != '\0') {
if (ch[n] == '/' || ch[n] == '*' && ch[n + 1] == ')') {
printf("运算表达式错误!\n");
goto flag;
} else if (ch[n] == '(' && ch[n + 1] == '*' || ch[n + 1] == '/') {
printf("运算表达式错误!\n");
goto flag;
}
n++;
}
Push2(&S2, '#');
while (ch[t - 1] != '#' ) {
printf(" %c\n", ch[t]);
if (IsStr(ch[t]) == 0) {
tot = ch[t] - 48;
Push1(&S1, tot);
} else if (IsStr(ch[t]) == 1) {
switch (Precede(GetTop2(&S2), ch[t])) {
case'>': {
Pop2(&S2, &oper);
Pop1(&S1, &b);
Pop1(&S1, &a);
Push1(&S1, Operate(a, oper, b) );
break;
}
case'<': {
Push2(&S2, ch[t]);
break;
}
case'=': {
Pop2( &S2, &x);
break;
}
}
}
t++;
}
printf("结果为:%d\n", GetTop1(&S1));
return 0;
}
int main() {
Parse();
return 0;
}