5

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?

vjain27
  • 3,514
  • 9
  • 41
  • 60

7 Answers7

3

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.

BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
3

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.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
poundifdef
  • 18,726
  • 23
  • 95
  • 134
2

In scanf statement you are mentioning %d which is holding integer only so by default it understood that the variable as integer

Ramya D
  • 21
  • 1
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.

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

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.

Antti Huima
  • 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
0

It basically uses a loop like:

while (isdigit((ch=getchar()))
    // ...
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

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).

caf
  • 233,326
  • 40
  • 323
  • 462