一、说明
1、本代码只适用于操作数为一位数的运算
2、输入:以‘#’结尾的表达式
eg:3*(7-2)#
二、算法步骤
(1)初始化shu栈(存操作数)和fu栈(存操作符),将表达式起始符“#”压入fu栈
(2)读取表达式,读入第一个字符ch,如果表达式没有读完毕至“#”或者fu栈的栈顶元素不为“#”,则执行以下循环。
1、如果ch不是运算符,压入数栈,读入下一字符
2、如果ch是运算符,根据 fu栈的栈顶运算符(简记为t)和ch的优先级比较 结果,做不同处理
【1】若t<ch: 将ch压入fu栈,读入下一字符
【2】若t>ch: 弹出t,从shu栈中先后弹出两个数,进行相应运算,将结果压入shu栈
【3】若等于,则fu栈的栈顶元素是"("且ch是")",此时弹出fu栈栈顶的"(",相当于括号匹配成功,继续读入下一个字符
(3)shu栈栈顶元素为表达式求值的结果,输出
三、代码
说明
#define ERROR ' ' #define OK 1
1、链栈的存储结构
typedef struct StackNode
{
Elem c;
struct StackNode* next;
}StackNode, * LinkStack;
2、入栈
Elem Push(LinkStack &s, Elem e)
{
LinkStack p = (LinkStack)malloc(sizeof(StackNode));//申请新结点
p->c = e;//将新结点数据域置为e
p->next = s;//将新结点插入栈顶
s = p;//修改栈顶指针
return OK;
}
3、出栈
void Pop(LinkStack& s, Elem &x2)
{
LinkStack p;
if (s == NULL)
return ;//栈空
x2 = s->c;//将栈顶元素赋给x2
p = s;//用p临时保存栈顶元素空间,以备释放
s = s->next;//修改栈顶指针
free(p);//释放原栈顶元素空间
}
4、得到栈顶元素
Elem GetTop(LinkStack &s)
{
return s->c;
}
5、判断是不是运算符
Elem In(char ch)
{
if (ch >= '0' && ch <= '9')
{
return 0;//是操作符返回 1
}
else return 1;
}
6、运算符优先级
用二维数组列出优先级表格,比较时查表即可
char Precede(char c1, char c2)
{
int i=0, j=0;
char pre[7][7] = {// + - * / ( ) #//便于对照
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='} };
switch (c1) {
case '+': i = 0; break;
case '-': i = 1; break;
case '*': i = 2; break;
case '/': i = 3; break;
case '(': i = 4; break;
case ')': i = 5; break;
case '#': i = 6; break;
}
switch (c2) {
case '+': j = 0; break;
case '-': j = 1; break;
case '*': j = 2; break;
case '/': j = 3; break;
case '(': j = 4; break;
case ')': j = 5; break;
case '#': j = 6; break;
}
return(pre[i][j]);
}
7、运算
Elem Opreate(Elem &a1, Elem &x1, Elem &b1)
{
switch ((char)x1)
{
case'+':return a1+b1;
case'-':return a1 - b1;
case'*':return a1*b1;
case'/': //判断除数是否为0,若除数为零返回错误提示
if (b1!=0)
return a1/b1;
else
{
printf("Divisor can not Be zero!\n");
exit(0);
}
}
}
8、完整代码
#define _CRT_SECURE_NO_WARNINGS
#define ERROR ' '
#define OK 1
typedef int Elem;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct StackNode
{
Elem c;
struct StackNode* next;
}StackNode, * LinkStack;
Elem Push(LinkStack &s, Elem e);
void Pop(LinkStack &s, Elem &x2);
Elem GetTop(LinkStack &s);
Elem In(char ch);
char Precede(char c1, char c2);
Elem Opreate(Elem &a1, Elem &x, Elem &b1);
Elem Push(LinkStack &s, Elem e)
{
LinkStack p = (LinkStack)malloc(sizeof(StackNode));
p->c = e;
p->next = s;
s = p;
return 1;
}
void Pop(LinkStack& s, Elem &x2)
{
LinkStack p;
if (s == NULL)
return ;
x2 = s->c;
p = s;
s = s->next;
free(p);
}
Elem GetTop(LinkStack &s)
{
return s->c;
}
Elem In(char ch)
{
if (ch >= '0' && ch <= '9')
{
return 0;
}
else return 1;
}
char Precede(char c1, char c2)
{
int i=0, j=0;
char pre[7][7] = {// + - * / ( ) #
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='} };
switch (c1) {
case '+': i = 0; break;
case '-': i = 1; break;
case '*': i = 2; break;
case '/': i = 3; break;
case '(': i = 4; break;
case ')': i = 5; break;
case '#': i = 6; break;
}
switch (c2) {
case '+': j = 0; break;
case '-': j = 1; break;
case '*': j = 2; break;
case '/': j = 3; break;
case '(': j = 4; break;
case ')': j = 5; break;
case '#': j = 6; break;
}
return(pre[i][j]);
}
Elem Opreate(Elem &a1, Elem &x1, Elem &b1)
{
switch ((char)x1)
{
case'+':return a1+b1;
case'-':return a1 - b1;
case'*':return a1*b1;
case'/': //判断除数是否为0,若除数为零返回错误提示
if (b1!=0)
return a1/b1;
else
{
printf("Divisor can not Be zero!\n");
exit(0);
}
}
}
Elem main()
{
LinkStack shu=NULL;
LinkStack fu =NULL;
char ch;
Elem x, a, b;
Push(fu,(Elem)'#');//将表达式起止符压入fu栈
ch = getchar();
while (ch != '#' || (char)GetTop(fu) != '#')//表达式没读完或fu栈的栈顶元素不为'#'
{
if (In(ch)==0)
{
Push(shu,ch-'0');
ch = getchar();
}
else
{
switch (Precede((char)GetTop(fu), ch))
{
case '>'://fu栈栈顶元素优先级高
Pop(fu,x);
Pop(shu,b);
Pop(shu,a);
Push(shu, Opreate(a, x, b));
break;
case '<':
Push(fu,(Elem)ch);
ch = getchar();
break;
case'=':
Pop(fu, x);
ch = getchar();
break;
}
}
}
printf("运算结果=%d",GetTop(shu));
return 0;
}
四、运行
五、个人总结
我做这个题是根据书上例题中算法描述打的代码
1、遇到的第一个困难是怎么补充出比较运算符优先级的函数,解决方案已给出。
2、最初,链栈的数据域我设置的是char型,这导致了一些问题
比如:进行运算后,得到运算结果为15(int),将15 (int)压入shu栈,我目前已知有两种方法(数字+‘0’ 或 强制类型转化), 数字+‘0’变数字字符(貌似只有0~9的数字才行)pass,用强制类型转化,也会出现错误,应该是我用法不当。
于是最后我就干脆将数据域设为int型,需要操作符时,再强制类型转化
3、还有就是参数传递中传引用(c++中用引用,c用指针)
以上内容,如有错误,望指正!!!