Step 4 of 8
Loading records
Much of the world's data lives in simple text formats: one record per line, with fields separated by spaces or commas. Loading such a file into an array of structs is a very common task.
fscanf reads fields directly into variables, and like scanf it returns how many fields it matched. Comparing that with the number you asked for tells you when to stop: at the end of the file it returns EOF, and on a malformed line it returns fewer.
#include <stdio.h>
typedef struct {
char item[24];
int qty;
double price;
} Line;
int main(void) {
FILE *f = fopen("order.txt", "w");
if (!f) return 1;
fputs("pen 3 1.50\nnotebook 2 4.25\nstapler 1 9.99\n", f);
fclose(f);
Line lines[10];
int n = 0;
f = fopen("order.txt", "r");
if (!f) return 1;
while (n < 10 && fscanf(f, "%23s %d %lf", lines[n].item, &lines[n].qty, &lines[n].price) == 3) {
n++;
}
fclose(f);
double total = 0;
for (int i = 0; i < n; i++) {
total += lines[i].qty * lines[i].price;
}
printf("%d lines, total %.2f\n", n, total);
return 0;
}
3 lines, total 22.99
Details that make it robust
n < 10 &&comes first in the condition, so the program never reads a record into a slot past the end of the array. (&&stops early when the left side is false.)%23slimits the name to fit the 24-byte array with its terminator.- Only after a successful read (all 3 fields) is
nincremented, so a bad line doesn't create a half-filled record. - Handle an empty file:
nstays 0, and code that divides bynor readslines[0]must check first.
Your turn: roster.txt holds name score pairs. Load them into the array (at most 32) and print the player with the highest score, then the average score with one decimal place.