Thursday, February 9, 2012

数据结构:利用栈的操作实现表达式求值

2008-12-31 by zhiwei  

数据结构课程中,在对桟的学习中我会遇到关于表达式求值问题,下面是我自己写的关于表达式求值的代码,其中还有很多不足之处,可以参考下思路。

如题:下面是我自己写的代码,一个头文件一个CPP文件。
以下是CPP文件(EvaluateExpression.cpp)源码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "EvaluateExpression.h"
 
char OP[]={'+','-','*','/','(',')','#'};
OPND_Stack OPND;//定义操作数栈变量 
OPTR_Stack OPTR;//定义运算符栈变量 
char x;//运算符出栈时起缓冲作用
int main()
{
	char *str=new char[STACK_INIT_SIZE],theta;//存放表达式
	OPND_Type t=0,a,b;	 
	printf("若你要输入负数如-4则就这样输入(0-4)\n");
	printf("请输入表达式(以#结束):");
	Init_OPTR_Stack(OPTR); Push_OPTR(OPTR,'#');
	Init_OPND_Stack(OPND); scanf("%s",str);	
	while(*str!='#'||GetTop_OPTR(OPTR)!='#')
	{
		if(!In(*str,OP))
		{
			t=0;
			while(!In(*str,OP))
			{
				if(*str<'0'||*str>'9')
				{
					printf("表达式有非法输入!\n");
					exit(0);
				}
				t*=10;
				t=*str-'0'+t;
				str++;
			}
			Push_OPND(OPND,t);
		}
		else
		{		
			switch(Precede(GetTop_OPTR(OPTR),*str))
			{
				case '<': Push_OPTR(OPTR,*str); str++; break;
				case '=': Pop_OPTR(OPTR,x);   str++; break;
				case '>': Pop_OPTR(OPTR,theta); Pop_OPND(OPND,b); Pop_OPND(OPND,a); Push_OPND(OPND,Operate(a,theta,b)); break;
			}
		}
	}
	printf("结果是: %d\n",GetTop_OPND(OPND));
	return 0;
}

以下是.h文件源码(EvaluateExpression.h)实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**************************************
  Name: 表达式求值的实现 
  Author: mail@chenzhiwei.cn
  Date: 2008/12/25
  Copyright http://chenzhiwei.net
  PS:还有些功能没有实现,如负数输入问题,还有运算符连续出现问题
**************************************/
#include "stdio.h"
#include "stdlib.h"
#define STACK_INIT_SIZE 100
typedef  char OPTR_Type;
typedef  int  OPND_Type;
#define overflow -2
typedef int  Status;
#define OK 1
#define ERROR 0 
typedef struct{
	OPND_Type *base;
	OPND_Type *top;
	int       stacksize;
}OPND_Stack;//定义操作数栈的结构;
typedef struct{
	OPTR_Type *base;
	OPTR_Type *top;
	int       stacksize;
}OPTR_Stack;//定义运算符栈的结构;
//-------------下为函数声明,其实作为头文件不用声明也行-----------------//
//1.初始化空栈;
Status Init_OPND_Stack(OPND_Stack &S);
Status Init_OPTR_Stack(OPTR_Stack &S);
//2.进栈操作;
Status Push_OPTR(OPTR_Stack &S,OPTR_Type e);
Status Push_OPND(OPND_Stack &S,OPND_Type e);
//3.出栈操作;
Status Pop_OPTR(OPTR_Stack &S,OPTR_Type &e);
Status Pop_OPND(OPND_Stack &S,OPND_Type &e);
//4.返回栈顶元素
OPTR_Type GetTop_OPTR(OPTR_Stack S);
OPND_Type GetTop_OPND(OPND_Stack S);
/*以下是一些基本操作实现;*/
 
Status Init_OPTR_Stack(OPTR_Stack &S)
{
    S.top=(OPTR_Type *)malloc(STACK_INIT_SIZE*sizeof(OPTR_Type));
	S.base=S.top;
	S.stacksize=STACK_INIT_SIZE;
	return OK;
}//初始化空栈;
Status Init_OPND_Stack(OPND_Stack &S)
{
    S.top=(OPND_Type *)malloc(STACK_INIT_SIZE*sizeof(OPND_Type));
	S.base=S.top;
	S.stacksize=STACK_INIT_SIZE;
	return OK;
}//初始化空栈;
 
Status Push_OPTR(OPTR_Stack &S,OPTR_Type e)
{
    if(S.top-S.base>=S.stacksize)
	{
		printf("内存超限!\n");
		exit(overflow);
	}
	*S.top=e;
	S.top++;
	return OK;
}//进栈操作;
Status Push_OPND(OPND_Stack &S,OPND_Type e)
{
    if(S.top-S.base>=S.stacksize)
	{
		printf("内存超限!\n");
		exit(overflow);
	}
	*S.top=e;
	S.top++;
	return OK;
}//进栈操作;
 
Status Pop_OPTR(OPTR_Stack &S,OPTR_Type &e)
{
    if(S.top==S.base) return ERROR;
	e=*--S.top;
	return OK;
}//出栈操作;
Status Pop_OPND(OPND_Stack &S,OPND_Type &e)
{
    if(S.top==S.base) return ERROR;
	e=*--S.top;
	return OK;
}//出栈操作;
 
OPTR_Type GetTop_OPTR(OPTR_Stack S)
{
	if(S.top==S.base) return '0';
	return *(S.top-1);
}
OPND_Type GetTop_OPND(OPND_Stack S)
{
	if(S.top==S.base) return '0';
	return *(S.top-1);
}
 
Status In(OPTR_Type c,OPTR_Type *p)
{
	while(*p!='\0')
	{
		if(*p==c)
		{
			return 1;
		}
		p++;
	}
	return 0;
}
 
OPTR_Type Precede(char prior,char next)
{
	if(prior=='+'||prior=='-')
	{
		if(next=='*'||next=='('||next=='/')
		   return '<';
		else return '>';
	}
	else if(prior=='*'||prior=='/')
	{
		if(next=='(')
		   return '<';
		else return '>';
	}
	else if(prior=='(')
	{
		if(next=='#')
		   exit(1);
		else if(next==')')
			return '=';
		else return '<';
	}
	else if(prior==')')
	{
		if(next=='(')
		   exit(1);
		else return '>';
	}
	else if(prior=='#') 
	{
		if(next=='#')
			return '=';
		else if(next==')')
			exit(1);
		else return '<';
	}
	else exit(1);
}
 
OPND_Type Operate(OPND_Type a,char c,OPND_Type b)
{
	OPND_Type temp;
	switch(c)
	{
		case '+':temp=a+b;break;
		case '-':temp=a-b;break;
		case '*':temp=a*b;break;
		case '/':temp=a/b;break;
	}
	return temp;
}

PS:不过还有些功能没有实现,如负数输入问题,还有运算符连续出现问题,有兴趣的朋友可以再优化一下。刚刚觉得自己的学习有了点起色,又要放假了,真无奈。。。

© 2008, chenzhiwei.net. 版权所有.
本文永久链接:http://chenzhiwei.net/2008/12/evaluate-expression/

Speak Your Mind