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

C语言中while循环+scanf读取文件出现多余行的原因

读取文件时出现多余垃圾行的原因分析

问题场景

需要处理一个共35行的文本文件,要求跳过首行,读取剩余34行中被**包裹的数字段,后续将数字转换为字母等级输出。但当前代码执行后,控制台多输出了一行无意义的垃圾数据。

文件内容示例:

601000002001010906001   5323 #0001 Y  S                AAAAAA AAA A        **1122334321135 113132311412413  **                                                                                                                                                                         009 
601000003001010906001   5323 #0001 Y  S                BBB BBBBBBB B       **12231342434321223333122142111 **                                                                                                                                                                          005 
601000004001010906001   5323 #0001 Y  S                CCCCCCCCC CCCCC     **24342323213151331233454432214   **                                                                                                                                                                        005 

当前使用的代码:

int getAnswer(char answer[][TOTAL_QUESTIONS])
{
    char c;
    int row = 0;
    int column = 0;
    char garbage[1000];

    while (scanf("%s", &answer[row][column]) != EOF)
    {
        // if(row < 34) {
        skipNchar(77);
        for (column = 0; column < TOTAL_QUESTIONS; column++)
        {
                scanf("%c",&c);
                if (c == ' ' || c == '*')
                    answer[row][column]=' ';
                else
                    answer[row][column] = c;
        }
        // scanf("%c", &c);
        answer[row][column] = '\0';
        row++;
        column = 0; //}
    }

    return row;
}

核心原因分析

  • 循环条件的致命错误
    你用scanf("%s", &answer[row][column]) != EOF作为循环终止条件,但%s格式符会自动跳过所有空白字符(包括换行、空格)。当文件读到末尾时,scanf会返回EOF,但如果最后一行处理完后还有残留空白,或者读取出现异常,循环可能多执行一次:此时scanf返回EOF,但代码仍会执行后续的skipNchar和字符读取逻辑,读取到的都是无效垃圾数据,最终写入answer数组形成多余行。

  • scanf("%s")的参数非法
    &answer[row][column]是单个字符的地址,而%s需要指向一段足够大的字符数组来存储读取的字符串。这种写法会直接溢出answer数组的缓冲区,破坏内存数据结构,导致后续读取错位,甚至产生随机垃圾数据。

  • 未实现跳过首行的逻辑
    需求明确要求跳过首行,但代码完全没有处理这一步,首行数据会被正常读取处理,相当于多读取了一行,再加上循环多跑的一次,最终输出行数超出预期。

  • 字符读取未检查EOF
    在for循环中读取每个字符时,没有检查scanf的返回值。当文件到末尾时,scanf("%c")会返回EOF,但代码仍会把无效的c值写入answer数组,导致垃圾行产生。

修复建议

  1. 先跳过首行
    在循环开始前,用fgets读取首行并丢弃:

    fgets(garbage, sizeof(garbage), stdin);
    
  2. 改用逐行读取的方式
    放弃scanf的循环方式,改用fgets读取整行,再从每行中提取目标数据,避免空白字符干扰:

    char line[2048];
    // 先跳过首行
    fgets(line, sizeof(line), stdin);
    while (fgets(line, sizeof(line), stdin) != NULL && row < 34) {
        // 定位到**包裹的区域
        char *start = strstr(line, "**");
        if (start) {
            start += 2; // 跳过第一个**
            char *end = strstr(start, "**");
            if (end) {
                int len = end - start;
                for (column = 0; column < TOTAL_QUESTIONS && column < len; column++) {
                    answer[row][column] = (start[column] == ' ') ? ' ' : start[column];
                }
                answer[row][column] = '\0';
                row++;
            }
        }
    }
    
  3. 检查所有IO操作的返回值
    无论是fgets还是scanf,都要检查返回值,确保读取成功后再处理数据,避免读取EOF时继续写入垃圾值。

  4. 避免缓冲区溢出
    确保answer数组的大小足够容纳每行的目标数据,TOTAL_QUESTIONS要和实际需要读取的字符数匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:23:11