关于用栈链表来实现中序表达式的一个小程序 《数据结构》

本文介绍了在《数据结构》一书中遇到的使用栈链表处理中序表达式的问题。在执行某些表达式时,如1+1+1或2*3+1,会出现段错误。通过调试发现,问题出在比较运算符优先级的条件判断上。修复方法是将判断栈是否为空的操作提前,避免空栈时访问数据导致的错误。调试过程中,作者体验到了gdb的强大帮助。
摘要由CSDN通过智能技术生成

今天我在黄国瑜的《数据结构》一书中看到一段代码:于用栈链表来实现中序表达式,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
struct s_node
{
	int data;
	struct s_node *next;
};
typedef struct s_node s_list;
typedef s_list *link;
link operator=NULL;
link operand=NULL;

link push(link stack,int value)
{
	link newnode;
	newnode=(link)malloc(sizeof(s_list));
	if(!newnode){
		printf("\nMemory allocation failure!");
		return NULL;
	}
	newnode->data=value;
	newnode->next=stack;
	stack=newnode;
	return stack;
}
link pop(link stack,int *value)
{
	link top;
	if(stack!=NULL){
		top=stack;
		stack=stack->next;
		*value=top->data;
		free(top);
		return stack;
	}
	else
		*value=-1;
}

int empty(link stack)
{
	if(stack==NULL)
		return 1;
	else
		return 0;
}
int is_operator(char operator)
{
	switch(operator){
		case '+': case '-': case '*': case '/': return 1;
		default:return 0;
	}
}
int priority(char operator)
{
	switch(operator){
		case '+':case '-':return 1;
		case '*':case '/':return 2;
		default: return 0;
	}
}

int two_result(int operator,int operand1,int operand2)
{
	switch(operator){
		case '+':return (operand2+operand1);
		case '-':return (operand2-operand1);
		case '*':return (operand2*operand1);
		case '/':return (operand2/operand1);
	}
}
void main()
{
	char expression[50];
	int position=0;
	int op=0;
	int operand1=0;
	int operand2=0;
	int evaluate=0;

	printf("\nPlease input the inorder expression:");
	gets(expression);
	while(expression[position]!='\0'&&expression[position]!='\n'){
		if(is_operator(expression[position])){
			if(!empty(operator))
			while(priority(expression[position])<=priority(operator->data)&&!empty(operator)){
				operand=pop(operand,&operand1);
				operand=pop(operand,&operand2);
				operator=pop(operator,&op);
				operand=push(operand,two_result(op,operand1,operand2));
			}
		operator=push(operator,expression[position]);
		}
		else
			operand=push(operand,expression[position]-48);
			position++;
	}
	while(!empty(operator)){
		operator=pop(operator,&op);
		operand=pop(operand,&operand1);
		operand=pop(operand,&operand2);
		operand=push(operand,two_result(op,operand1,operand2));
	}
	operand=pop(operand,&evaluate);
	printf("The expression[%s]result is '%d'\n",expression,evaluate);
}

执行时有一个警告:

查资料知在gcc编译器中没有gets函数,只有fgets,在这里为了结果的正确就不改了。这样也可以执行。

可是呢,在执行的时候,当你执行1+1,2*3,1+2*3,等等类似的表达式都是正确的,可是当执行1+1+1,2*3+1这样的时候就出现段错误,为什么呢?分析表达式,看出只要是前面的运算符小于后边的运算符时都是正确的,大于等于时都错了。

后来经过调试,发现第87行改为这样就对了:

之前:

while(priority(expression[position])<=priority(operator->data)&&!empty(operator))

改后:while(!empty(operator)&&priority(expression[position])<=priority(operator->data))

因为当输入运算符时要进行与上一次运算符的比较,如果这次的运算符优先级高于上一次的话,就执行下面的语句,执行完语句后,再次进行判断优先级,按照未改之前的看,当执行到priority(operator->data)时就出错了,因为i这时operator就是空了,它没有data了,所以出现了段错误。把empty(operator)提到前面来,进来后直接判断,为空直接执行while之外的语句,这样就对了。

(后记:虽然刚刚接触gdb,可是真好用,这次就是用它找到段错误的,要不是用它,不知道又得折腾到什么时候呢!)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值