栈操作实现表达式求值
Posted mygod2093725_wht
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈操作实现表达式求值相关的知识,希望对你有一定的参考价值。
算法思路:
首先应该想怎样将操作数和操作符分开放入两个栈,此时可以用asc码的大小来区分,区分开以后通过fgetc()从文件中读取字符,读取到的字符再通过入栈操作push()入栈。然后再想入栈和出栈的规则,操作数栈需要实现的功能是把每一个遇到的操作数对应的字符串,转化为数值,可以用库函数atof()来实现。而整体的实现需要考虑操作符栈的栈顶元素和即将入栈元素c的优先级,具体算法:
1.c>栈顶(optr),c入栈(optr),获取下一个字符并输出
2.c=栈顶(optr),栈顶(optr)弹出
3.c<栈顶,栈顶(optr)弹出,操作数栈(opnd)弹出两次,根据操作符的类型,计算两数的结果并入栈
最后当c为#且字符栈为空,说明计算结束;
具体代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAX 16
typedef struct stack
int base, top;
int stacksize;
Stack;//建一个栈
float* Initstack1(Stack *m);//操作数栈的初始化
char* Initstack2(Stack *m);//操作符栈的初始化
void Push1(float *p, Stack *m, float c);//入栈
void Push2(char *p, Stack *m, char c);//入栈
float Pop1(float *p, Stack *m);//出栈
char Pop2(char *p, Stack *m);//出栈
char compare(char a, char b);//比较ab两个操作符的优先级
float gettop1(float *p, Stack *m);//访问栈顶元素
char gettop2(char *p, Stack *m);//访问栈顶元素
float Ope(float a, char c, float b);//根据c操作符对ab进行运算
int compared(char a, char b);//处理多位数字
void write(float *p, Stack *m, float c);//修改操作(数字栈)
int main()
int i = 0,j; //循环标记变量
Stack opnd, optr; //定义两个栈用来存储操作数和操作符
float *p1 = NULL;char *p2 = NULL; //定义栈指针
char c,before='#'; //接收字符
char t; float a, b; //接收弹出的字符和数字
float result; //暂存ab计算结果
float d; //接受字符转化成数字的值
FILE *fp; //文件指针
errno_t err; //检查变量
char change[12] = 0 ; //定义数组用于暂存字符串
p1 = Initstack1(&opnd);
p2 = Initstack2(&optr); //栈的初始化
printf("文件中的表达式是:");
Push2(p2, &optr, '#'); //#先入栈
err = fopen_s(&fp, "E:\\\\hu.txt", "r"); //以读的方式打开E盘中的文件hu.txt
//如果err等于0则表示文件打开成功,否则打开失败
if (err != 0)
printf("Failure to open hu.txt\\n");
system("pause"); //程序暂停一下
exit(0); //程序退出
c = fgetc(fp); //从文件中获取字符,获取之后对应指针会移动到下个字符
putchar(c); //打印字符c
while ((c != '#') || (optr.base!=optr.top))
//当c为#且字符栈为空,说明计算结束,应当退出循环
if ((c >= '0' && c <= '9') || (c=='.'))//将操作数与操作符区分开
i = 0;
do
change[i] = c; //把操作数对应的字符串写进数组
i++;
before = c;
c = fgetc(fp);
putchar(c);
while (compared(c, before) == 1);
d = atof(change); //调用库函数atfo把字符串转化为浮点型的数据
Push1(p1, &opnd, d); //操作数入栈
for (j = 0; j < 12; j++) //清空数组
change[j] = 0;
else
switch (compare(c, gettop2(p2, &optr)))
case '>':
Push2(p2, &optr, c); //操作符入栈
before = c;
c = fgetc(fp); putchar(c); break;
case '=':
if (gettop2(p2, &optr) != '#')
t = Pop2(p2, &optr); //弹出操作符
before = c;
c = fgetc(fp); putchar(c);
else
t = Pop2(p2, &optr); //弹出操作符
break;
case '<':
t = Pop2(p2, &optr); b = Pop1(p1, &opnd); a = Pop1(p1, &opnd);//弹出两个操作数
result = Ope(a, t, b); //ab运算后返回运算结果
Push1(p1, &opnd, result); //运算结果入栈
break;
result = gettop1(p1, &opnd);
printf("\\n结果是:%.4f\\n", result);
fclose(fp);//关闭文件
system("pause");
return 0;
float* Initstack1(Stack *m)
float *p;
p = (float*)malloc(MAX * sizeof(float));//申请内存
m->base = m->top = 0; //初始化栈为空
m->stacksize = MAX; //设置栈的大小
return p; //p指向申请的内存块的首部,也指向栈的底部
char* Initstack2(Stack *m)
char *p;
p = (char*)malloc(MAX * sizeof(char));
m->base = m->top = 0;
m->stacksize = MAX;
return p;
void Push1(float *p, Stack *m, float c)//入栈操作(数字栈)
p[m->top] = c;
m->top++;
void Push2(char *p, Stack *m, char c)//入栈操作(字符栈)
p[m->top] = c;
m->top++;
float Pop1(float *p, Stack *m) //出栈操作(数字栈)
float t;
m->top--;
t = p[m->top];
return t;
char Pop2(char *p, Stack *m) //出栈操作(字符栈)
char t;
m->top--;
t = p[m->top];
return t;
float gettop1(float *p, Stack *m) //读取栈的数据但是不改变栈的结构(数字栈)
float t;
m->top--;
t = p[m->top];
m->top++;
return t;
char gettop2(char *p, Stack *m) //读取栈的数据但是不改变栈的结构(字符栈)
char t;
m->top--;
t = p[m->top];
m->top++;
return t;
char compare(char a, char b) //比较即将写入的操作符与栈顶操作符的优先级
switch (a)
case '^':
switch (b)
case '+':
return '>'; break;
case '-':
return '>'; break;
case '*':
return '>'; break;
case '/':
return '>'; break;
case '(':
return '>'; break;
case ')':
return '>'; break;
case '#':
return '>'; break;
case '+':
switch (b)
case '+':
return '<'; break;
case '-':
return '<'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case '(':
return '>'; break;
case ')':
return '<'; break;
case '#':
return '>'; break;
case '^':
return '<'; break;
case '-':
switch (b)
case '+':
return '<'; break;
case '-':
return '<'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case '(':
return '>'; break;
case ')':
return '<'; break;
case '#':
return '>'; break;
case '^':
return '<'; break;
case '*':
switch (b)
case '+':
return '>'; break;
case '-':
return '>'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case '(':
return '>'; break;
case ')':
return '<'; break;
case '#':
return '>'; break;
case '^':
return '<'; break;
case '/':
switch (b)
case '+':
return '>'; break;
case '-':
return '>'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case '(':
return '>'; break;
case ')':
return '<'; break;
case '#':
return '>'; break;
case '^':
return '<'; break;
case '(':
switch (b)
case '+':
return '>'; break;
case '-':
return '>'; break;
case '*':
return '>'; break;
case '/':
return '>'; break;
case '(':
return '>'; break;
case '#':
return '>'; break;
case '^':
return '<'; break;
case ')':
switch (b)
case '+':
return '<'; break;
case '-':
return '<'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case '(':
return '='; break;
case ')':
return '<'; break;
case '^':
return '<'; break;
case '#':
switch (b)
case '+':
return '<'; break;
case '-':
return '<'; break;
case '*':
return '<'; break;
case '/':
return '<'; break;
case ')':
return '<'; break;
case '#':
return '='; break;
case '^':
return '<'; break;
float Ope(float a, char c, float b)//对ab进行+-*/运算
switch (c)
case '+':
return (a + b);
case '-':
return (a - b);
case '*':
return (a * b);
case '/':
if (b == 0)
printf("零做除数!!\\n");
exit(0);
return (a / b);
case '^':
return (pow(a, b));
int compared(char a, char b) //处理多位数字
if ((((a >= '0') && (a <= '9')) && ((b >= '0') && (b <= '9'))) || (a == '.') || (b == '.'))
return 1;
else
return 0;
void write(float *p, Stack *m, float c)//修改操作(数字栈)
m->top--;
p[m->top] = c;
m->top++;
文件内容:40.2-(30-20)*0.1#
以上是关于栈操作实现表达式求值的主要内容,如果未能解决你的问题,请参考以下文章