利用栈来完成表达式求值

利用栈来完成表达式求值

一个表达式要求值,分为操作数部分和运算符部分,求值的过程便是运算符对操作数进行操作。
首先我们定义两个栈,一个栈存放运算符,先放个#进去,代表开始,然后记得结束最后一个字符也是#,这样代表结束。然后建立一个栈存放操作数。
算法:
定义一个字符来getchar字符,然后判断。首先判断这是字符是不是#或者现在运算符栈的top是不是#,如果两个都是#那么运算完成。
然后判断,不是运算符的话就存入操作数栈内
如果是运算符,那么判断,这个运算符与现在运算符栈top位置的运算符的关系,两者的优先性,根据优先性来进行下一步操作
比如top位置是‘-‘,然后字符是‘)’,那么在运算符栈内肯定有一个“(”与字符‘)’对应,如果没有,那么肯定输入有问题。因为有’(‘在栈内所以‘-’的优先性是大于‘)’的,获得字符‘>’所以进行运算,也就是减。首先从操作数里面取top出来,作为减数,然后top–,然后再取top作为被减数,因为存放顺序的关系,先进去的肯定是在前面。然后在字符“>”的情况下是不进行getchar的,因为也就进行了运算,所以现在字符还是‘)’,然后现在运算符栈内的就是‘(’,如果不是,那么继续运算,因为可能出现(7+2+2)这种,那么多算一次‘>’的情况就行。然后(与)判断结果是=,让运算符栈内(消掉,然后现在括号内的运算已经完毕,然后getchar获取下一个字符,继续进行判断!

代码可以直接运行

#include"consts.h"

typedef struct {
	char S[100];
	int top;
}CHARStack;

void InitStack(CHARStack *S) {
     S->top = -1;
}
void Push(CHARStack* S, char ch) {
	if (S->top >= 99) {
		printf("栈满!\n");
		exit(0);
	}
	else {
		S->top++;
		S->S[S->top] = ch;
	}
}
char GetTop(CHARStack* S) {
	if (S->top==-1) {
		printf("栈空!\n");
		exit(0);
	}
	else {
		
		return S->S[S->top];
	}
}

int TRIn(char ch) {                           //是运算符就返回1,不是运算符返回0
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '#') {
		return 1;
	}
	else return 0;
}


char Precede(char ch1, char ch2) {
	if (ch1 == '+') {
		if (ch2 == '+')return '>';
		if (ch2 == '-')return '>';
		if (ch2 == '*')return '<';
		if (ch2 == '/')return '<';
		if (ch2 == '(')return '<';
		if (ch2 == ')')return '>';
		if (ch2 == '#')return '>';
	}
	else if (ch1 == '-') {
		if (ch2 == '+')return '>';
		if (ch2 == '-')return '>';
		if (ch2 == '*')return '<';
		if (ch2 == '/')return '<';
		if (ch2 == '(')return '<';
		if (ch2 == ')')return '>';
		if (ch2 == '#')return '>';
	}
	else if (ch1 == '*') {
		if (ch2 == '+')return '>';
		if (ch2 == '-')return '>';
		if (ch2 == '*')return '>';
		if (ch2 == '/')return '>';
		if (ch2 == '(')return '<';
		if (ch2 == ')')return '>';
		if (ch2 == '#')return '>';
	}
	else if (ch1 == '/') {
		if (ch2 == '+')return '>';
		if (ch2 == '-')return '>';
		if (ch2 == '*')return '>';
		if (ch2 == '/')return '>';
		if (ch2 == '(')return '<';
		if (ch2 == ')')return '>';
		if (ch2 == '#')return '>';
	}
	else if (ch1 == '(') {
		if (ch2 == '+')return '<';
		if (ch2 == '-')return '<';
		if (ch2 == '*')return '<';
		if (ch2 == '/')return '<';
		if (ch2 == '(')return '<';
		if (ch2 == ')')return '=';
		if (ch2 == '#') {
			printf("输入的多项式有误!\n");
			exit(0);
		}
	}
	else if (ch1 == ')') {
		if (ch2 == '+')return '>';
		if (ch2 == '-')return '>';
		if (ch2 == '*')return '>';
		if (ch2 == '/')return '>';
		if (ch2 == '(') {
			printf("输入的多项式有误!\n");
			exit(0);
		}
		if (ch2 == ')')return '>';
		if (ch2 == '#')return '>';
	}
	else if (ch1 == '#') {
		if (ch2 == '+')return '<';
		if (ch2 == '-')return '<';
		if (ch2 == '*')return '<';
		if (ch2 == '/')return '<';
		if (ch2 == '(')return '<';
		if (ch2 == ')') {
			printf("输入的多项式有误!\n");
			exit(0);
		}
		if (ch2 == '#')return '=';
	}
	else {
		printf("出错!");
		exit(0);
		return 0;
	}
}

void Pop(CHARStack* S, char* ch) {
	if (S->top == -1) {
		printf("栈空!\n");
		exit(0);
	}
	else {
		*ch=S->S[S->top];
		S->top--;
	}
}

int changchartonumber(char ch) {
	if (ch == '0') {
		return 0;
	}
	else if (ch == '1') {
		return 1;
	}
	else if (ch == '2') {
		return 2;
	}
	else if (ch == '3') {
		return 3;
	}
	else if (ch == '4') {
		return 4;
	}
	else if (ch == '5') {
		return 5;
	}
	else if (ch == '6') {
		return 6;
	}
	else if (ch == '7') {
		return 7;
	}
	else if (ch == '8') {
		return 8;
	}
	else if (ch == '9') {
		return 9;
	}
	else {
		
		return (int)ch;
		
	}
}
char Operate(char ch1, char theta, char ch2) {
	int c1, c2;
	c1 = changchartonumber(ch1);
	c2 = changchartonumber(ch2);
	
	if (theta == '+') {
		return c1 + c2;
	}
	else if (theta == '-') {
		return c1 - c2;
	}
	else if (theta == '*') {
		return  c1 * c2;
	}
	else if (theta == '/') {
		return c1 / c2;
	}
	else {
		printf("错误");
		exit(0);
		return '0';
	}

}

int main() {
	char c,theta,a,b,xl,p;
	int x;
	CHARStack *OPTR, *OPND;                      //定义OPTR为运算符栈,OPND为运算数栈
	OPTR = (CHARStack*)malloc(sizeof(CHARStack));
	OPND = (CHARStack*)malloc(sizeof(CHARStack));
	InitStack(OPTR);
	Push(OPTR,'#');
	InitStack(OPND);
	c = getchar();
	while (c != '#' || GetTop(OPTR) != '#') {
		if (!TRIn(c)) {                    //不是运算符
			Push(OPND, c);
			c = getchar();
		}
		else {
			switch (Precede(GetTop(OPTR),c))
			{
			case'<'://栈顶元素优先权低
				Push(OPTR, c); c = getchar(); break;
			case'='://脱括号并接受下一个字符
				Pop(OPTR, &p); c = getchar(); break;
			case'>'://栈顶元素优先权高
				
				Pop(OPTR, &theta);
				Pop(OPND, &b);
				Pop(OPND, &a);
			
				Push(OPND, Operate(a, theta, b));
				break;
			}
		}
	}
	printf("结果为:%d",(int)OPND->S[OPND->top]);
	return 0;
}

头文件

#pragma once
#include<stdio.h>                        //EOF(=^Z或F6),NULL
#include<malloc.h>                       //malloc()等
#include<limits.h>                       //INT_MAX等
#include<string.h>                       
#include<stdlib.h>                       //atoi()
#include<io.h>                           //eof
#include<math.h>                         //floor(),ceil(),abs()*
#include<process.h>                      //exit()*
/*函数结果状态代码*/
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR -1
#define INFEASIBLE -1


在这里插入图片描述

这个过程当中其实需要两个类型栈来进行运算的,但是我图方便就按一个类型就是char类型进行运算,然后根据ASCII码与数字的关系,灵活转换,就可以达到两个类型栈的效果。比如字符‘5’-‘2’两个字符相减结果肯定是ASCII码,但由于位置的特殊性,结果还是3,但是这种算法是错误的。因为实际上是53-50=3;这个过程我利用一个changchartonumber函数,让他们变成int值直接的运算,要不然‘5’+‘2’实际上是53+50,结果是无法估计的!然后根据直接把结果存放在栈内。比如结果3,我直接把3存放在内,但是3代表的字符是未知的对于我来说,那么输出结果的时候,可以直接(int)强制转型,输出的便是3.其实char型的本质是int型,ASCII码表就是对于int与char之间的关系,多理解就可以了

本人在校大学生,菜鸟学习中,欢迎大佬指导,欢迎大家点赞关注!

  • 10
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以回答这个问题。利用C数组模拟完成后缀表达式求值的步骤如下: 1. 定义一个数组作为,同时定义一个变量作为顶指针。 2. 从左到右扫描后缀表达式,遇到操作数时,将其压入中。 3. 遇到操作符时,弹出顶的两个元素,进行相应的计算,并将结果压入中。 4. 重复执行步骤2和3,直到扫描完整个表达式。 5. 最终,中只剩下一个元素,就是后缀表达式的计算结果。 代码示例: ``` #include<stdio.h> #include<string.h> #define MAXSIZE 100 float stack[MAXSIZE]; // 定义数组 int top = -1; // 定义顶指针 // 将元素压入中 void push(float item){ if (top == MAXSIZE-1){ printf("Stack Overflow\n"); return; } stack[++top] = item; } // 弹出顶元素 float pop(){ if (top == -1){ printf("Stack Underflow\n"); return -1; } return stack[top--]; } // 判断是否为操作符 int isOperator(char ch){ if (ch == '+' || ch == '-' || ch == '*' || ch == '/'){ return 1; } return 0; } // 计算后缀表达式 float evaluatePostfix(char postfix[]){ int len = strlen(postfix); for (int i = 0; i < len; i++){ char ch = postfix[i]; if (isOperator(ch)){ float op2 = pop(); float op1 = pop(); switch(ch){ case '+': push(op1 + op2); break; case '-': push(op1 - op2); break; case '*': push(op1 * op2); break; case '/': push(op1 / op2); break; } } else if (ch >= '0' && ch <= '9'){ push(ch - '0'); } } return stack[top]; } int main(){ // 后缀表达式 "23*6+" char postfix[] = "23*6+"; float result = evaluatePostfix(postfix); printf("Result = %f\n", result); return 0; } ``` 以上就是利用C数组模拟完成后缀表达式求值的过程和对应的代码实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值