Reputation: 51
I have question about %d
and %c
and 'enter' in C language.
Example code is very simple:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
int i;
scanf("%d", &i);
printf("%d", i);
return 0;
}
input [enter space 3] -> output [3]
%d
doesn't get enter or space.
But when input [q enter] -> output is trash value.
Why just 'enter' doesn't exit program unlike %c
?
Upvotes: 1
Views: 582
Reputation: 47925
As you've noticed, the behavior of %d
and %c
is quite different. We know that %d
is for entering integers, and %c
is for entering characters. But besides that, there are other, more subtle but perhaps more interesting differences.
Depending on how you count, scanf
with %d
does something like six sifferent things:
+
or -
) coming up next on the input stream.i
).EOF
if an end-of-fie or error condition was encountered while reading.But by contrast, what %c
does is much, much simpler. Basically it is:
EOF
if an end-of-fie or error condition was encountered while reading.Notice that %c
does not skip leading whitespace characters before reading. If the next character available on the input stream is a whitespace character, %c
will read and return it.
Also, %c
will read and return any character. It's not fussy. It doesn't limit itself to just digit characters like %d
does. If there's an input character at all, %c
will read it. I think it ends up being impossible for %c
to return 0 if it couldn't read a character, because the only condition under which it wouldn't be able to is end-of-file, and that returns EOF
.
So, to your questions:
input [enter space 3] -> output [3]
%d
doesn't get enter or space.
More precisely, %d
is willing to skip over those whitespace characters, looking for a digit like 3, which it is then able to successfully convert and return.
But when input [q enter] -> output is trash value.
More precisely, scanf
fails to convert as requested, so it fills nothing into i
, but in this case it will also have returned 0, which is supposed to alert you the fact that scanf
failed to convert, and that you need to be careful, because no new value has been stored into i
.
You need to check for this yourself, by doing something like
if(scanf("%d", &i) != 1) {
fprintf(stderr, "failed to read integer\n");
exit(1);
}
/* ... rest of program ... */
Why just 'enter' doesn't exit program unlike %c?
Im not sure what you mean by "just exit program". No correctly-written call to scanf
should cause your program to exit. Maybe you can show your code, or explain, what caused your program to exit.
As I said earlier, there is a difference between %c and %d
in terms of what they accept as "correct" input, and whether or not they're willing to automatically skip leading whitespace.
Upvotes: 0
Reputation: 23792
input [enter space 3] -> output [3] ... %d doesn't get enter or space
The %d
specifier is for integers, other inputed characters will not be read by scanf
and will remain in the buffer. Whitespace characters and conditionally '-'
, '+'
will be ignored and discarded, scanf
will keep waiting for the expected input in this case.
But when input [q enter] -> output is trash value
As stated, any non digit characters, with the exception of the described above, will not be read by scanf
and will remain in the buffer, i
will remain uninitialized. What normaly happens is that the value previously stored in i
, which will be any garbage value stored in the memory where i
now lives, will be printed. However, the behavior of passing uninitialized variables to printf
is undefined.
Why just 'enter' doesn't exit program unlike %c?
scanf
with %c
specifier has a different behavior it will read exactly one character and will store it in i
, enter
is a non printable control character so scanf
will read it and store it in i
, in fact you will note that printf
with %d
will print 10 (for ASCII encoding), which is the ASCII code for line feed, aka new line character.
With the %d
specifier, as stated before, scanf
will ignore and discard white space characters, it will keep waiting for an input until you input a non white space character.
Upvotes: 2
Reputation: 93456
Because Enter inserts a character ('\n'
) into the stream. The %c
format specifier matches any character including \n
, but it is not a decimal digit so in your example i
remains unassigned (and the newline remains buffered).
If you have %c
thus:
char c = 0 ;
scanf("%c", &c);
printf("%c", c);
and press Enter it does not "just exit", as you suggest- it outputs a blank newline. If you entered multiple spaces and newline, the first space would be assigned to c
and printed. The rest would remain buffered. This output is of course largely invisible. In the first instance you would that an extra blank line, which you might only notice by the position of any following output.
Note that scanf()
returns the number of formatters validly matched, so for:
int x = scanf("%d", &i);
x
will be zero, if you simply press Enter and i
will be undefined (in practice it would likely be unchanged, but that is not defined behaviour), but for:
char c ;
int x = scanf("%c", &c);
x
will have value 1, while c will contain a newline character \n
(typically ASCII LF - value 10).
Upvotes: 0
Reputation: 93456
Because Enter inserts a <newline>
character ('\n'
) into the stream. The %c
format specifier matches any character including '\n'
, but it is not a decimal digit so in your example i
remains unassigned (and the newline remains buffered) because it does not match the %d
format specifier.
Upvotes: 0
Reputation: 222302
Why just 'enter' doesn't exit program unlike %c?
With %d
, scanf
reads characters from input while expecting them to match the following in order:
scanf
stops reading for %d
when it reads a character that does not match the expected sequence (and the non-matching character is left in the stream). When you press the Enter key, a new-line character is generated in the stream, and scanf
reads it. Since it is a white-space character at a time when scanf
expects it, scanf
continues reading. So the program does not stop; scanf
continues waiting for more input.
In contrast, with a %c
conversion, scanf
does not expect white-space characters before the character to be read. It reads exactly one character and stores it. %d
allows initial white-space in what it matches, but %c
does not.
But when input [q enter] -> output is trash value.
When you press the Q key (and then Enter), scanf
reads “q”. Since it does not expect a “q” at this time, it stops reading. Then it returns to your main
routine. Since scanf
did not read any digit characters, it did not make a conversion and assign a value to i
. So i
remains uninitialized.
Upvotes: 1
Reputation: 3812
The behavior of scanf
can be read here. The function skips leading whitespace for %d
, but not for %c
:
All conversion specifiers other than [, c, and n consume and discard all leading whitespace characters (determined as if by calling isspace) before attempting to parse the input.
When the character q
is input while scanf
is looking for a digit, it doesn't find one and hence doesn't set the value pointed to. The value pointed to will be indeterminate.
When not entering a number, %d
will look for one and not initialize the value pointed to, whereas %c
will read the newline character (i.e. \n
, or decimal integer value 10).
Upvotes: 1