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

表达式求值程序多位数/浮点数入栈故障排查求助

问题分析与修复方案

你当前的代码无法处理多位数整数和浮点数,核心问题集中在Token结构冗余、栈存储类型混乱、数字解析逻辑缺失浮点数支持,以及中缀转后缀时错误拆分数字这几点。以下是针对性的修复步骤:


1. 重构Token结构,统一数字存储

把冗余的value(int)和value1(double)合并为单个double num,用统一类型存储所有数字(整数/浮点数),同时明确Token类型:

typedef struct token{
    int type;           // 标记类型:T_NUMBER、T_PLUS、T_MINUS、T_TRIG等
    double num;         // 存储数字(整数/浮点数通用)
    int trig_type;      // 三角函数类型(如1=sin,2=cos)
    int precedence;     // 运算符优先级
    struct token *next;
} Token;

2. 修复栈结构,避免类型混淆

原栈用double items混存字符和数字,导致类型错乱。改为存储Token指针,明确每个栈元素的类型:

typedef struct {
    Token* items[200];
    int top;
} Stack;

如果追求简单,也可以拆分出数字栈(存double)和操作符栈(存Token或字符),彻底避免混存问题。

3. 完善数字解析逻辑,支持多位数和浮点数

原define_type只处理了整数第一位,补充浮点数解析和完整数字读取逻辑:

// Function为输入表达式字符串,i为当前解析索引,head为Token链表头
void define_type() {
    int len = strlen(Function);
    while (i < len) {
        // 解析数字(整数+浮点数)
        if (isdigit(Function[i]) || Function[i] == '.') {
            Token* nexttoken = (Token*)malloc(sizeof(Token));
            nexttoken->type = T_NUMBER;
            
            double num = 0.0;
            int decimal_flag = 0;
            double decimal_factor = 0.1;

            // 读取整数部分
            while (i < len && isdigit(Function[i])) {
                num = num * 10 + (Function[i] - '0');
                i++;
            }
            // 读取小数部分
            if (i < len && Function[i] == '.') {
                i++;
                decimal_flag = 1;
                while (i < len && isdigit(Function[i])) {
                    num += (Function[i] - '0') * decimal_factor;
                    decimal_factor *= 0.1;
                    i++;
                }
            }
            nexttoken->num = num;

            // 将Token加入链表
            if (head == NULL) {
                head = nexttoken;
            } else {
                Token* tmp = head;
                while (tmp->next != NULL) tmp = tmp->next;
                tmp->next = nexttoken;
            }
            nexttoken->next = NULL;
        } 
        // 处理运算符、三角函数等逻辑(根据你的需求补充)
        else if (strchr("+-*/()", Function[i])) {
            Token* nexttoken = (Token*)malloc(sizeof(Token));
            switch(Function[i]) {
                case '+': nexttoken->type = T_PLUS; nexttoken->precedence = 1; break;
                case '-': nexttoken->type = T_MINUS; nexttoken->precedence = 1; break;
                case '*': nexttoken->type = T_MUL; nexttoken->precedence = 2; break;
                case '/': nexttoken->type = T_DIV; nexttoken->precedence = 2; break;
                case '(': nexttoken->type = T_LPAREN; nexttoken->precedence = 0; break;
                case ')': nexttoken->type = T_RPAREN; nexttoken->precedence = 0; break;
            }
            // 加入链表逻辑同上
            i++;
        }
        // 其他字符处理(如三角函数、非法字符)
        else {
            printf("无效字符: %c\n", Function[i]);
            i++;
        }
    }
}

4. 修复中缀转后缀逻辑,完整存储数字Token

原代码把数字转成单个字符存入栈,导致多位数被拆分。现在直接将完整的数字Token加入后缀栈:

void infix_to_postfix(Token* head, Stack* postfix_tokens) {
    Stack op_stack;
    // 初始化栈(需实现对应的push_token、pop_token、peek_token函数)
    initialize_stack(&op_stack);

    Token* tmp = head;
    while (tmp != NULL) {
        switch (tmp->type) {
            case T_NUMBER:
                push_token(postfix_tokens, tmp);
                break;
            case T_LPAREN:
                push_token(&op_stack, tmp);
                break;
            case T_RPAREN:
                // 弹出操作符直到左括号
                while (op_stack.top != -1 && peek_token(&op_stack)->type != T_LPAREN) {
                    push_token(postfix_tokens, pop_token(&op_stack));
                }
                pop_token(&op_stack); // 丢弃左括号
                break;
            case T_PLUS: case T_MINUS: case T_MUL: case T_DIV:
                // 按优先级弹出操作符
                while (op_stack.top != -1 && peek_token(&op_stack)->precedence >= tmp->precedence) {
                    push_token(postfix_tokens, pop_token(&op_stack));
                }
                push_token(&op_stack, tmp);
                break;
            case T_TRIG:
                push_token(&op_stack, tmp);
                break;
        }
        tmp = tmp->next;
    }
    // 弹出剩余操作符
    while (op_stack.top != -1) {
        push_token(postfix_tokens, pop_token(&op_stack));
    }
}

5. 修复后缀表达式求值逻辑

现在后缀栈里是完整的Token,直接读取数字即可,无需拼接字符:

double evaluate_postfix(Stack* postfix_tokens) {
    Stack num_stack;
    initialize_num_stack(&num_stack); // 数字栈存储double

    while (postfix_tokens->top != -1) {
        Token* token = pop_token(postfix_tokens);
        if (token->type == T_NUMBER) {
            push_num(&num_stack, token->num);
        } 
        else if (token->type == T_PLUS || token->type == T_MINUS || token->type == T_MUL || token->type == T_DIV) {
            double b = pop_num(&num_stack);
            double a = pop_num(&num_stack);
            double res;
            switch(token->type) {
                case T_PLUS: res = a + b; break;
                case T_MINUS: res = a - b; break;
                case T_MUL: res = a * b; break;
                case T_DIV: 
                    if (b == 0) {
                        printf("除零错误!\n");
                        exit(1);
                    }
                    res = a / b; break;
            }
            push_num(&num_stack, res);
        }
        else if (token->type == T_TRIG) {
            double val = pop_num(&num_stack);
            double res;
            switch(token->trig_type) {
                case 1: res = sin(val); break; // 注意参数为弧度
                case 2: res = cos(val); break;
            }
            push_num(&num_stack, res);
        }
        free(token); // 释放Token内存
    }
    return pop_num(&num_stack);
}

内容的提问来源于stack exchange,提问作者Meryem İbrahim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:30:55