C语言数据结构 -- 中缀表达式的计算

本质上是后缀表达式和中缀转后缀的结合

思路:1.遇到操作数,直接入栈

2.遇到界限符,若‘(’,入栈;若是‘)’,则是弹出操作符,直到‘(’,记得top--,把‘(’去掉

3.遇到操作符,先判空,为空,直接入栈;不为空,弹出比此运算符级别高的或者相等的运算符,每弹出一个运算符,则相对应操作数也需要弹出两个,进行运算,这里就需要判断存放操作数的栈是否含有两个及以上的操作数,若没有,直接输出错误(我这里是没有进行这个判断的),若没错,进行运算,将结果压入操作数栈,操作数栈和运算符栈都减1

4.最后需要判断运算栈是不是为-1,若不是需要再次运算。最后判断操作栈是不是只有一个元素,是则直接输出,不是则输出错误。

/*
无论是前面的中缀转后缀还是现在的中缀的计算,我认为最大的漏洞就是最后判断
两个栈为空的问题 
*/ 
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#define Maxsize 10

typedef struct{ //定义一个存放操作数的栈 
	float data[Maxsize];
	int top1;
}Sqstack1;

typedef struct{ //定义一个存放运算符的栈 
	char data[Maxsize];
	int top2; 
}Sqstack2;

void Initstack(Sqstack1 *s1, Sqstack2 *s2)// 初始化 
{
	s1->top1 = -1;
	s2->top2 = -1;
}

void push1(Sqstack1 *s1, float x) //操作数入栈
{
	s1->top1++;
	s1->data[s1->top1] = x;
} 

void push2(Sqstack2 *s2, char x) // 运算符入栈
{
	s2->top2++;
	s2->data[s2->top2] = x;  
  }  

int zhuanhuan(char x) //将符号转化为数字 
{
	switch(x)
	{
		case '+': return 1;
		case '-': return 1;	
		case '*': return 2;
		case '/': return 2;
		case '(': return 0;
	} 
	
}

void jisuan(Sqstack1 *s1, Sqstack2 *s2, char c) //对其运算 
{
	switch(c) //注意计算的时候先出栈的在运算符右边 
	{
		case '+' :
			s1->data[s1->top1-1] = s1->data[s1->top1-1] + s1->data[s1->top1]; s1->top1--; s2->top2--;break;
		case '-' : 
			s1->data[s1->top1-1] = s1->data[s1->top1-1] - s1->data[s1->top1]; s1->top1--; s2->top2--;break;
		case '*' : 
			s1->data[s1->top1-1] = s1->data[s1->top1-1] * s1->data[s1->top1]; s1->top1--; s2->top2--;break;
		case '/' :
			s1->data[s1->top1-1] = s1->data[s1->top1-1] / s1->data[s1->top1]; s1->top1--; s2->top2--;break;
	}	
} 
 

void yunsuanfu(Sqstack1 *s1, Sqstack2 *s2, char x) //对运算符的操作 
{
	if(s2->top2 == -1)
		push2(s2, x);
	else
	{
		while(zhuanhuan(s2->data[s2->top2]) >= zhuanhuan(x))
		{
			jisuan(s1, s2, s2->data[s2->top2]);
			if(s2->top2 == -1 || s2->data[s2->top2] == '(')
				break;
		}
		push2(s2, x);	
	}	
}

void jiexianfu(Sqstack1 *s1, Sqstack2 *s2) //处理遇到)的情况
{
	while(s2->data[s2->top2] != '(')
	{
		jisuan(s1, s2, s2->data[s2->top2]);
	}
	s2->top2--;
} 

int main()
{
	Sqstack1 s1;
	Sqstack2 s2;
	Initstack(&s1, &s2);
	
	int i;
	char a[10];
	
	printf("请输入需要计算的中缀表达式:");
	scanf("%s", a);
	
	for(i = 0; i<strlen(a); i++)
	{
		if(a[i] >= '0' && a[i] <= '9')
		{
			float x = a[i] - '0';
			push1(&s1, x);
		}
		else if(a[i] == '+' || a[i] == '-' || a[i] == '/' || a[i] == '*')
		{
			yunsuanfu(&s1, &s2, a[i]);
		}
		else
		{
			if(a[i] == '(')
				push2(&s2, a[i]);
			if(a[i] == ')')
			{
				jiexianfu(&s1, &s2);
			}
		}
	}
	
	while(s2.top2 != -1) // 确认运算符全部出栈 
	{
		jisuan(&s1, &s2, s2.data[s2.top2]);
	}
	
	
	if(s1.top1 == 0)
	{
		printf("%.2f\n", s1.data[s1.top1]);
	}
	else
	{
		printf("表达式错误"); 
	}
	
	return 0;
 } 

中缀表达式求值可以通过将中缀表达式转换为后缀表达式,然后再对后缀表达式进行求值来实现。以下是一个简单的中缀表达式求值的示例程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define STACK_SIZE 100 typedef struct { double data[STACK_SIZE]; int top; } Stack; void initStack(Stack* s) { s->top = -1; } int isStackEmpty(Stack* s) { return s->top == -1; } int isStackFull(Stack* s) { return s->top == STACK_SIZE - 1; } void push(Stack* s, double data) { if (isStackFull(s)) { fprintf(stderr, "Stack overflow.\n"); exit(EXIT_FAILURE); } s->data[++s->top] = data; } double pop(Stack* s) { if (isStackEmpty(s)) { fprintf(stderr, "Stack underflow.\n"); exit(EXIT_FAILURE); } return s->data[s->top--]; } int priority(char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } double evaluate(double op1, char operator, double op2) { switch (operator) { case '+': return op1 + op2; case '-': return op1 - op2; case '*': return op1 * op2; case '/': return op1 / op2; default: fprintf(stderr, "Invalid operator: %c\n", operator); exit(EXIT_FAILURE); } } double evaluateInfixExpression(char* infix) { Stack operatorStack; double operandStack[STACK_SIZE]; int operandCount = 0; char* token = strtok(infix, " "); while (token != NULL) { if (isdigit(token[0])) { operandStack[operandCount++] = atof(token); } else { while (!isStackEmpty(&operatorStack) && priority(token[0]) <= priority(operatorStack.data[operatorStack.top])) { double op2 = operandStack[--operandCount]; double op1 = operandStack[--operandCount]; char operator = pop(&operatorStack); operandStack[operandCount++] = evaluate(op1, operator, op2); } push(&operatorStack, token[0]); } token = strtok(NULL, " "); } while (!isStackEmpty(&operatorStack)) { double op2 = operandStack[--operandCount]; double op1 = operandStack[--operandCount]; char operator = pop(&operatorStack); operandStack[operandCount++] = evaluate(op1, operator, op2); } return operandStack[0]; } int main() { char infix[STACK_SIZE]; printf("Enter an infix expression: "); fgets(infix, sizeof(infix), stdin); printf("Result: %f\n", evaluateInfixExpression(infix)); return 0; } ``` 该程序使用两个栈,一个用于存储操作符,另一个用于存储操作数。它首先将中缀表达式字符串分解成单词,然后扫描每个单词,如果它是一个操作数,则将其推入操作数栈,否则将其与操作符栈的栈顶元素进行比较。如果其优先级高于操作符栈的栈顶元素,则将其推入操作符栈,否则将操作符栈的栈顶元素弹出,与两个操作数栈的栈顶元素进行操作并将结果推入操作数栈。最后,当操作符栈为空时,操作数栈的栈顶元素即为表达式的值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值