Working of scanf and checking if input is int

2019-05-11 14:27发布

问题:

I wanted to check whether input given is integer input or not. I did not wanted to store input in a string. After seeing several questions on stackoverflow and by hit and trial, I have created following code

while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
    printf("Please enter an integer only : ");
    if(a == '\n')
        scanf("%c",&a);
    else
    {
        while(a != '\n')
            scanf("%c",&a);
    }
}

It works but according to my understanding, the following should have also worked

while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
    printf("Please enter an integer only : ");
    while(a != '\n')
        scanf("%c",&a);
}

Can someone please tell me why above did not worked ?? Also if someone has better solution please give it also.

Note :I am considering 12qwe also as an invalid input. I just want integers.

回答1:

The problem with

while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
    printf("Please enter an integer only : ");
    while(a != '\n')
        scanf("%c",&a);
}

is that if a happens to contain '\n' before the scan, and the scan fails, the inner while loop doesn't run at all. So

  • if the scan failed trying to parse an int from the input stream because the input was e.g. "ab c\n", the offending input remains in the input stream, the next scanf in the outer while loop control fails parsing an int again, a remains '\n', repeat.

  • if an input error occurred before reading a character from the stream into a, the scanf in the outer loop control fails because of a corrupted stream, repeat.

In the other version,

while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
    printf("Please enter an integer only : ");
    if(a == '\n')
        scanf("%c",&a);
    else
    {
        while(a != '\n')
            scanf("%c",&a);
    }
}

you make at least some progress as long as there is input to be read from the stream, since whatever a contains, you read at least one character from the input stream before attempting the next parsing of an int. It will also result in an infinite loop if the input stream is corrupted/closed/ends prematurely, e.g. if you redirect stdin from an empty file. You can have that loop also output multiple "Please enter an integer only : " messages by giving input like `"a\nb\nc\nd\n".

So you should check whether scanf encountered the end of the stream or some other read error before converting anything from the input, and abort in that case:

int reads;
while(((reads = scanf("%d%c", &num, &a)) != 2 && reads != EOF) || a != '\n')
{
    printf("Please enter an integer only : ");
    // read at least one character until the next newline
    do {
        reads = scanf("%c", &a);
    }while(reads != EOF && a != '\n');
}


回答2:

This is a wrong way to do. You can rather read the input using fgets() and then parse your string for integer ASCII range.

fgets(s, 1024, stdin)

for (i=0; s[i] ! = '\0';i++) {
if( s[i] <'0' && s[i] >'9')
  // not an integer<br>

You can also use standard functions like isalnum, isalpha etc.



回答3:

it works……

while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
    printf("Please enter an integer only : ");
    do{
        scanf("%c",&a);
    }while(a != '\n');
}


标签: c int scanf