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

C语言读取txt文件到double数组时数值不符的问题排查

问题:读取文本文件数值到double数组时数值不符且input[i]触发段错误

我想把txt文件里的一列数值读到C语言的double数组里(多年没写C/C++,完全是新手状态)。现在读取后数组里的数值和文件里的对不上,不知道原因和解决办法。已经在CMAKE里把C标准设为C99,因为代码库其他部分是2006年的旧代码,不过这些部分要等数值正确读取后才会运行。

实现代码

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

int main(){
    double *input = malloc(sizeof(double) * 30);
    FILE *fReader= fopen("../values.txt", "r");
    if (fReader == NULL){
        perror("following error occurred:");
        return EXIT_FAILURE;
    }
    for(int i=0; i<30; i++){
    // 如果用input[i]会触发段错误
        if(fscanf(fReader, "%f", (input+i)) != 1){
            perror("following error occurred during value reading: ");
            fclose(fReader);
            return EXIT_FAILURE;
        }
        printf( "current value is %e\n", *(input+i));
    }

    if (ferror(fReader)){
        perror("following error occurred after reading: ");
        return EXIT_FAILURE;
    }
    if (fclose(fReader)){
        perror("following error occurred closing file: ");
        return EXIT_FAILURE;
    }

    return 0;
}

注:使用input[i]会触发段错误。这段代码能运行,但数组里的数值和文件里的不一致。

GDB调试输出

$1 = {
  {
    5.2090851696161347e-315,
    1.5708573496820653e-314,
    5.1267133989091838e-315,
    0,
    1.5717337030679671e-314,
    5.1214795787184985e-315,
    1.5632763856615201e-314,
    1.5698868046570466e-314,
    5.1603745953073066e-315,
    1.5776507290912971e-314,
    5.1890476209538565e-315,
    1.5757154067636091e-314,
    5.1701259393153366e-315,
    1.5646987621187767e-314,
    1.5706057487281833e-314,
    1.5745646547527293e-314,
    5.074800315787295e-315,
    1.5708606090331309e-314,
    1.5584251847289437e-314,
    5.0712624352138373e-315,
    1.5742053425473973e-314,
    5.121533268832232e-315,
    1.5713904213165801e-314,
    1.5767611663662882e-314,
    5.1426528410215284e-315,
    1.5729652822422439e-314,
    5.1593853918931727e-315,
    1.5747322610883588e-314,
    4.9742190195450526e-315,
    5.0023562211173747e-315
  }
}

values.txt文件内容

0.421499729344799
-0.0637534886782198
0.106157122495887
0
-0.0769690171367188
0.0982644454758486
-0.0186078658644284
-0.0558087634241033
0.188837376753259
-0.207397239912854
0.300632085420638
-0.149027358129317
0.218247717844644
-0.0239702769714967
-0.0612296530370315
-0.119660179409031
0.0451857273951361
-0.0638026393400715
-0.00797183286147529
0.0425181372831318
-0.114241700013729
0.0983454129367622
-0.0717922840839158
-0.18056777523574
0.135388066712405
-0.0955414085415107
0.185853919257983
-0.122187706120336
0.00796167779508749
0.0132655904045542

解决办法

1. 数值不符的核心原因:格式符不匹配

你用了%f格式符读取double类型变量,但%f在fscanf里是给float类型用的。读取double必须用%lf格式符。

因为float和double的内存占用不同(通常float是4字节,double是8字节),用%f读取到double地址时,只会写入前4字节,剩下的4字节是垃圾值,导致最终看到的是极小的错误数值(比如你GDB里的那些接近0的极小值)。

修正后的fscanf语句应该是:

if(fscanf(fReader, "%lf", (input+i)) != 1)

2. input[i]触发段错误的原因

input[i]和*(input+i)是完全等价的写法,理论上不该出现段错误。出现问题大概率是因为你之前用%f写入时破坏了内存:

  • 用%f往double地址写float数据,相当于只写了一半的内存,后续写入可能覆盖malloc分配区域之外的内存,破坏了堆结构,导致访问input[i]时触发段错误。
  • 先修正格式符为%lf,再测试input[i],就不会有段错误了。

另外,建议在malloc后检查是否分配成功,避免空指针访问:

double *input = malloc(sizeof(double) * 30);
if (input == NULL) {
    perror("malloc failed");
    return EXIT_FAILURE;
}

3. 额外的小问题:printf格式错误

你代码里的printf语句写了%current,这是笔误,应该去掉前面的%,改成:

printf( "current value is %e\n", *(input+i));

修正后的完整代码

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

int main(){
    double *input = malloc(sizeof(double) * 30);
    if (input == NULL) {
        perror("malloc failed");
        return EXIT_FAILURE;
    }
    FILE *fReader= fopen("../values.txt", "r");
    if (fReader == NULL){
        perror("following error occurred:");
        free(input); // 分配成功后要释放
        return EXIT_FAILURE;
    }
    for(int i=0; i<30; i++){
        if(fscanf(fReader, "%lf", &input[i]) != 1){ // 改用input[i]的地址
            perror("following error occurred during value reading: ");
            fclose(fReader);
            free(input);
            return EXIT_FAILURE;
        }
        printf( "current value is %e\n", input[i]);
    }

    if (ferror(fReader)){
        perror("following error occurred after reading: ");
        fclose(fReader);
        free(input);
        return EXIT_FAILURE;
    }
    if (fclose(fReader)){
        perror("following error occurred closing file: ");
        free(input);
        return EXIT_FAILURE;
    }
    free(input); // 最后释放内存
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:22:10