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

为何我的C语言表达式求值代码仅输出最后一位而非计算结果?

问题分析与修复

问题根源

你的代码实现的是**后缀表达式(逆波兰表达式)**的求值逻辑,但如果输入的是普通中缀表达式(比如3+5),会直接触发错误逻辑:遇到运算符时栈中元素不足2个,弹出无效值后计算结果异常,最终仅输出表达式最后一位数字。此外代码还存在以下缺陷:

  • 遇到非数字字符就强制执行运算,无边界检查
  • 仅支持+、-两种运算符
  • 未处理栈溢出/下溢、除零等异常情况
  • 未释放栈内存,存在内存泄漏

修复方案

根据需求场景提供两种修复代码:

场景1:正确处理后缀表达式

适用于输入为后缀表达式的场景(如35+表示3+5),修复后的代码完善了错误检查与运算符支持:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef struct Stack {
    int top;
    unsigned capacity;
    int *array;
} Stack;

Stack *createStack(unsigned capacity) {
    Stack *stack = (Stack *)malloc(sizeof(Stack));
    stack->capacity = capacity;
    stack->top = -1;
    stack->array = (int *)malloc(stack->capacity * sizeof(int));
    return stack;
}

int isEmpty(Stack *stack) {
    return stack->top == -1;
}

int peek(Stack *stack) {
    return stack->array[stack->top];
}

int pop(Stack *stack) {
    if (!isEmpty(stack))
        return stack->array[stack->top--];
    fprintf(stderr, "Error: Stack underflow!\n");
    exit(EXIT_FAILURE);
}

void push(Stack *stack, int op) {
    if (stack->top == stack->capacity - 1) {
        fprintf(stderr, "Error: Stack overflow!\n");
        exit(EXIT_FAILURE);
    }
    stack->array[++stack->top] = op;
}

int evaluate(char *expression) {
    Stack *stack = createStack(strlen(expression));
    int i;
    int len = strlen(expression);
    for (i = 0; i < len; ++i) {
        if (isspace(expression[i])) {
            continue;
        } else if (isdigit(expression[i])) {
            int operand = 0;
            while (i < len && isdigit(expression[i]))
                operand = operand * 10 + expression[i++] - '0';
            --i;
            push(stack, operand);
        } else {
            if (stack->top < 1) {
                fprintf(stderr, "Error: Invalid expression!\n");
                exit(EXIT_FAILURE);
            }
            int operand1 = pop(stack);
            int operand2 = pop(stack);
            switch (expression[i]) {
                case '+':
                    push(stack, operand2 + operand1);
                    break;
                case '-':
                    push(stack, operand2 - operand1);
                    break;
                case '*':
                    push(stack, operand2 * operand1);
                    break;
                case '/':
                    if (operand1 == 0) {
                        fprintf(stderr, "Error: Division by zero!\n");
                        exit(EXIT_FAILURE);
                    }
                    push(stack, operand2 / operand1);
                    break;
                default:
                    fprintf(stderr, "Error: Unsupported operator '%c'\n", expression[i]);
                    exit(EXIT_FAILURE);
            }
        }
    }
    if (stack->top != 0) {
        fprintf(stderr, "Error: Invalid expression!\n");
        exit(EXIT_FAILURE);
    }
    int result = pop(stack);
    free(stack->array);
    free(stack);
    return result;
}

int main() {
    char expression[100];
    int choice;
    do {
        printf("\n菜单:\n");
        printf("1. 计算算术表达式(后缀表达式)\n");
        printf("2. 退出\n");
        printf("请输入选择: ");
        scanf("%d", &choice);
        while (getchar() != '\n');
        switch (choice) {
            case 1:
                printf("请输入后缀表达式(如35+表示3+5): ");
                fgets(expression, sizeof(expression), stdin);
                expression[strcspn(expression, "\n")] = '\0';
                int result = evaluate(expression);
                printf("结果: %d\n", result);
                break;
            case 2:
                printf("再见!\n");
                break;
            default:
                printf("无效选择,请重试。\n");
                break;
        }
    } while (choice != 2);
    return 0;
}

场景2:支持中缀表达式求值

适用于输入为普通中缀表达式的场景(如3+5*2),新增中缀转后缀的逻辑,处理运算符优先级与括号:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef struct Stack {
    int top;
    unsigned capacity;
    char *array;
} CharStack;

typedef struct IntStack {
    int top;
    unsigned capacity;
    int *array;
} IntStack;

CharStack *createCharStack(unsigned capacity) {
    CharStack *stack = (CharStack *)malloc(sizeof(CharStack));
    stack->capacity = capacity;
    stack->top = -1;
    stack->array = (char *)malloc(stack->capacity * sizeof(char));
    return stack;
}

int isCharEmpty(CharStack *stack) {
    return stack->top == -1;
}

char charPeek(CharStack *stack) {
    return stack->array[stack->top];
}

char charPop(CharStack *stack) {
    if (!isCharEmpty(stack))
        return stack->array[stack->top--];
    return '\0';
}

void charPush(CharStack *stack, char op) {
    if (stack->top == stack->capacity - 1) {
        fprintf(stderr, "Error: Stack overflow!\n");
        exit(EXIT_FAILURE);
    }
    stack->array[++stack->top] = op;
}

IntStack *createIntStack(unsigned capacity) {
    IntStack *stack = (IntStack *)malloc(sizeof(IntStack));
    stack->capacity = capacity;
    stack->top = -1;
    stack->array = (int *)malloc(stack->capacity * sizeof(int));
    return stack;
}

int isIntEmpty(IntStack *stack) {
    return stack->top == -1;
}

int intPeek(IntStack *stack) {
    return stack->array[stack->top];
}

int intPop(IntStack *stack) {
    if (!isIntEmpty(stack))
        return stack->array[stack->top--];
    fprintf(stderr, "Error: Stack underflow!\n");
    exit(EXIT_FAILURE);
}

void intPush(IntStack *stack, int op) {
    if (stack->top == stack->capacity - 1) {
        fprintf(stderr, "Error: Stack overflow!\n");
        exit(EXIT_FAILURE);
    }
    stack->array[++stack->top] = op;
}

int precedence(char op) {
    switch(op) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0;
    }
}

void infixToPostfix(char *infix, char *postfix) {
    CharStack *stack = createCharStack(strlen(infix));
    int i = 0, j = 0;
    int len = strlen(infix);
    while (i < len) {
        if (isspace(infix[i])) {
            i++;
            continue;
        }
        if (isdigit(infix[i])) {
            while (i < len && isdigit(infix[i])) {
                postfix[j++] = infix[i++];
            }
            postfix[j++] = ' ';
        } else if (infix[i] == '(') {
            charPush(stack, infix[i++]);
        } else if (infix[i] == ')') {
            while (!isCharEmpty(stack) && charPeek(stack) != '(') {
                postfix[j++] = charPop(stack);
                postfix[j++] = ' ';
            }
            charPop(stack);
            i++;
        } else {
            while (!isCharEmpty(stack) && precedence(charPeek(stack)) >= precedence(infix[i])) {
                postfix[j++] = charPop(stack);
                postfix[j++] = ' ';
            }
            charPush(stack, infix[i++]);
        }
    }
    while (!isCharEmpty(stack)) {
        postfix[j++] = charPop(stack);
        postfix[j++] = ' ';
    }
    postfix[j-1] = '\0';
    free(stack->array);
    free(stack);
}

int evaluatePostfix(char *postfix) {
    IntStack *stack = createIntStack(strlen(postfix));
    int i = 0;
    int len = strlen(postfix);
    while (i < len) {
        if (isspace(postfix[i])) {
            i++;
            continue;
        } else if (isdigit(postfix[i])) {
            int operand = 0;
            while (i < len && isdigit(postfix[i])) {
                operand = operand * 10 + postfix[i++] - '0';
            }
            intPush(stack, operand);
        } else {
            int operand1 = intPop(stack);
            int operand2 = intPop(stack);
            switch(postfix[i]) {
                case '+':
                    intPush(stack, operand2 + operand1);
                    break;
                case '-':
                    intPush(stack, operand2 - operand1);
                    break;
                case '*':
                    intPush(stack, operand2 * operand1);
                    break;
                case '/':
                    if (operand1 == 0) {
                        fprintf(stderr, "Error: Division by zero!\n");
                        exit(EXIT_FAILURE);
                    }
                    intPush(stack, operand2 / operand1);
                    break;
            }
            i++;
        }
    }
    int result = intPop(stack);
    free(stack->array);
    free(stack);
    return result;
}

int evaluateInfix(char *expression) {
    char postfix[200];
    infixToPostfix(expression, postfix);
    return evaluatePostfix(postfix);
}

int main() {
    char expression[100];
    int choice;
    do {
        printf("\n菜单:\n");
        printf("1. 计算算术表达式(中缀表达式,如3+5*2)\n");
        printf("2. 退出\n");
        printf("请输入选择: ");
        scanf("%d", &choice);
        while (getchar() != '\n');
        switch (choice) {
            case 1:
                printf("请输入中缀表达式: ");
                fgets(expression, sizeof(expression), stdin);
                expression[strcspn(expression, "\n")] = '\0';
                int result = evaluateInfix(expression);
                printf("结果: %d\n", result);
                break;
            case 2:
                printf("再见!\n");
                break;
            default:
                printf("无效选择,请重试。\n");
                break;
        }
    } while (choice != 2);
    return 0;
}

关键修复点说明

  1. 后缀表达式版本:

    • 新增栈溢出/下溢、无效表达式的错误检查
    • 扩展支持*、/运算符,增加除零判断
    • 提前计算表达式长度,避免循环内重复调用strlen
    • 释放栈内存,避免内存泄漏
    • 支持跳过输入中的空格
  2. 中缀表达式版本:

    • 实现中缀转后缀逻辑,处理运算符优先级与括号
    • 用空格分隔后缀表达式操作数,解决多位数解析问题
    • 完善全流程错误处理机制

内容的提问来源于stack exchange,提问作者Progger_Pro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:15:01