To begin with, you will want to review Why is while ( !feof (file) ) always wrong?
When reading lines of data from a file, use a line-oriented input function such as fgets()
or POSIX getline()
to read an entire line into a buffer -- then parse the needed values from the buffer. This provides two primary benefits:
you can independently validate:
a. the read of data from the file; and
b. parsing of the values from the line.
what remains in your input buffer does not depend on the scanf
format-specifier used. (an entire line is always consumed, so you are always ready to read from the beginning of the next line for your next input)
Any time you are reading from a file, simply provide a buffer of sufficient size when using fgets
(don't skimp on buffer size!). POSIX getline
will automatically allocate whatever space is required. Then use sscanf
to parse any information needed from the line (or strtok
or strsep
or any of the other functions you like to locate a specific point within the buffer).
If you are not parsing information and need the whole line, simply trim the '\n'
from the end of the buffer by overwriting it with the nul-character. strcspn
provides a simple method, or use strlen
to get the length then overwrite the last character.
In your case you simply need to handle the first line differently from the remaining lines -- so keep a line-counter initialized to zero at the beginning. If your line counter is zero, then parse 3-integer values from the line, otherwise do whatever you need with the subsequent lines (below they are simply output with along with the line number)
Putting it altogether, you could do something similar to:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* don't skimp on buffer size */
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
int n, s, d; /* your int variables */
size_t ndx = 0; /* line counter */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
if (!ndx) { /* if 1st line, parse into n, s, d */
if (sscanf (buf, "%d %d %d", &n, &s, &d) == 3)
printf ("line[%2zu] - n: %d s: %d d: %d\n",
ndx + 1, n, s, d);
else { /* if parse fails - handle error */
fputs ("error: invalid format - line 1.\n", stderr);
return 1;
}
}
else { /* for all subsequent lines */
buf[strcspn(buf, "\r\n")] = 0; /* trim '\n' from buf */
printf ("line[%2zu] : %s\n", ndx + 1, buf);
}
ndx++; /* increment line counter */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
Example Use/Output
Using your input file, you would get the following:
$ ./bin/rdline1_3int dat/line1_3int.txt
line[ 1] - n: 8 s: 3 d: 5
line[ 2] : mary
line[ 3] : tom
line[ 4] : jane
line[ 5] : joe
line[ 6] : dave
line[ 7] : judy
line[ 8] : fred
line[ 9] : bill
line[10] : jane
line[11] : jones
line[12] : judy
line[13] : mary
line[14] : judy
line[15] : fred
line[16] : joe
line[17] : dave