1

Please see the following code:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    int i = scanf("%d", &n);
    printf("%d\n", i);
    int j = scanf("%d", &n);
    printf("%d\n", j);
    return 0;
}

Suppose I input a string for n at the first time, scanf will return 0; however, why it won't allow me to input a value for n the second time and j is automatic 0? What should I do to make it allow me to input a value for n again even if I typed a wrong value at the first time?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Your code is not allowing for a '\n' (newline) when you enter a value. Suggest changing the scanf format string from "%d" to " %d" so it will skip over any white space (newline is a white space). Otherwise, the second call to scanf() is seeing the newline and stopping – user3629249 Oct 21 '14 at 15:17

4 Answers4

5

You're almost certainly entering a non-numeric value, which will cause the first scanf to fail, returning zero and (this is the important bit) leaving the stream pointer exactly where it was before the scanf call.

That means the next time you call it, it will simply try to read the same data.

The return value of zero is a dead giveaway - scanf returns the number of items successfully scanned, so zero means you didn't give it a number.

If you enter numbers, it works fine, as per the following code:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    int i = scanf("%d", &n);
    printf(">> %d %d\n", i, n);
    int j = scanf("%d", &n);
    printf(">> %d %d\n", j, n);
    return 0;
}

When you run that and enter 41 and 32, you see:

41
>> 1 41
32
>> 1 32

Every C programmer at some point in their career comes up against the inadequacies of user input in that language. Your best bet for line based input is to simply find a function that does it well, then use sscanf on the resultant string.

One that ensures lines are the basic unit, and can handle buffer overflows and making sure excess data doesn't "corrupt" future input.

Here's one I prepared earlier.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

You can ignore the rest of the line before entering input afresh and reading them. You can ignore the rest of the line using:

scanf("%[^\n]*\n");
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

If you enter numbers your code will work fine. However, when you are entering a string, then you must remove the string from input stream before using it again.


For example:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    char c;
    int i = scanf("%d", &n);
    printf("%d\n", i);
    //Remove the previous string from the input stream
    while ( (c = getchar()) != '\n' && c != EOF );
    int j = scanf("%d", &n);
    printf("%d\n", j);
    return 0;
}

Output when input is integer

100
1
200
1

Output when input is strings

abcd
0
efghi
0

For further reference: Why does everyone say not to use scanf? What should I use instead?

ani627
  • 5,578
  • 8
  • 39
  • 45
  • You might want to slightly adjust the wording. It's not the newline that needs to be removed, it's the non-numeric input (though the easiest way to do this is to skip everything up to and including the newline). The newline will be skipped by the next `scanf` anyway because it's whitespace. – paxdiablo Oct 21 '14 at 05:08
  • @paxdiablo: Thanks for the correct suggestion. Made the changes. Your answer is better than mine :) – ani627 Oct 21 '14 at 05:28
  • Thank you very much for your help! But I may not understand what this line of code does: while ( (c = getchar()) != '\n' && c != EOF ); it seems that nothing is within the while loop. – nomorewords Oct 21 '14 at 12:01
1

The non-numeric string you entered isn't consumed by scanf.

Instead, you can use fgets and sscanf like this:

#include <stdio.h>

int main(void)
{
    int n;
    char str[100];
    fgets(str, sizeof(str), stdin);
    int i = sscanf(str, "%d", &n);
    printf("%d\n", i);
    fgets(str, sizeof(str), stdin);
    int j = sscanf(str, "%d", &n);
    printf("%d\n", j);
    return 0;
}
Yu Hao
  • 119,891
  • 44
  • 235
  • 294