Reputation:
I am having some doubt. The doubt is
What is the difference between the following two scanf statements.
scanf("%s",buf);
scanf("%[^\n]", buf);
If I am giving the second scanf in the while loop, it is going infinitely. Because the \n
is in the stdin
.
But in the first statement, reads up to before the \n
. It also will not read the \n
.
But The first statement does not go in infinitely. Why?
Upvotes: 2
Views: 454
Reputation: 9416
You can think of %s
as %[^\n \t\f\r\v]
, that is, after skipping any leading whitespace, a group a non-whitespace characters.
Upvotes: 0
Reputation: 153348
Common
Both expect buf
to be a pointer to a character array. Both append a null character to that array if at least 1 character was saved. Both return 1 if something was saved. Both return EOF
if end-of-file detected before saving anything. Both return EOF
in input error is detected. Both may save buf
with embedded '\0'
characters in it.
scanf("%s",buf);
scanf("%[^\n]", buf);
Differences
"%s"
1) consumes and discards leading white-space including '\n'
, space, tab, etc. 2) then saves non-white-space to buf
until 3) a white-space is detected (which is then put back into stdin
). buf
will not contain any white-space.
"%[^\n]"
1) does not consume and discards leading white-space. 2) it saves non-'\n'
characters to buf
until 3) a '\n'
is detected (which is then put back into stdin
). If the first character read is a '\n'
, then nothing is saved in buf
and 0 is returned. The '\n'
remains in stdin
and explains OP's infinite loop.
Failure to test the return value of scanf()
is a common code oversight. Better code checks the return value of scanf()
.
IMO: code should never use either:
Both fail to limit the number of characters read. Use fgets()
.
Upvotes: 0
Reputation: 1380
Let's take a look at these two code snippets :
#include <stdio.h>
int main(void){
char sentence[20] = {'\0'};
scanf("%s", sentence);
printf("\n%s\n", sentence);
return 0;
}
Input : Hello, my name is Claudio.
Output : Hello
#include <stdio.h>
int main(void){
char sentence[20] = {'\0'};
scanf("%[^\n]", sentence);
printf("\n%s\n", sentence);
return 0;
}
Input : Hello, my name is Claudio.
Output : Hello, my name is Claudio.
%[^\n]
is an inverted group scan and this is how I personally use it, as it allows me to input a sentece with blank spaces in it.
Upvotes: 0
Reputation: 16017
You can think of scanf as extracting words separated by whitespace from a stream of characters. Imagine reading a file which contains a table of numbers, for example, without worrying about the exact number count per line or the exact space count and nature between numbers.
Whitespace, for the record, is horizontal and vertical (these exist) tabs, carriage returns, newlines, form feeds and last not least, actual spaces.
In order to free the user from details, scanf treats all whitespace the same: It normally skips it until it hits a non-whitespace and then tries to convert the character sequence starting there according to the specified input conversion. E.g. with "%d" it expects a sequence of digits, perhaps preceded by a minus sign.
The input conversion "%s" also starts with skipping whitespace (and that's clearer documented in the opengroup's man page than in the Linux one).
After skipping leading whitespace, "%s" accepts everything until another whitespace is read (and put back in the input, because it isn't made part of the "word" being read). That sequence of non-whitespace chars -- basically a "word" -- is stored in the buffer provided. For example, scanning a string from " a bc "
results in skipping 3 spaces and storing "a" in the buffer. (The next scanf would skip the intervening space and put "bc" in the buffer. The next scanf after that would skip the remaining whitespace, encounter the end of file and return EOF.) So if a user is asked to enter three words they could give three words on one line or on three lines or on any number of lines preceded or separated by any number of empty lines, i.e. any number of subsequent newlines. Scanf couldn't care less.
There are a few exceptions to the "skip leading whitespace" strategy. Both concern conversions which usually indicate that the user wants to have more control about the input conversion. One of them is "%c" which just reads the next character. The other one is the "%[" spec which details exactly which characters are considered part of the next "word" to read. The conversion specification you use, "%[^\n]", reads everything except newline. Input from the keyboard is normally passed to a program line by line, and each line is by definition terminated by a newline. The newline of the first line passed to your program will be the first character from the input stream which does not match the conversion specification. Scanf will read it, inspect it and then put it back in the input stream (with ungetc()
) for somebody else to consume. Unfortunately, it will itself be the next consumer, in another loop iteration (as I assume). Now the very first character it encounters (the newline) does not match the input conversion (which demands anything but the newline). Scanf therefore gives up immediately, puts the offending character dutifully back in the input for somebody else to consume and returns 0 indicating the failure to even perfom the very first conversion in the format string. But alas, it itself will be the next consumer. Yes, machines are stupid.
Upvotes: 1
Reputation: 34588
First scanf("%s",buf); scan only word or string, but second scanf("%[^\n]", buf); reads a string until a user inputs is new line character.
Upvotes: 0
Reputation: 134286
Regarding the properties of the %s
format specifier, quoting C11
standrad, chapter §7.21.6.2, fscanf()
s
Matches a sequence of non-white-space characters.
The newline is a whitespace character, so only a newlinew
won't be a match for %s
.
So, in case the newline is left in the buffer, it does not scan the newline alone, and wait for the next non-whitespace input to appear on stdin
.
Upvotes: 2
Reputation: 7352
The %s
format specifier specifies that scanf()
should read all characters in the standard input buffer stdin
until it encounters the first whitespace character, and then stop there. The whitespace ('\n'
) remains in the stdin
buffer until consumed by another function, like getchar()
.
In the second case there is no mention of stopping.
Upvotes: 1