Original format
The %s
conversion specification skips any white space (blanks, tabs, newlines, etc) in the input, and then reads non-white-space up to the next white space character. The \t
appearing in the format string causes fscanf()
to skip zero or more white space characters (not just tabs).
You have:
fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, pObj->age, pObj->country, pObj-profile);
You need to pass a pointer to the age and you need an arrow ->
between pObj
and profile
(please post code that could compile; it doesn't inspire confidence when there are errors like this):
fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, &pObj->age, pObj->country, pObj->profile);
Given the first input line:
Newton 30 United Kingdom Scientist
fscanf()
will read Newton
into pObj->name
, 30
into pObj->age,
Unitedinto
pObj->countryand
Kingdominto
pObj->profile.
fscanf()` and family are very casual about white space, in general. Most conversions skip leading white space.
After the 4 values are assigned, you have \the n"
at the end of the format. The tab skips the white space between Kingdom
and Scientist
, but the data doesn't match he n
, so the scanning stops — not that you're any the wiser for that.
The next operation will pick up where this one stopped, so the next pObj->name
will be assigned Scientist
and then the pObj->age
conversion will fail because Maxwell
doesn't represent an integer. The conversions stop there on that fscanf()
.
And so the problems continue. Your claimed output can't be attained with the code you show in the question.
If you're adamant that you must use fscanf()
, you'll need to use scan sets such as %24[^\t]
to read the country. But you'd do better using fgets()
or POSIX function getline()
to read whole lines of input, and then perhaps use sscanf()
but more likely use strcspn()
or strpbrk()
from Standard C (or perhaps strtok()
or — far better — POSIX strtok_r()
or Windows strtok_s()
, or non-standard strsep()
) to split the line into fields at tabs. Note that strtok_r()
et al don't care how many repeats there are of the delimiter (tabs in your case) between the fields; you can't have empty fields with them. You can identify empty fields with strcspn()
, strpbrk()
and strsep()
.
Cleaned up format
The format string has been revised to:
fscanf(fPtr,"%s\t%d\t%s\t%s\n", pObj->name, &pObj->age, pObj->country, pObj->profile);
This won't work, but can now be adapted so it will work.
if (fscanf(fPtr," %49[^\t]\t%d\t%24[^\t]\t%19[^\n]", pObj->name, &pObj->age, pObj->country, pObj->profile) != 4)
…handle a format error…
Beware trailing white space in scanf()
format strings. The leading blank skips any newline left over from previous lines, and skips any leading white space on a line. The %49[^\t]
looks for up to 49 non-tabs; the tab is optional and matches any sequence of white space, but the first character will be a tab unless the name was too long. Then it reads a number, more optional white space (it doesn't have to be a tab, but it will be unless the data is malformatted), then up to 24 non-tabs, white space again (of which the first character will be a tab unless there's a formatting problem), and up to 19 non-tabs. The next character should be a newline, unless there's a formatting problem.