Reputation: 917
My question seems to be very simple but I can't find an answer on Google.
I'd like to know what while (fscanf(inFile, "%[^ \n] ", string) != EOF)
does. I'm trying to read in a string from a file by using the above.
However, I am not exactly sure what this statement does, specifically the %[^ \n]
part. I know that it will loop until end of file, but is "string" a number value or some other value? Also, how can I use it?
For example, for a sentence "I like trees", what is the string value equivalent to?
Thank you in advanced.
Upvotes: 0
Views: 220
Reputation: 153338
while (fscanf(inFile, "%[^ \n] ", string) != EOF)
has huge problems.
The format string "%[^ \n] "
is made up of 2 directives: "%[^ \n]"
and " "
.
"%[^ \n]"
is a format specifier made up of a scanset. The scanset consists of all char
except ' '
and '\n'
. So fscanf()
looks for 1 or more characters that are in the scanset and saves them to string
.
"%[^ \n]"
has 2 problems:
1) If the first character encountered is not in the scanset, fscanf()
ungets that character back to inFile
and the function returns 0. No further scanning occurs. So if inFile
begins with a ' '
, code puts nothing in string
, inFile
is not advanced and subsequent code is set up for UB or an infinite loop!
2) The numbers of characters to save in string
is unbounded. So if inFile
begins with more that the sizeof(string)-1
char
in the scanset, undefined behavior ensues.
" "
directive tells fscanf()
to consume 0 or more white-space char
. This can be confusing should inFile
have the value stdin
. In that case, the user needs to enter some non-white-space after the ' '
or '\n'
. Since stdin
is usually line buffered, that means something like "abc\ndef\n"
needs to be entered before scanf()
saves "abc"
and returns 1. The "def\n"
is still in stdin
.
Recommend instead:
char string[100];
while (fscanf(inFile, "%99s", string) == 1) {
...
}
"%99s"
will consume optionally leading white-space, then up to 99 non-white-space char
, appending the usual \0
.
Upvotes: 0
Reputation: 9680
Note the space after the caret ^
and the trailing space in the format string "%[^ \n] "
of fscanf
.
fscanf(inFile, "%[^ \n] ", string)
The above statement means that fscanf
will read from the stream inFile
and match any nonempty sequence of characters which does not contain either a space ' '
or a newline '\n'
and write them into the buffer pointer to by the next argument which is string
, and then read and discard any number of (including zero) whitespace characters (meant by the trailing space in the format string). The buffer pointed to by string
must be large enough for any such sequence of characters plus the terminating null byte added automatically. If the buffer is not large enough, then fscanf
will overrun it invoking undefined behaviour and most likely causing program crash due to segfault. You must guard against it by specifying maximum field width which should be one less than the length of the buffer to accommodate the terminating null byte.
fscanf
returns the total number of input items successfully matched and assigned, which in this case, is one. It will return EOF
when the end of file is reached in the stream inFile
. Therefore the while
loop condition means that fscanf
will read such a sequence of characters and write it into the buffer string
till the end of file is reached in the stream inFile
.
You should change your while
loop to -
// assuming string is a char array
char string[100];
while(fscanf(inFile, "%99[^ \n] ", string) == 1) {
// return value 1 of fscanf means fscanf call was successful
// do stuff with string
}
Upvotes: 2
Reputation: 1973
"%[^ \n]"
basically it matches every thing except a \n
or a ' '
character.
The fscanf
statement you have will read everything from the file pointed to by inFile
and then stores what it read into a string named string
, which should be declared as char string[500]
(or a similar sufficiently large value). Everytime it successfully reads a character, it returns it.
Now since you need a way for the while
loop to quit after reading the file, you are comparing the return of fscanf
to EOF
, which is the special end-of-file character.
EDIT: corrected const char*
Upvotes: 0
Reputation: 1463
%[^ \n]
tells fscanf
to read all the characters excluding \n
and space
.
Upvotes: 2