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

使用GMP库开发高精度二进制计算器:后缀表达式求值赋值错误求助

解决GMP库中“assignment to expression with array type”错误

错误原因分析

  1. GMP类型本质限制:mpf_t是GMP库定义的浮点类型,底层是数组类型(通过typedef封装)。C语言中数组不能直接用=赋值,也不能作为函数返回值直接返回——返回数组会自动退化为指针,但mpf_t的数组类型与指针不兼容,且局部数组在函数结束后会被销毁,导致悬空引用。
  2. 代码赋值违规:main函数中ans = evaluatePostfix(postfix);尝试直接赋值数组类型的ans,违反了C语言数组操作规则,触发报错。
  3. 栈操作潜在bug:原代码用mpf_set_ui(op2, pop(&operandStack));将pop返回值转为浮点类型,说明栈存储的是整数而非mpf_t数值,完全丢失了GMP的无限精度特性。

修正方案

核心思路

  • 放弃返回mpf_t的方式,改为通过参数传递已初始化的mpf_t变量,让函数将结果写入该变量。
  • 调整栈的存储逻辑,改为存储mpf_t指针,保留无限精度特性。

修正后的代码片段

重写evaluatePostfix函数

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

// 假设Stack的基础定义(需匹配你的实际实现)
typedef struct Stack {
    void** items;
    int top;
    int capacity;
} Stack;

// 判断是否为操作数(可根据需求调整)
int isOperand(char c) {
    return isdigit(c) || c == '.';
}

void evaluatePostfix(char* postfix, mpf_t result) {
    Stack operandStack;
    initializeStack(&operandStack);

    int i;
    mpf_t operand, op1, op2;
    mpf_init(operand);
    mpf_init(op1);
    mpf_init(op2);

    for (i = 0; postfix[i] != '\0'; i++) {
        char token = postfix[i];

        if (isOperand(token)) {
            // 解析操作数字符串为mpf_t类型
            mpf_set_str(operand, &postfix[i], 10);
            // 分配内存存储mpf_t,压入栈中
            mpf_t* temp = malloc(sizeof(mpf_t));
            mpf_init(*temp);
            mpf_set(*temp, operand);
            push(&operandStack, temp);
            // 跳过当前操作数的剩余字符
            while (postfix[i] != ' ' && postfix[i] != '\0') {
                i++;
            }
            if (postfix[i] == '\0') break;
        } else if (token != ' ') {
            // 弹出栈顶两个操作数,清理内存
            mpf_t* op2_ptr = pop(&operandStack);
            mpf_set(op2, *op2_ptr);
            mpf_clear(*op2_ptr);
            free(op2_ptr);

            mpf_t* op1_ptr = pop(&operandStack);
            mpf_set(op1, *op1_ptr);
            mpf_clear(*op1_ptr);
            free(op1_ptr);

            // 执行运算
            switch (token) {
                case '+':
                    mpf_add(result, op1, op2);
                    break;
                case '-':
                    mpf_sub(result, op1, op2);
                    break;
                case '*':
                    mpf_mul(result, op1, op2);
                    break;
                case '/':
                    if (mpf_cmp_d(op2, 0.0) != 0) {
                        mpf_div(result, op1, op2);
                    } else {
                        fprintf(stderr, "Error: Division by zero\n");
                        exit(EXIT_FAILURE);
                    }
                    break;
                case '%':
                    fprintf(stderr, "Error: Modulo operation not supported for floating-point numbers\n");
                    exit(EXIT_FAILURE);
                case '^':
                    fprintf(stderr, "Error: Exponentiation operation not supported for floating-point numbers\n");
                    exit(EXIT_FAILURE);
                default:
                    fprintf(stderr, "Invalid operator\n");
                    exit(EXIT_FAILURE);
            }

            // 将运算结果压入栈
            mpf_t* res_ptr = malloc(sizeof(mpf_t));
            mpf_init(*res_ptr);
            mpf_set(*res_ptr, result);
            push(&operandStack, res_ptr);
        }
    }

    // 将栈顶最终结果写入传入的result变量
    mpf_t* final_ptr = pop(&operandStack);
    mpf_set(result, *final_ptr);
    mpf_clear(*final_ptr);
    free(final_ptr);

    // 清理临时变量
    mpf_clear(operand);
    mpf_clear(op1);
    mpf_clear(op2);

    // 清理栈中剩余元素,防止内存泄漏
    while (!isEmpty(&operandStack)) {
        mpf_t* ptr = pop(&operandStack);
        mpf_clear(*ptr);
        free(ptr);
    }
}

修改main函数调用逻辑

int main() {
    while (1) {
        struct Num* linked_list = NULL;
        char temp;

        printf("\nEnter infix expression: ");
        while ((temp = getchar()) != '\n') {
            append(&linked_list, temp);
        }

        char* infix = linkedListToString(linked_list);
        char* postfix = malloc(strlen(infix) + 1);

        infixToPostfix(infix, postfix);
        printf("Postfix expression: %s\n", postfix);

        // 初始化结果变量
        mpf_t ans;
        mpf_init(ans);
        // 调用求值函数,直接将结果写入ans
        evaluatePostfix(postfix, ans);
        gmp_printf("\nResult: %.2Ff\n", ans);

        // 清理资源
        mpf_clear(ans);
        free(postfix);
        free(infix);
        freeLinkedList(linked_list);
        printf("\nCtrl + c to exit\n");
    }

    return 0;
}

关键注意事项

  • 必须使用GMP提供的mpf_set系列函数操作mpf_t,禁止直接赋值数组。
  • 栈操作需严格管理内存:压栈时分配内存,弹出时清理mpf_t并释放指针,避免内存泄漏。
  • 确保initializeStack、push、pop、isEmpty等栈函数能正确处理void*类型指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:17:16