The purpose of this parsing loop is to update the list of products from the contents of the file. The while
loop has problems:
- the
fscanf()
format uses %s
which is risky as unexpectedly long input may cause a buffer overflow, attempting to write beyond the end of the serial
destination array.
- comparing the
fscanf()
return value to EOF
is not reliable: you should instead check the number of successful conversions, which should be 2
.
- the
\n
at the end of the format string matches any white space, it is not a reliable way to test for the end of line.
- the
for
loop attempts to locate the product in the listProducts
array and add an entry if it was not found. The loop logic is incorrect for this purpose: you always increment i
.
It is recommended to read the file one full line at a time with fgets()
, parse the line with sscanf()
and report any parsing issues.
Here is a modified version:
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;
}