Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scanf and loops

Tags:

c

scanf

here a a piece of code that is supposed to loop over and over until the user inputs a number between 0 and 15

        int input;

        do
        {

                printf("Enter a number => ");
                scanf("%d",&input);
                printf("\n %d \n",input);

        }
        while (!(input>0 && input <15));

However if the user puts in something like "gfggdf" it results in the loop repeating over and over and over and never prompting the user for input again... the console looks like this

Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
Enter a number =>
0
(looping indefinitely)

After looking through this book, it seems I need to do something like this to prevent this from happening.

int input, error, status;
char skip_ch;

do
{
        error = 0;

        printf("Enter a number => ");
        status = scanf("%d",&input);
        printf("\n %d \n",input);

        if(status!=1)
        {
                error=1;
        }
        else if(input < 0 || input >15){
                error = 1;
        }

        do
        {
                scanf("%c",&skip_ch);
        }while(skip_ch != '\n');
}
while (error);

I understand needing to check for the scanf status to make sure it was valid input, What I don't understand the the inner do-while loop. I feel like the book never really explained to me why scanf needs to be called several times like that, it's like somehow the scanf buffer got filled up with a bunch of garbage and it's somehow cleaning it out by just looping through it a million times for you.

Could anyone please explain this black magic to me?

like image 828
Daniel Avatar asked Mar 26 '26 13:03

Daniel


1 Answers

That's why there are so many answers to similar questions that recommend not using scanf().

Also, you should check the return value from scanf() because it tells you when something has gone wrong - and no value could be converted.

The normal recommended solution is a combination of fgets() to read lines of input and sscanf() to parse the line once it is read.

The second loop in your example goes around reading the characters up to and including a newline, thus resynchronizing scanf() and skipping any bogus data. It is a long-winded way of doing it; it would be simpler to use getchar() instead:

int c;
while ((c = getchar()) != EOF && c != '\n')
    ;

Note the use of 'int c;' - the type is crucially not 'char' or 'unsigned char' because it must store all possible char values plus EOF.

like image 54
Jonathan Leffler Avatar answered Mar 28 '26 02:03

Jonathan Leffler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!