I am wondering how does the standard C library function scanf() check if the input is an integer or a character when we call scanf("%d",&var) when a character itself is just a number? I know that when it encounters a non-integer it puts it back into the input buffer and returns a -1 but how does it know that the input is not an integer?
7 Answers
The input is always a string. If scanf
is expecting an integer (because you passed it "%d"
), it attempts to convert the string to an integer for you.

- 84,206
- 33
- 197
- 283
-
But whatever we input it would be a sequence of ascii values that are all numbers. Isn't it? – vjain27 Apr 12 '11 at 01:42
-
ASCII values that represent numbers, you mean. scanf takes the character '9', decides it represents a number, and converts it to an integer 9. – Marvo Apr 12 '11 at 01:44
-
Yes that's what it should do. The keyboard will send ascii characters only. – vjain27 Apr 12 '11 at 01:50
-
Detail: As C defines a _string_, input is rarely ever a string as it lacks a null character. Input is a sequence of characters. – chux - Reinstate Monica Aug 29 '22 at 19:54
You're correct in that each character is really represented as an 8-bit integer. The solution is simple: look at that number, and see if it is in the range 48-57, which is the range of SCII codes for the characters '0' - '9'.
Starting on line 1315 of the scanf()
source code we can see this in action. scanf()
is actually more complicated, though - it also looks at multi-byte characters to determine the numeric value. Line 1740 is where the magic happens and that character is actually converted into a number. Finally, and possibly this is the most useful, the strtol()
function does the looping to perform that conversion.

- 63,369
- 21
- 118
- 128

- 18,726
- 23
- 95
- 134
In scanf statement you are mentioning %d which is holding integer only so by default it understood that the variable as integer

- 21
- 1
Basically, the scanf
function matches regular expressions based on the conversion specifier you pass. If you specify %d
, that tells scanf
to match input against a regular expression that's one or more characters between '0'
and '9'
(optionally with a leading +
or -
character). It then converts that sequence of characters to the equivalent integer value.
A very simplistic version might look something like this:
while (isdigit(c = fgetc(stream))
val = val * 10 + valueOf(c);
ungetc(c, stream);
where isdigit
is a standard library function that returns true (non-zero) if the character value represents a decimal digit, and valueOf
is a user-defined function that maps the character representing an integer ('0'
- '9'
) to the equivalent integer value (0
- 9
) (I'm not aware of a standard library function that does that for individual character values). Why not just subtract '0'
from c
to get the equivalent integer value? Depending on the encoding, it's not guaranteed that all decimal integer characters will be laid out in order (All The World Is Not ASCII); best to delegate the actual conversion to a function that's aware of the current encoding.

- 119,563
- 19
- 122
- 198
It tries to parse a valid decimal integer from the beginning of the stream, in practice optional + or - and then sequence of one or more digits.

- 25,136
- 3
- 52
- 71
-
Could you please explain how does it parse ? For eg. how will it differentiate between an A and the value 65 because A will be passed as 65 - its ascii value ? – vjain27 Apr 12 '11 at 01:47
-
Uh scant tries to read the ASCII representation of a decimal integer here. Letter A is not part of such. – Antti Huima Apr 12 '11 at 01:54
It basically uses a loop like:
while (isdigit((ch=getchar()))
// ...

- 476,176
- 80
- 629
- 1,111
You misunderstand the %d
format specifier. It does not return the ASCII value of the entered character (you can use %c
for that); it returns the integer that the characters represent. So, on an input character of '9'
, %d
returns the value 9 - not the ASCII value of '9'
.
(Well, %d
actually looks at a sequence of characters, so if the input is '9'
followed by '0'
followed by ' '
, it'll interpret that as 90).

- 233,326
- 40
- 323
- 462