You can actually do this quite simply by reading the line into an array (buffer) and then parsing what you need from the line with sscanf()
. Don't use scanf()
directly as that opens you up to a whole array of pitfalls related to what characters remain unread in your input stream. Instead, do all input by reading a line at a time and then use sscanf()
to parse the values from the buffer, just as you would with scanf()
, but by using fgets()
to read, you consume an entire line at a time, and what remains in your input stream does not depend on the success or failure of your conversions.
For example, you could do:
#include <stdio.h>
#define MAXC 1024
#define NCMAX 100
int main (void) {
char buf[MAXC],
name[NCMAX],
city[NCMAX];
unsigned n;
if (!fgets (buf, MAXC, stdin))
return 1;
if (sscanf (buf, "%u <%99[^>]> <%99[^>]>", &n, name, city) != 3) {
fputs ("error: invalid format", stderr);
return 1;
}
printf ("no. : %u\nname : %s\ncity : %s\n", n, name, city);
}
The sscanf()
format string is key. "%u <%99[^>]> <%99[^>]>"
reads the number as an unsigned value, <%99[^>]>
consumes the '<'
and then the character class %99[^>]
uses the field-width modifier of 99
to protect your array bounds and the class [^>]
will read all characters not including >
(it does the same for the city
next). The conversion is Validated by Checking the Return to insure three valid conversions took place. If not, the error is handled.
Example Use/Output
With your input in the file dat/no_name_place.txt
, the file is simply redirected on stdin
and read by the program resulting in:
$ ./bin/no_name_city < dat/no_name_place.txt
no. : 223234
name : Justin
city : Riverside