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

C语言程序bug:atof()截断末尾字符,长输入运算结果错误

问题分析与修复方案

核心错误原因

问题根源在于局部数组的生命周期失效:getAndTokenize函数里的lit_in是栈上的局部变量,函数执行完毕返回时,该数组会被销毁。但你把strtok返回的指向lit_in内部的指针存在了return_struc->tokens里,后续在main中访问这些指针时,内存已被回收,行为完全不可预测,这就是数字被截断的诡异现象的本质。

修复步骤

1. 修正Token存储方式

不能直接保存strtok返回的局部数组指针,必须为每个Token单独分配内存并复制内容:

修改getAndTokenize函数中的Token存储逻辑:

// 原代码:直接保存指针
// return_struc->tokens[0] = token;
// 替换为:分配内存并复制内容
return_struc->tokens[0] = malloc(strlen(token) + 1);
strcpy(return_struc->tokens[0], token);

// 循环内同理修改:
// 原代码:return_struc->tokens[i] = token;
// 替换为:
return_struc->tokens[i] = malloc(strlen(token) + 1);
strcpy(return_struc->tokens[i], token);

2. 调整结构体内存分配

原代码仅为结构体分配了基础空间,未给指针数组预留足够空间。需要按指针大小计算分配:

// 原代码:t_return *return_struc = malloc(sizeof(t_return) + MAX);
// 替换为:为MAX个char*指针预留空间
t_return *return_struc = malloc(sizeof(t_return) + MAX * sizeof(char*));

3. 添加内存释放逻辑(避免泄漏)

在main函数使用完Token后,需释放每个Token的内存和结构体本身:

// 在main末尾添加
for (int j = 0; j < tokens->arrayMembers; j++) {
    free(tokens->tokens[j]);
}
free(tokens);

4. 处理输入换行符(可选优化)

fgets会读取输入末尾的换行符,可能导致最后一个Token带换行,手动去除可避免潜在问题:

// 在fgets读取后添加
input[strcspn(input, "\n")] = '\0';

修复后的完整代码

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

#define MAX 1024

typedef struct tokenReturn {
    int arrayMembers;
    char* tokens[];
} t_return;

t_return *getAndTokenize(char* delim) {
    char* input = malloc(MAX);
    char lit_in[MAX];
    
    if (fgets(input, MAX, stdin) == NULL) {
        perror("Error: ");
        exit(EXIT_FAILURE);
    }

    // 去除输入末尾的换行符
    input[strcspn(input, "\n")] = '\0';
    strncpy(lit_in, input, MAX);
    free(input);

    // 为结构体和指针数组分配足够空间
    t_return *return_struc = malloc(sizeof(t_return) + MAX * sizeof(char*));
    if (return_struc == NULL) {
        puts("Allocation error");
        perror("Error");
        exit(EXIT_FAILURE);
    }
    
    char *token = strtok(lit_in, delim);
    // 为第一个Token分配内存并复制
    return_struc->tokens[0] = malloc(strlen(token) + 1);
    strcpy(return_struc->tokens[0], token);
    
    int i = 1;
    while (true) 
    {
        if((token = strtok(NULL, delim)) == NULL) {
            break;
        }
        // 为每个Token分配内存并复制
        return_struc->tokens[i] = malloc(strlen(token) + 1);
        strcpy(return_struc->tokens[i], token);
        i++;
    }
    return_struc->arrayMembers = i;
    
    return return_struc;
}

float sum(float x, float y) {
    return x + y;
}

float multiply(float x, float y) {
    return x * y;
}

float subs(float x, float y) {
    return x - y;
}

float division(float x, float y) {
    return x / y;
}

int main(void) {
    printf("Operation: ");
    t_return* tokens = getAndTokenize(" ");
    
    // 校验输入格式是否正确
    if (tokens->arrayMembers != 3) {
        puts("Invalid input format! Use: number operator number");
        // 提前释放内存
        for (int j = 0; j < tokens->arrayMembers; j++) {
            free(tokens->tokens[j]);
        }
        free(tokens);
        exit(EXIT_FAILURE);
    }
    
    float a = atof(tokens->tokens[0]);
    char symbol = tokens->tokens[1][0];
    float b = atof(tokens->tokens[2]);
    float result;

    switch (symbol) {
        case '+':
            result = sum(a, b);
            break;
        
        case '-':
            result = subs(a, b);
            break;
        
        case '/':
            result = division(a, b);
            break;
        
        case '*':
            result = multiply(a, b);
            break;
        
        default:
            puts("Operation not recognized!");
            // 释放内存
            for (int j = 0; j < tokens->arrayMembers; j++) {
                free(tokens->tokens[j]);
            }
            free(tokens);
            exit(EXIT_FAILURE);
    }

    printf("Result is: %.3lf\n", result);
    
    // 释放所有分配的内存
    for (int j = 0; j < tokens->arrayMembers; j++) {
        free(tokens->tokens[j]);
    }
    free(tokens);
    
    exit(EXIT_SUCCESS);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 04:27:15