Reputation: 187
I was writing a program in c to read the contents of a file. The code is as follows:
#include<stdio.h>
void main()
{
char line[90];
while(scanf("%79[^\n]\n",line)==1)
printf("%s",line);
}
The above code reads a file content and displays it on the screen.
But
while(scanf("%79[^\n]",line)==1) and while(scanf("%79[^\n]s",line)==1) or while(scanf("%79[^\n]s\n",line)==1)
doesn't work.(They display only the first line)
Can anyone explain?
Upvotes: 3
Views: 1667
Reputation: 206607
The format "%79[^\n]"
says all the characters up to 79 characters max that are not '\n'
.
When you use,
scanf("%79[^\n]s",line)
the return value should not be 1 since the s
in the format specifier expects a literal s
after it has finished reading all the characters that are not '\n'
. In other words, scanf
reports failure.
When you use,
scanf("%79[^\n]\n",line)
it succeeds because it finds a literal '\n'
at the end.
The difference between
scanf("%79[^\n]",line)
and
scanf("%79[^\n]\n",line)
is that the '\n'
is left in the input stream in the first case while it is consumed in the second case. In the second case, not only is the '\n'
consumed but any sequence of whitespaces starting at the '\n'
is consumed too (Thanks to @MattMcNabb for the additional clarification).
If you want scanf
to consume just the '\n'
, use:
scanf("%79[^\n]%*c",line)
Upvotes: 5
Reputation: 153508
Lots of subtle differences:
1) "%79[^\n]"
tells scanf()
to scan and save 1 to 79 char
except '\n'
. If the first char
attempted to scan is \n
, nothing will be save and scanning stops. In OP's examples, 0 is returned. Else a '\0'
is append to the destination line
. A 1 is returned if there is nothing more.
2) "%79[^\n]\n"
does 1) and if successful continues to look for any consecutive white-space, not just '\n'
. This will typically include a '\n'
and then all leading whitespace of the next line. It will return 1 regardless if it find a white-space.
3) "%79[^\n]s"
does 1 and if successful continues to look a single s
. It will return 1 regardless if it find a s
. Likely this is not OP's desire - drop the 's'
.
4) "%79[^\n]s\n"
does 3) and if successful, behaves like 2) continues to look for any consecutive white-space, not just '\n'
. It will return 1 regardless if it find a white-space.
5) The 3 while()
statement is fairly complex, taken as a whole. It gets stuck trying to read a '\n'
into the beginning of 1 of the 3 scanf()
.
A better approach, if code needs to use scanf()
to read a line, is
while (scanf(" %79[^\n]%*c", line) ==1)
. This will toss leading white-space and then read a line up to '\n'
, tossing that '\n'
via the "%*c"
.
The best approach is to use fgets(line, sizeof line, stdin)
.
Upvotes: 1
Reputation: 111
Its possible that the problem is concested to logic values shortcircuting. ie. when compiler determents that he has sufficient information to evaluate the whole expression it doesn't need to test other logic values(and doesn't evaluate them).
i.e. false and call_foo() always evaluate to false, so call_foo() is never called.
It could also be connected to that, when you read a line in scanf(first of 3 logic expresions) others scanf will read on next lines, not that same lines, because the first scanf already had taken the data from the buffer.
Upvotes: 0
Reputation: 726599
Since the format itself is the same, the key to solving this is, as you can certainly tell, the trailing character after the format string (or the absence of that character)
'\n'
at the end, you tell scanf
to read and ignore the end-of-line character after reading the string. This works fine, because '\n'
is what terminates the string in accordance with your format (i.e. %79[^\n]
).'s'
at the end, you tell scanf
that you expect a literal s
after the string that ends in '\n'
. This is an error, because scanf
will read the string up to, and excluding, the '\n'
character* .'\n'
at the end, the first read will succeed, but all subsequent ones will stumble upon the '\n'
, and stop reading right away.Note that the code that works may produce unexpected results for input strings that exceed 79 characters. These strings would be chopped at the 79-character mark, their remainder presented as the beginning of the next string.
* There is an unlikely situation when this read would succeed - namely, when the read terminates due to reaching the limit of 79, and then discovering the letter s
at the 80-th space.
Upvotes: 1