You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免调用栈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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 12:44:56