C语言实现栈的中缀表达式转化为后缀表达式,并且计算后缀表达式

因为数据结构老师布置了栈的后缀表达式实验,经过思考,有以下反思。

中缀表达式转换为后缀表达式

  1. 关于括号,直接将括号里面的符号加入后缀表达式。
  2. 关于数字,直接推入后缀表达式
  3. 遇到±符号,如果栈为空或者栈顶为“(”,直接将符号推入栈,如果栈不为空,且栈顶不为“(”,则推出栈顶符号。再将±符号推入符号栈。
  4. 如果遇到“/”符号,如果如果栈为空或者栈顶为“(”,直接推入栈,如果栈不为空,且栈顶符号优先级大于或者等于“/”符号,则推出栈顶符号。再将*/符号推入符号栈。
  5. 如果最后符号栈还有符号,直接加入后缀表达式。
    实际上也就是优先级比较的问题。

后缀表达式的计算:
后缀表达式的计算,只需要从左到右,遇到运算符就计算即可,无需考虑优先级的问题
代码块如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node{
	int data;
	struct node *next; 
}node,*link;
typedef struct snode
{
	char c;
	struct snode *next;
}snode,*slink;

void dealExpression();
char opTop(slink &s);
void push(link &s,int x);
void push1(slink &s,char x);
int pop1(slink &s);
int pop(link &s);
void calculate(link &s,slink &s1);
int main(void)
{
	dealExpression();
	
}
void empty(link &s)
{
	s=NULL;
}
void empty1(slink &s)
{
	s=NULL;
}
void push(link &s,int x)
{	node *p=(link )malloc(sizeof(node));
	p->data=x;
	p->next=s;
	s=p;
}
void push1(slink &s,char x)
{	snode *p=(slink )malloc(sizeof(snode));
	p->c=x;
	p->next=s;
	s=p;
}
int pop(link &s)
{
	int x;
	if(s==NULL){
		printf("it is an empty stack");

	}
	else{
		x=s->data;
		s=s->next;
		return x;
	}
}
int pop1(slink &s)
{
	snode *p=s;
	char x;
	if(s==NULL){
		printf("it is an empty stack");
	}
	else{
		x=p->c;
		s=s->next;
		free(p);
		return x;
	}
}	
char opTop(slink &s1){
if(s1==NULL){
	return 0;
}
else{
	return s1->c;
}
}
//计算,将栈中的数值和运算符进行计算 
void calculate(link &s,slink &s1)
{
	int number1,number2;
	char opf;
	number1=pop(s);
	number2=pop(s);
	opf=pop1(s1);
	int tmpResult=0;
	switch(opf){
			case '+':
					tmpResult=number1+number2;
				break;
			case '-':
					tmpResult=number2-number1;

				break;
			case '*':
					tmpResult=number2*number1;
					break;
			case '/':
					tmpResult=number2/number1;
					break;
	}
	push(s,tmpResult);
}

//将中缀表达式转化为后缀,并且存储在数值中 
void dealExpression()
{
	char change[100];
	int i=0;
	char a,b;
	node *s;
	snode *s1;
//定义节点一定要初始化节点,要不然会发生分配内存错误 
	empty(s);
	empty1(s1);
	char currentchar;
	scanf("%c",&currentchar);
//	转换过程 
	while(currentchar!='='){
	switch(currentchar){
		case '+':
		case '-':
			if(opTop(s1)==0){
				push1(s1,currentchar);
			}
			else{
				while(opTop(s1)=='+'||opTop(s1)=='-'||opTop(s1)=='*'||opTop(s1)=='/')
				{
					a=pop1(s1);
					change[i]=a;
					i++;
					printf("%c",a); 
				}
				push1(s1,currentchar);
			}
			scanf("%c",&currentchar);
			break;
		case '*':
		case '/':
			if(opTop(s1)==NULL){
				push1(s1,currentchar);
			}
			else{
				while(opTop(s1)=='*'||opTop(s1)=='/')
				{
					a=pop1(s1);
					change[i]=a;
					i++;
					printf("%c",a);
				}
				push1(s1,currentchar);
			}
			scanf("%c",&currentchar);
			break;
		case '(':
			push1(s1,currentchar);
			scanf("%c",&currentchar);
			break;
		case ')':
			while(opTop(s1)!='('){
				b=pop1(s1);
				change[i]=b;
				i++;
				printf("%c",b);
			}
			pop1(s1);
			scanf("%c",&currentchar);
			break;
		default:
			int opNum=0;
			while(currentchar>='0'&currentchar<='9'){
//				通过递归实现二位到以上的数 
				opNum=opNum*10+currentchar-'0';
				scanf("%c",&currentchar);
			}
 			change[i]=char(opNum);
			i++;
			printf("%d",opNum);
			break;
					}
		}
		while(opTop(s1)!=0)
		{
			a=pop1(s1);
			change[i]=char(a);
			i++;
			printf("%c",a);

		}
//		将转化的后缀表达式进行计算,如果遇到操作符,直接计算就可,无需考虑优先级,只需要考虑到从左至右的顺序 
		int j=0;
		while(j<i){
			switch(change[j]){
				case '+':
				case '-':
				case '*':
				case '/':
					push1(s1,change[j]);
					calculate(s,s1);
//					重要,因为break语句导致我调试了很久 
					break;
				default:
				push(s,int(change[j])); 

		}
		j++;
	}
		while(opTop(s1)!=0){
		calculate(s,s1);
		}
		int result;
		result=pop(s);
		printf("\n%d",result);

}

遇到的问题和反思:
解决了上次中缀表达式中,地址分配错误的问题,因为上次中缀表达式,我没有将栈初始化,所以导致了地址分配错误,所以将栈初始化是很重要的。
然后遇到了case,break的问题,我大意忘记写了break,结果导致了我调试了很久才发现问题:问题是这样的,我输入的 1+2= 结果却是45,在调试中发现“+”的ASCLL码正好是43,而且在最后一次case循环中,不仅是符号栈有输入,数字栈也有输入。才发现是忘记写break,导致最后一次循环:符号栈和数字栈都有输入,符号栈的输入是“+”,数字栈的输入是“43”.所以导致最后结果是45.

  • 14
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
下面是使用C语言实现中缀表达式转化后缀表达式的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // 定义操作符的优先级 #define ADD_SUB 1 #define MUL_DIV 2 #define POWER 3 // 定义的最大容量 #define MAX_STACK_SIZE 100 // 定义结构体 typedef struct { int top; char data[MAX_STACK_SIZE]; } Stack; // 初始化 void initStack(Stack *stack) { stack->top = -1; } // 判断是否为空 int isEmpty(Stack *stack) { return stack->top == -1; } // 判断是否已满 int isFull(Stack *stack) { return stack->top == MAX_STACK_SIZE - 1; } // 入 void push(Stack *stack, char c) { if (isFull(stack)) { printf("Error: Stack is full\n"); exit(-1); } stack->data[++stack->top] = c; } // 出 char pop(Stack *stack) { if (isEmpty(stack)) { printf("Error: Stack is empty\n"); exit(-1); } return stack->data[stack->top--]; } // 获取顶元素 char peek(Stack *stack) { if (isEmpty(stack)) { printf("Error: Stack is empty\n"); exit(-1); } return stack->data[stack->top]; } // 判断是否为操作符 int isOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'; } // 获取操作符的优先级 int getPriority(char c) { if (c == '+' || c == '-') { return ADD_SUB; } else if (c == '*' || c == '/') { return MUL_DIV; } else if (c == '^') { return POWER; } else { printf("Error: Invalid operator '%c'\n", c); exit(-1); } } // 中缀表达式转化后缀表达式 void infixToPostfix(char *infix, char *postfix) { Stack stack; initStack(&stack); int i, j; for (i = 0, j = 0; infix[i] != '\0'; i++) { if (isdigit(infix[i])) { // 如果是数字,直接添加到后缀表达式中 postfix[j++] = infix[i]; } else if (isOperator(infix[i])) { // 如果是操作符,弹出中优先级大于等于该操作符的所有操作符,添加到后缀表达式中 while (!isEmpty(&stack) && isOperator(peek(&stack)) && getPriority(peek(&stack)) >= getPriority(infix[i])) { postfix[j++] = pop(&stack); } // 将该操作符入 push(&stack, infix[i]); } else if (infix[i] == '(') { // 如果是左括号,直接入 push(&stack, infix[i]); } else if (infix[i] == ')') { // 如果是右括号,弹出中所有左括号之前的操作符,添加到后缀表达式中 while (!isEmpty(&stack) && peek(&stack) != '(') { postfix[j++] = pop(&stack); } // 弹出左括号 if (!isEmpty(&stack) && peek(&stack) == '(') { pop(&stack); } else { printf("Error: Mismatched parentheses\n"); exit(-1); } } else { printf("Error: Invalid character '%c'\n", infix[i]); exit(-1); } } // 弹出中所有操作符,添加到后缀表达式中 while (!isEmpty(&stack)) { if (peek(&stack) == '(') { printf("Error: Mismatched parentheses\n"); exit(-1); } postfix[j++] = pop(&stack); } postfix[j] = '\0'; // 添加字符串结束符 } int main() { char infix[100], postfix[100]; printf("Enter an infix expression: "); scanf("%s", infix); infixToPostfix(infix, postfix); printf("Postfix expression: %s\n", postfix); return 0; } ``` 使用示例: ``` Enter an infix expression: 3+4*5-6/2^(1+2) Postfix expression: 345*+612+/^- ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值