3
votes

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.

3
Maybe "%d%n" format is what you need. You could also check scanf()s return value. - wildplasser
I did what you told. But what it is doing is that it checks for the integer part correctly. But when integer is entered correctly, it skips next scanf() in my code. Do /n remains in buffer here ?? I think it should not. - Sahil
No, I meant "%d%n". %n reports the number of succesfully consumed characters: in you case the number of numerical characters in the input string. After that, you could loop until you get a '\n'. (in fact you don;t need the %n; just read a %d, and than loop until '\n') - wildplasser
@屾顶洞人 张博 Second code hangs enter qwe as input twice. You will see it outputs "Enter an integer : " infinitely. - Sahil
if I just read an integer and loop until /n, it will except 12qwe as a valid input (Not sure but I think it will). I don't want that. And earlier, I used %d/n by mistake. But now when you have told the use of %n, I think it will not fulfill the requirement in this case - Sahil

3 Answers

3
votes

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');
}
1
votes

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.

1
votes

it works……

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