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

sscanf导致valid_lines计数器无法正常递增的问题排查

C语言文件解析函数计数异常问题排查

我编写了一个C语言文件解析函数read_file,用于读取并解析文件内容。每次valid_lines计数器递增后,printf输出显示计数正常,但最终valid_lines的值始终为1,排查后定位问题出在sscanf代码块中。

函数代码

void read_file(char *filename, int *city_num_lines, double *city_min, double *city_max, double *city_avg) {
    // files are in data_files/ directory
    char path[LINE_MAX_LENGTH] = "data_files/";
    strcat(path, filename);

    FILE *file = fopen(path, "r");

    // check if file exists
    if (file == NULL) {
        printf("Error: Could not open file %s\n", filename);
        return;
    }

    char buffer[LINE_MAX_LENGTH];
    int valid_lines = 0;
    double min = BIG_NUM;
    double max = -BIG_NUM;
    double sum = 0;
    double avg = 0;

    // read line by line
    while (fgets(buffer, LINE_MAX_LENGTH, file) != NULL) {
        // skip first line
        if (buffer[0] == 'm') {
            continue;
        }

        // separate by tab (\t)
        double cur_max, cur_min;
        char delim;
        if (sscanf(buffer, "%lf%[\t]%lf", &cur_max, &delim, &cur_min) != 3) {
            // printf("skipped line %s", buffer);
            continue;
        }

        // increment line count
        valid_lines++;
        printf("num_lines incremented\n");

        // update min and max
        if (cur_max > max) {
            max = cur_max;
            printf("max: %lf\n", max);
        }
        if (cur_min < min) {
            min = cur_min;
            printf("min: %lf\n", min);
        }
        sum += (cur_max + cur_min) / 2;
        // printf("%lf - %lf\n", min, max);

    }

    printf("num_lines: %d\n", valid_lines);

    // calculate average
    avg = sum / valid_lines;

    // update city values
    *city_num_lines = valid_lines;
    *city_min = min;
    *city_max = max;
    *city_avg = avg;

    fclose(file); // close file
}

控制台输出(最后几行)

...
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines incremented
num_lines: 1

问题根源与修复

问题原因

问题出在sscanf的格式字符串"%lf%[\t]%lf":

  • %[\t]格式说明符会匹配所有制表符,并将匹配到的内容(包括末尾的NUL终止符)写入目标地址。
  • 但此处仅为delim分配了1字节的char空间,无法容纳至少2字节(制表符+NUL终止符)的内容,导致内存越界,覆盖了相邻的valid_lines变量的内存区域,使得最终计数异常。

修复方案

方案1:直接跳过分隔符(推荐)

不需要单独存储制表符,直接在格式字符串中跳过即可,同时删除无用的delim变量:

// 修改sscanf调用,直接匹配制表符并跳过
if (sscanf(buffer, "%lf\t%lf", &cur_max, &cur_min) != 2) {
    continue;
}

方案2:限制匹配长度(若需验证分隔符)

如果需要确认分隔符是制表符,可以限制%[\t]的匹配长度,并给delim分配足够空间:

char delim[2]; // 分配足够空间存储制表符+NUL终止符
if (sscanf(buffer, "%lf%1[\t]%lf", &cur_max, delim, &cur_min) != 3) {
    continue;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:22:59