求后缀表达式值(c语言)(链栈)(头歌适用版)

 本题在求后缀表达式的结构体的基础上再加了一个int变量,和数字入栈的函数

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>
#include <stdio.h>
#include<string.h>
//若取出的字符是操作数,则加入后缀表达式
//若取出的字符是运算符:
//a.若为’(’,入栈;
//b.若为’)’,则依次把栈中的运算符加入后缀表达式,直到出现’(’,然后从栈中删除’(’;
//c.若为除了括号之外的其他运算符,当其优先级高于栈顶的运算符时,直接入栈;
//否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到遇到一个比它优先级低或遇到了一个左括号为止。

struct node
{
	char num;//内容,存放操作符
	int shuzi;//存放数字
	struct node* next;//链式表,指向下一个结点
};
typedef  struct node* PNODE;

struct stack//存放栈顶的结构体,即栈
{
	PNODE top;
	int size;//栈的大小
};
typedef  struct stack* Stack;

//创建一个空栈
Stack createStack()
{
	Stack stack;
	stack = (Stack)malloc(sizeof(struct stack));
	if (stack != NULL)
	{
		stack->top = NULL;
		stack->size = 0;
	}
	else printf("Out of space!");
	return stack;
}

//判断栈是否为空栈
int isEmptyStack(Stack stack)
{
	return(stack->top == NULL);
}

//入栈操作(头插法)(入字符)
void pushStack(Stack stack, char x)
{
	PNODE p;
	p = (PNODE)malloc(sizeof(struct node));
	if (p == NULL)
	{
		printf("Out of space!\n");
	}
	else {
		p->num = x;
		p->next = stack->top;
		stack->top = p;
		stack->size++;
	}
}

//入栈操作(头插法)(入数字)
void pushshuziStack(Stack stack, int x)
{
	PNODE p;
	p = (PNODE)malloc(sizeof(struct node));
	if (p == NULL)
	{
		printf("Out of space!\n");
	}
	else {
		p->shuzi = x;
		p->next = stack->top;
		stack->top = p;
		stack->size++;
	}
}
//出栈操作
void popStack(Stack stack)
{
	PNODE p;
	if (isEmptyStack(stack))
	{
		printf("Empty Stack pop!\n");
	}
	else {
		p = stack->top;
		stack->top = stack->top->next;
		free(p);
		stack->size--;
	}
}

//取栈顶元素
char top_num(Stack stack)
{
	if (stack->top == NULL)
	{
		printf("Empty Stack!\n");
	}
	else {
		return(stack->top->num);
	}

}
/*
   函数名:inToPost,本函数名和参数不能更改
   函数功能:将中缀表达式转换为后缀表达式输出
   函数参数:中缀表达式,放在字符数组中
   返回值:返回放有后缀表达式的栈
*/
Stack  inToPost(char* expression)
{
	//在此处填写代码,完成中缀表达式转换为后缀表达式并输出
	/**********  Begin  **********/
	Stack houzhui, fuhao;
	houzhui = createStack();
	fuhao = createStack();
	int len;
	len = strlen(expression);//得到字符串的长度
	char q = '#';
	pushStack(fuhao, q);
	for (int i = 0; i < len; i++)//遍历数组
	{
		char ch = expression[i];
		//若取出的字符是操作数,则加入后缀表达式
		if (ch >= '0' && ch <= '9')
		{
			if (expression[i + 1] >= '0' && expression[i + 1] <= '9' && i != len - 1)//如果后面一个也是操作数就不加空格,除非是最后一个数
			{
				pushStack(houzhui, ch);
			}
			else {

				pushStack(houzhui, ch);
				pushStack(houzhui, ' ');
			}
		}
		//a.若为’(’,入符号栈;
		else if (ch == '(')
		{
			pushStack(fuhao, ch);
		}
		//b.若为’)’,则依次把栈顶的运算符加入后缀表达式,直到出现’(’,然后从栈中删除’(’;
		else if (ch == ')')
		{
			while (fuhao->top->num != '(')
			{
				char topch = fuhao->top->num;
				popStack(fuhao);//出栈栈顶
				pushStack(houzhui, topch);//入栈后缀
				pushStack(houzhui, ' ');//空格入栈,表示间隔
			}
			popStack(fuhao);//在符号栈中删除(
		}
		//c.若为除了括号之外的其他运算符,当其优先级高于栈顶的运算符时,直接入栈;
		//否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到遇到一个比它优先级低或遇到了一个左括号为止。

		//假如是+,-,那么栈顶遇到(,进符号栈,否则栈顶一直出栈进后缀栈
		else if (ch == '+' || ch == '-')
		{
			while (fuhao->top->num != '(')
			{
				if (fuhao->top->num == '#')
				{
					break;
				}
				char topch = fuhao->top->num;
				popStack(fuhao);//出符号栈栈顶
				pushStack(houzhui, topch);//入栈后缀
				pushStack(houzhui, ' ');
			}
			pushStack(fuhao, ch);//此时的符号进入符号栈
		}
		//如果是* /,如果栈顶为* /,栈顶就出栈进入后缀栈,如果是	其他就入符号栈
		else if (ch == '*' || ch == '/')
		{
			while (fuhao->top->num == '*' || fuhao->top->num == '/')
			{
				char topch = fuhao->top->num;
				popStack(fuhao);//出符号栈栈顶
				pushStack(houzhui, topch);//入栈后缀
				pushStack(houzhui, ' ');
			}
			pushStack(fuhao, ch);//此时的符号进入符号栈
		}
	}
	//数组遍历完,将符号栈中所有东西存入后缀栈
	while (fuhao->top->num != '#')
	{
		char topch = fuhao->top->num;
		popStack(fuhao);//出符号栈栈顶
		pushStack(houzhui, topch);//入栈后缀
		pushStack(houzhui, ' ');
	}
	return houzhui;

	/**********  End  **********/
}

//print函数用于输出后缀表达式,参数是 inToPost的返回值

void print(Stack s)
{
	Stack result;
	result = createStack();//由于栈输出是逆序的,所以再来一个栈变成正序

	while (s->size != 0)
	{
		char topch = s->top->num;
		pushStack(result, topch);
		//printf("%c", topch);
		popStack(s);
	}

	while (result->size != 0)
	{
		char topch = result->top->num;
		printf("%c", topch);
		popStack(result);
	}

}
/*
   第三关
   函数名:calExp,本函数名和参数不能更改
   函数功能:调用inToPost函数求解后缀表达式,并求解后缀表达式的值返回
   函数参数:
   返回值:无
*/
int calExp(char* express)
{
	//在此处填写代码,完成表达式求值并输出
	/**********  Begin  **********/
	Stack s = inToPost(express);
	Stack zhengxu;

	zhengxu = createStack();//由于栈是逆序的,所以再来一个栈变成正序
	while (s->size != 0)
	{
		char topch = s->top->num;
		pushStack(zhengxu, topch);
		//printf("%c", topch);
		popStack(s);
	}
	//基本思路,利用后缀表达式,将后缀表达式压入栈,变成正序的。
	//再来一个栈,然后再遍历后缀栈,如果是操作数就入栈,是运算符就栈顶出两次栈,第一个在右第二个在左,运算出的结果再次入栈
	//具体操作:1.查看栈顶,是数字就存入str数组,遇到空格就利用atoi()将str变成int,再存入栈顶的数字里,如果遇到运算符,第一个在右第二个在左,运算出的结果再次入栈
	Stack result;
	result = createStack();
	char str[10];
	int i=0;
	int k;
	while (zhengxu->size > 0)
	{
		i = 0;
		k = 0;

		while (zhengxu->top->num != ' ')
		{
			if (zhengxu->top->num >= '0' && zhengxu->top->num <= '9')
			{
				str[i] = zhengxu->top->num;
				popStack(zhengxu);
				i++;
			}
			else if(zhengxu->top->num=='*') 
			{
				k = result->top->shuzi * result->top->next->shuzi;//出栈两个,进栈一个
				popStack(result);
				popStack(result);
				popStack(zhengxu);
			}
			else if (zhengxu->top->num == '+')
			{
				k = result->top->shuzi + result->top->next->shuzi;//出栈两个,进栈一个
				popStack(result);
				popStack(result);
				popStack(zhengxu);
			}
			else if (zhengxu->top->num == '-')
			{
				k = result->top->next->shuzi - result->top->shuzi;//出栈两个,进栈一个
				popStack(result);
				popStack(result);
				popStack(zhengxu);
			}
			else if (zhengxu->top->num == '/')
			{
				k = result->top->next->shuzi - result->top->shuzi;//出栈两个,进栈一个
				popStack(result);
				popStack(result);
				popStack(zhengxu);
			}
		}
		if (i != 0)
		{
			k = atoi(str);
			while (i >= 0)
			{
				str[i] = 0;
				i--;
			}//清空字符串
			pushshuziStack(result, k);
			k = 0;
		}

		if (k != 0)
		{
			pushshuziStack(result, k);
			popStack(zhengxu);
		}
		else {
			popStack(zhengxu);
		}
		
	}
	return result->top->shuzi;
	/**********  End  **********/
}

int main(void)
{
	char express[80];
	gets_s(express);
	printf("%d", calExp(express));
}

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值