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

C语言读取文件整数仅读取首行的问题排查与解决咨询

C语言tally函数读取文件提前终止循环的问题分析与解决

问题描述

我编写了一个C语言函数tally,用于从指定文件中读取整数值并统计指定整数出现的次数。待读取的.txt文件每行包含一个整数和一个浮点数,但目前函数仅读取首行的数值后就终止循环。

问题代码:

int tally(char fname[], int item) {
    int totalSales = 0;
    FILE *input;
    int intPlaceholder;
    FILE *write;

    input = fopen(fname, "r");

    if (input != NULL) {
        for (int i = 0; fscanf(input, "%d", &intPlaceholder) == 1; i++) {
            if (intPlaceholder == item) {
                totalSales++;
                // Adds 1 to total sales after finding a matching item code in the file
                printf("Has found a match!");
            }
            else {
                // Does nothing as it hasn't found a matching code
            }
            printf("\nLooped once.");
        }
        printf("\nStopped looping.\n");
    }
    else {
        printf("This option is not valid.\n");
        return 0;    // Could not open the file
    }
    fclose(input);
    return totalSales;
}

待读取的文件内容:

0   87.99
1   3.99
2   7.99
3   10.00
4   8.00

实际运行时,代码仅识别到0和87(本不应识别87,但这不是首要问题),仅循环两次,而我预期会循环10次。另有一个读取浮点数的同类函数运行正常,困惑为何仅整数读取出现此问题。

原因分析

  1. fscanf("%d")的读取逻辑:%d格式符会连续读取输入流中的数字字符,直到遇到非数字字符才停止。首行读取0后,流中剩余内容为87.99\n,下一次fscanf("%d")会读取87(.是非数字字符,触发停止),此时流中剩下.99\n。
  2. 循环终止的触发:第三次调用fscanf("%d")时,流的当前位置是.,无法解析为整数,fscanf返回EOF,循环条件不满足,因此循环仅执行两次就终止。
  3. 预期偏差:你预期循环10次是误解了文件结构,实际每行是一个整数加一个浮点数,共5行,正确的循环次数应该是5次(每行处理一个目标整数)。

解决方法

核心思路是每次读取整数后,跳过该行剩余的浮点数内容,避免后续读取时遇到无效字符导致解析失败。以下是两种可行方案:

方案1:用fscanf抑制读取浮点数

在读取整数后,用%*f格式符读取并丢弃该行的浮点数(*表示抑制赋值,不存储到变量):

int tally(char fname[], int item) {
    int totalSales = 0;
    FILE *input;
    int intPlaceholder;

    input = fopen(fname, "r");

    if (input != NULL) {
        // 每次读取整数后,自动读取并丢弃后续的浮点数
        while (fscanf(input, "%d%*f", &intPlaceholder) == 1) {
            if (intPlaceholder == item) {
                totalSales++;
                printf("Has found a match!");
            }
            printf("\nLooped once.");
        }
        printf("\nStopped looping.\n");
    } else {
        printf("This option is not valid.\n");
        return 0;
    }
    fclose(input);
    return totalSales;
}

方案2:逐行读取后解析(容错性更强)

使用fgets读取整行内容,再用sscanf从行内解析整数,这种方法不受行内多余字符、换行符的影响,更适合处理结构化文本:

#include <string.h> // 需包含string.h头文件

int tally(char fname[], int item) {
    int totalSales = 0;
    FILE *input;
    int intPlaceholder;
    char line[100]; // 定义足够大的缓冲区存储每行内容

    input = fopen(fname, "r");

    if (input != NULL) {
        // 逐行读取文件,直到文件末尾
        while (fgets(line, sizeof(line), input) != NULL) {
            // 从当前行中解析整数,忽略后续所有内容
            if (sscanf(line, "%d", &intPlaceholder) == 1) {
                if (intPlaceholder == item) {
                    totalSales++;
                    printf("Has found a match!");
                }
                printf("\nLooped once.");
            }
        }
        printf("\nStopped looping.\n");
    } else {
        printf("This option is not valid.\n");
        return 0;
    }
    fclose(input);
    return totalSales;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:06:05