31

I have significant trouble with this...

printf("> ");
int x = getchar();

printf("got the number: %d", scanf("%d", &x));

Output

> 1234
got the number: 1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maček
  • 76,434
  • 37
  • 167
  • 198
  • 2
    The reason you got the `1` is completely coincidental. `scanf` returns the number of values successfully read which is why its showing you a 1. Try another number and you will see why. – Marlon Feb 23 '11 at 04:49
  • 1
    See http://stackoverflow.com/questions/4023895/how-to-read-string-entered-by-user-in-c/4023921#4023921 if you want a robust input solution. I'm not dissing the accepted answer, `scanf` is fine (for _this_ situation anyway, not so for unbounded string entry) but you'll eventually want something that can be used as a general-purpose solution. It's often better to get a string from the user then `sscanf` it to get other representations. – paxdiablo Feb 23 '11 at 05:07
  • 1
    What's the getchar() doing there? – Jim Balter Feb 23 '11 at 09:53

3 Answers3

70

I'm not fully sure that this is what you're looking for, but if your question is how to read an integer using <stdio.h>, then the proper syntax is

int myInt;
scanf("%d", &myInt);

You'll need to do a lot of error-handling to ensure that this works correctly, of course, but this should be a good start. In particular, you'll need to handle the cases where

  1. The stdin file is closed or broken, so you get nothing at all.
  2. The user enters something invalid.

To check for this, you can capture the return code from scanf like this:

int result = scanf("%d", &myInt);

If stdin encounters an error while reading, result will be EOF, and you can check for errors like this:

int myInt;
int result = scanf("%d", &myInt);

if (result == EOF) {
    /* ... you're not going to get any input ... */
}

If, on the other hand, the user enters something invalid, like a garbage text string, then you need to read characters out of stdin until you consume all the offending input. You can do this as follows, using the fact that scanf returns 0 if nothing was read:

int myInt;
int result = scanf("%d", &myInt);

if (result == EOF) {
    /* ... you're not going to get any input ... */
}
if (result == 0) {
    while (fgetc(stdin) != '\n') // Read until a newline is found
        ;
}

Hope this helps!

EDIT: In response to the more detailed question, here's a more appropriate answer. :-)

The problem with this code is that when you write

printf("got the number: %d", scanf("%d", &x));

This is printing the return code from scanf, which is EOF on a stream error, 0 if nothing was read, and 1 otherwise. This means that, in particular, if you enter an integer, this will always print 1 because you're printing the status code from scanf, not the number you read.

To fix this, change this to

int x;
scanf("%d", &x);
/* ... error checking as above ... */
printf("got the number: %d", x);

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • I'm sorry I didn't provide more information with my original question. I made updates above. – maček Feb 23 '11 at 04:47
  • @macek- Just updated this to go into more detail about your particular problem. Can you look over this and see if it helps? – templatetypedef Feb 23 '11 at 04:50
  • 3
    Our answers were so similar, I just decided to delete mine. Yours is much better and more in depth! Also just a tiny nitpick, scanf returns the number of items successfully read so if you did "%d %d", it would return 2. – Marlon Feb 23 '11 at 04:51
  • @templateypedef, thank you, thank you! The added explanation is very helpful :) – maček Feb 23 '11 at 04:54
8

The typical way is with scanf:

int input_value;

scanf("%d", &input_value);

In most cases, however, you want to check whether your attempt at reading input succeeded. scanf returns the number of items it successfully converted, so you typically want to compare the return value against the number of items you expected to read. In this case you're expecting to read one item, so:

if (scanf("%d", &input_value) == 1)
    // it succeeded
else
    // it failed

Of course, the same is true of all the scanf family (sscanf, fscanf and so on).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
3

The solution is quite simple ... you're reading getchar() which gives you the first character in the input buffer, and scanf just parsed it (really don't know why) to an integer, if you just forget the getchar for a second, it will read the full buffer until a newline char.

printf("> ");
int x;
scanf("%d", &x);
printf("got the number: %d", x);

Outputs

> [prompt expecting input, lets write:] 1234 [Enter]
got the number: 1234
josegomezr
  • 888
  • 4
  • 15
  • 2
    This doesn't quite work.. it just prints the return code of scanf() which is usually 0 or 1. You want: `int x; scanf("%d", &x); printf("number: %d", x);` – charlie May 10 '16 at 21:32