我有下面的代码,应该逐行读取文件并在每行上执行
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,然后在主函数中运行此代码片段
此解析循环的目的是根据文件内容更新产品列表。
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;
}