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

fscanf读取输入文件最后一行(仅负值场景?)失败问题排查求助

问题定位与修复方案

根因分析

  • 最后一行末尾无换行符导致提前终止循环:你使用fscanf("%f%c")要求每次必须匹配1个浮点数+1个字符才返回2,若文件最后一行末尾没有换行符,读完最后一个浮点数就到达EOF,fscanf返回1,你直接执行break跳出循环,此时已经读取到的最后几个浮点数还未存入结果向量,直接被丢弃,这就是结果时有时无的核心原因——不同编辑器保存文件时,是否自动在末尾加换行符的规则不同。
  • 格式匹配逻辑不严谨:文件中浮点数的分隔符是逗号,你当前逻辑误将逗号读入字符变量c,虽然c!='\n'的判断刚好能跳过逗号,但逻辑完全不可靠,同时coordinate!='\n'是无效判断,浮点数不可能等于换行符的ASCII值。
  • 变量名笔误(潜在崩溃风险):代码中定义指针变量时写的是double** vex = ...,后续断言和使用时用的是vecs,属于笔误,会触发未定义行为,大概率直接崩溃。
  • 格式符不匹配:用%f读取float再赋值给double类型的数组元素,存在不必要的精度损失。

修复后代码

typedef struct vectors { 
        double** vecs; 
        int n; /* number of vectors */
} vectors;

vectors* parseInput(char* file_name, int dim) {
    double coordinate; // 改double直接存,不需要float中转
    char c;
    double *vec = NULL;
    int i=0, j=0, debug;
    FILE* input;
    vectors* datapoints;
    // 修正变量名笔误,vex改成vecs
    double** vecs = (double**) calloc (1000, sizeof (double*)); // 不需要乘dim,1000是最大向量数
    assert(vecs != NULL);
    datapoints = (vectors*)malloc(sizeof(vectors));
    assert(datapoints != NULL);
    input = fopen(file_name, "r");
    assert(input != NULL);
 
    while (1) {
        // 先读浮点数,用%lf匹配double
        debug = fscanf(input, "%lf", &coordinate);
        if(debug == EOF) {
            break;
        }
        if (debug != 1) {
            // 非法格式直接报错跳出
            fprintf(stderr, "Invalid file format\n");
            break;
        }
        // 新向量初始化
        if (j == 0) {
            vec = (double *)calloc(dim, sizeof(double));
            assert(vec != NULL);
        }
        // 存入当前坐标
        vec[j] = coordinate;
        j++;
        // 读完一个完整向量就存入结果集
        if (j == dim) {
            print_vec(vec, dim);
            vecs[i] = vec;
            i++;
            j = 0;
        }
        // 跳过后面所有的分隔符:逗号、空格、换行、回车
        while((c = fgetc(input)) != EOF && (c == ',' || c == ' ' || c == '\n' || c == '\r'));
        if (c != EOF) {
            // 把多读的非分隔符塞回流里,给下一次读浮点数用
            ungetc(c, input);
        }
    }
    // 收缩内存
    vecs = (double**)realloc(vecs, i*sizeof(double*));
    assert(vecs != NULL);
    datapoints->vecs = vecs;
    datapoints->n = i;
    fclose(input);
    return datapoints;
}

修改说明

  • 修正了变量名笔误,同时调整vecs的初始分配大小,原本乘dim属于多余操作,1000是支持的最大向量数量,可根据需求调整。
  • 拆分读取逻辑,先单独读取浮点数,再跳过所有分隔符(逗号、空格、换行、回车),不受最后一行是否有换行符的影响。
  • 替换%f为%lf直接读取double类型,避免精度损失。
  • 删除无效判断逻辑,代码健壮性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:48:03