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

C语言中缀表达式求值代码编译通过但运行崩溃,求问题排查

中缀表达式求值C代码崩溃问题排查与修复

你的代码崩溃主要是逻辑错误导致的内存越界和栈结构破坏,以下是具体问题和修复方案:


核心错误点与修复

1. popOp函数操作错误的栈指针

这是导致程序崩溃的最直接原因:操作符栈的指针是to,但popOp错误地使用了数字栈的指针tn,直接引发数组越界,触发内存访问错误。

错误代码:

char popOp()
{
    return op[--tn];
}

修复后:

char popOp()
{
    return op[--to];
}

2. 右括号处理逻辑错误

处理)时,while(op[to++]!='(')的写法会提前移动to指针,导致循环中访问错误的栈元素,后续的popOp()还会多弹出一个元素,彻底破坏栈结构。

错误代码:

else if(c==')')
{
    while(op[to++]!='(')
    {
        r = actualOperation(numbers, op);
        pushNum(r);
    }
    popOp();
}

修复后:

else if(c==')')
{
    // 循环直到遇到左括号,不提前移动指针
    while(op[to] != '(')
    {
        r = actualOperation(numbers, op);
        pushNum(r);
    }
    // 弹出左括号即可,无需额外pop
    popOp();
}

3. 多位数解析逻辑错误

当前代码只会保留多位数的最后一位(比如12会被解析成2),正确逻辑应该是逐位累加构建完整数字。

错误代码:

num = 0;
while(isItDigit(c))
{
    num = isItDigit(c);
    i++;
    if(i < strlen(expr))
    {
        c = expr[i];
    }
    else
    break;
}

修复后:

num = 0;
while(isItDigit(c))
{
    num = num * 10 + isItDigit(c);
    i++;
    if(i < strlen(expr))
    {
        c = expr[i];
    }
    else
        break;
}

4. isItDigit函数遗漏'0'的处理

函数只覆盖了1-9,导致数字0无法被识别为有效数字,添加对应case即可:

修复后函数:

int isItDigit(char c)
{
    switch(c)
    {
        case '0':
            return 0;
        case '1':
            return 1;
        case '2':
            return 2;
        case '3':
            return 3;
        case '4':
            return 4;
        case '5':
            return 5;
        case '6':
            return 6;
        case '7':
            return 7;
        case '8':
            return 8;
        case '9':
            return 9;       
    }
    return 0;
}

5. isOperator函数缺少默认返回值

当输入字符不是运算符时,函数无明确返回值,会返回随机值导致逻辑判断错误,改为返回1/0表示是否为运算符:

修复后函数:

int isOperator(char ch)
{
    switch(ch)
    {
        case '+':
        case '-':
        case '*':
        case '/':
            return 1; // 是运算符返回1
        default:
            return 0; // 不是返回0
    }
}

修复后的完整代码

//header files
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

//global variables
int numbers[50], tn=-1, to=-1;
char op[50];

//is it digit?
int isItDigit(char c)
{
    switch(c)
    {
        case '0':
            return 0;
        case '1':
            return 1;
        case '2':
            return 2;
        case '3':
            return 3;
        case '4':
            return 4;
        case '5':
            return 5;
        case '6':
            return 6;
        case '7':
            return 7;
        case '8':
            return 8;
        case '9':
            return 9;       
    }
    return 0;
}

//function to push digits
void pushNum(int n)
{
    numbers[++tn]=n;
}

//function to push operators
void pushOp(char ch)
{
    op[++to]=ch;
}

//function to pop digits
int popNum()
{
    return numbers[--tn];
}

//function to pop operators
char popOp()
{
    return op[--to];
}

//actual operation
int actualOperation(int numbers[50], char op[50])
{
    int x,y;
    char opr;
    x=popNum();
    y=popNum();
    opr=popOp();
    
    switch(opr)
    {
        case '+':
            return x+y;
        case '-':
            return y-x;
        case '*':
            return x*y;
        case '/':
            if(x==0)
            {
                printf("\nCannot divide by zero");
                exit(0);
            }
            else
            {
                return y/x;
            }
    }
    return 0;
}

//function to check if character is an operator or not
int isOperator(char ch)
{
    switch(ch)
    {
        case '+':
        case '-':
        case '*':
        case '/':
            return 1;
        default:
            return 0;
    }
}

//precedence of the operators
int precedence(char ch)
{
    switch (ch)
    {
        case '+':
            return 1;
        case '-':
            return 1;
        case '*':
            return 2;
        case '/':
            return 2;
        case '^':
            return 3;
        
    }
    
    return -1;
}

//to evaluate an infix expression
int evaluateInfix(char expr[50])
{
    int i, num, output, r;
    char c;
    
    for(i=0;expr[i]!=0;i++)
    {
        c = expr[i];
        
        if(isItDigit(c)!=0)
        {
            num = 0;
            while(isItDigit(c))
            {
                num = num * 10 + isItDigit(c);
                i++;
                if(i < strlen(expr))
                {
                    c = expr[i];
                }
                else
                break;
            }
            i--;
            pushNum(num);
        }
        else if(c=='(')
        {
            pushOp(c);
        }
        else if(c==')')
        {
            while(op[to] != '(')
            {
                r = actualOperation(numbers, op);
                pushNum(r);
            }
            popOp();
        }
        else if(isOperator(c))
        {
            while(to!=-1 && precedence(c)<=precedence(op[to]))
            {
                output = actualOperation(numbers, op);
                pushNum(output);
            }
            pushOp(c);
        }
            

    }
    while(to!=-1)
    {
            output = actualOperation(numbers, op);
            pushNum(output);
    }
    return popNum();
}

//main function
int main()
{
    char expr[50] = "(7-2)+(3*4)";
    int ans = evaluateInfix(expr);
    printf("Answer = %d", ans); 
    return 0;
}

运行修复后的代码,输入(7-2)+(3*4)会输出Answer = 17,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:10:25