栈操作实现表达式求值

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#


以上是关于栈操作实现表达式求值的主要内容,如果未能解决你的问题,请参考以下文章

栈的应用——表达式求值

leetcode 150. 逆波兰表达式求值(栈)

150. 逆波兰表达式求值-栈

Leetcode No.150 逆波兰表达式求值(栈)

Stack实现表达式的求值

使用栈实现表达式求值