如何避免调用栈pop()前使用isEmpty()?空栈返回值方案探讨
解决整数栈pop()空栈返回0与栈内值混淆的问题
你当前的问题是栈的pop()函数在空栈时返回0,这会和栈中存储的合法0值混淆,且希望避免每次调用pop()前都检查栈是否为空。下面是几种可行的解决思路:
方案一:通过指针返回弹出值,函数返回状态码
这是C语言处理这类问题最常用的方式——用函数返回值表示操作是否成功,真正的弹出值通过指针参数传递,彻底区分“空栈”和“弹出了0”两种情况。
修改后的完整代码示例:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define STK_SIZE 100 #define INSTR_SIZE 5 // 修改pop签名:新增指针参数返回弹出值 int push(int * stack,int * stk_top,int operand); int pop(int * stack,int * stk_top, int *result); int main() { int n_instr=0; int operand=0; int stack[STK_SIZE]; int stk_top = -1; char line[INSTR_SIZE+5]; FILE * fp = fopen("instructions.txt", "r"); fgets(line, sizeof(line), stdin); n_instr = atoi(line); for(int i=0;i<n_instr;i++) { fgets(line, sizeof(line), stdin); char * opcode = strtok(line, " \n"); if(!strcmp(opcode,"PUSH")){ operand = atoi(strtok(NULL, " ")); push(stack,&stk_top,operand); } else if(!strcmp(opcode,"POP")){ int val; // 根据返回值判断是否弹出成功 if(pop(stack,&stk_top, &val) == 0){ printf("%d\n", val); } else { printf("Error: POP from empty stack\n"); } } else if(!strcmp(opcode,"ADD")){ int n1, n2; // 确保两次pop都成功再执行加法 if(pop(stack,&stk_top, &n1) != 0 || pop(stack,&stk_top, &n2) !=0){ printf("Error: ADD requires at least two elements in stack\n"); continue; } push(stack,&stk_top,n1 + n2); } else if(!strcmp(opcode,"SUB")){ int n1, n2; if(pop(stack,&stk_top, &n1) !=0 || pop(stack,&stk_top, &n2) !=0){ printf("Error: SUB requires at least two elements in stack\n"); continue; } push(stack,&stk_top,n2 - n1); } } fclose(fp); int val; // 循环弹出直到栈空 while(pop(stack,&stk_top, &val) ==0){ printf("%d\n", val); } return 0; } int push(int * stack,int * stk_top,int operand){ if(*stk_top<STK_SIZE-1){ (*stk_top)++; stack[*stk_top]=operand; return 0; // 成功返回0 } return 1; // 栈满返回1 } int pop(int * stack,int *stk_top, int *result){ if(*stk_top>-1){ *result = stack[*stk_top]; (*stk_top)--; return 0; // 成功返回0 } return 1; // 空栈返回1 }
这种方案逻辑清晰,能针对性处理空栈错误,适合绝大多数场景。
方案二:使用特殊标记值(需限制栈内数据范围)
如果能保证栈中永远不会存储某个特定整数(比如INT_MIN,即int类型的最小值),可以用该值作为空栈标记。需要引入<limits.h>头文件。
修改pop()函数及调用逻辑:
#include <limits.h> int pop(int * stack,int *stk_top){ if(*stk_top>-1){ int n = stack[*stk_top]; (*stk_top)--; return n; } return INT_MIN; // 空栈返回INT_MIN } // 调用示例(POP指令) int val = pop(stack,&stk_top); if(val == INT_MIN){ printf("Error: POP from empty stack\n"); } else { printf("%d\n", val); }
该方案局限性较大,仅适用于能明确排除INT_MIN作为合法栈元素的场景。
方案三:封装栈为结构体(模块化设计)
把栈的数组、栈顶状态封装成结构体,配合状态返回的函数使用,让代码结构更清晰,便于后续扩展。
示例代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define STK_SIZE 100 #define INSTR_SIZE 5 // 封装栈结构体 typedef struct { int data[STK_SIZE]; int top; } Stack; int stack_push(Stack *stack, int operand); int stack_pop(Stack *stack, int *result); int main() { int n_instr=0; int operand=0; Stack stack = {.top = -1}; // 初始化栈顶为-1 char line[INSTR_SIZE+5]; FILE * fp = fopen("instructions.txt", "r"); fgets(line, sizeof(line), stdin); n_instr = atoi(line); for(int i=0;i<n_instr;i++) { fgets(line, sizeof(line), stdin); char * opcode = strtok(line, " \n"); if(!strcmp(opcode,"PUSH")){ operand = atoi(strtok(NULL, " ")); stack_push(&stack, operand); } else if(!strcmp(opcode,"POP")){ int val; if(stack_pop(&stack, &val) == 0){ printf("%d\n", val); } else { printf("Error: POP from empty stack\n"); } } // ADD、SUB逻辑同方案一,此处省略 } fclose(fp); int val; while(stack_pop(&stack, &val) ==0){ printf("%d\n", val); } return 0; } int stack_push(Stack *stack, int operand){ if(stack->top < STK_SIZE-1){ stack->top++; stack->data[stack->top] = operand; return 0; } return 1; } int stack_pop(Stack *stack, int *result){ if(stack->top > -1){ *result = stack->data[stack->top]; stack->top--; return 0; } return 1; }
这种方案让栈的状态管理更集中,代码可读性和可维护性更强。
内容的提问来源于stack exchange,提问作者user2805902
相关产品推荐
相关产品推荐

