while 中的 EOF 跳出范围[关闭]

问题描述 投票:0回答:1

我有下面的代码,应该逐行读取文件并在每行上执行

for
,但在第一次运行后它会跳出
while

while (fscanf(f, "%s%*c%d\n", serial, &n) != EOF) {

    for (j = 0; j < i + 1; j++) {
        if (strcmp(serial, listProducts[j].serialID) == 0) {
            listProducts[j].n_items += n;
        } else {
            strcpy(listProducts[i].serialID, serial);
            listProducts[i].n_items = n;
        }
    }
    i++;
}

输入是包含以下信息的文件:a.txt

OP001Y100SSID 11 \n
AP003XMCN90ID 10 \n
BP007QRV200ID 19 \n
OP002HJDE28ID 22 \n
CP009QWDGREID 21

为了调试,我们只需要一个 txt filr,然后在主函数中运行此代码片段

c scanf
1个回答
1
投票

此解析循环的目的是根据文件内容更新产品列表。

while
循环有问题:

  • fscanf()
    格式使用
    %s
    ,这是有风险的,因为意外的长输入可能会导致缓冲区溢出,尝试写入超出
    serial
    目标数组的末尾。
  • fscanf()
    返回值与
    EOF
    进行比较并不可靠:您应该检查成功转换的数量,应该是
    2
  • 格式字符串末尾的
    \n
    与任何空格匹配,这不是测试行尾的可靠方法。
  • for
    循环尝试在
    listProducts
    数组中查找产品,如果未找到则添加一个条目。为此,循环逻辑是不正确的:您总是递增
    i

建议使用

fgets()
一次读取一整行文件,使用
sscanf()
解析该行并报告任何解析问题。

这是修改后的版本:

int load_products(struct product *listProducts, int count, FILE *f) {
    char buf[128];
    int i = 0;

    while (fgets(buf, sizeof buf, f)) {
        char serial[30];
        int n;
        int j;

        if (sscanf(buf, "%29s%d", serial, &n) != 2) {
            fprintf(stderr, "invalid format: %s\n", buf);
            continue;
        }

        for (j = 0; j < i; j++) {
            if (strcmp(serial, listProducts[j].serialID) == 0)
                break;
        }
        if (j < i) {
            /* product was found: update the count */
            listProducts[j].n_items += n;
        } else {
            /* product was not found: add an entry at the end */
            if (i >= count) {
                fprintf(stderr, "too many products, maximum: %d\n", count);
                break;
            }
            strcpy(listProducts[i].serialID, serial);
            listProducts[i].n_items = n;
            i++;
        }
    }
    return i;
}
© www.soinside.com 2019 - 2024. All rights reserved.