user1930901
user1930901

Reputation: 211

Code giving me an infinite loop

#include <stdio.h>
void load_menu(void);

int main(void)
{
    load_menu();
    return 0;
}

void load_menu(void)
{
int choice;
int loopagain;

do
{
    printf("Menu \n\n");
    printf("Please enter your choice: \n");
    printf("1. \n");
    printf("2.\n");
    printf("3.\n");
    printf("4. Exit\n");
    if (scanf("%d",&choice)==1)
    {

        switch(choice)
        {
            case 1:
                    break;
            case 2:
                    break;
            case 3:
                    break;
            case 4: printf("Quitting program!\n");
                    break;
            default: printf("Invalid choice! Please try again\n");
                    printf("\n");
                break;
        }
    }

    else
    {
        printf("Characters are invalid, please enter a number: \n ");
        if (scanf("%d",&loopagain)==1)
            load_menu();
    }

}while((choice !=4));
}

why is this still giving me an infinite loop when I enter a character? It is a menu (the case statements still need to be filled) but i am taking care of the character input by the if statement but it still does not seem to work. Thanks

Upvotes: 1

Views: 514

Answers (4)

Afonso Tsukamoto
Afonso Tsukamoto

Reputation: 1214

I think your problem is the loopagain variable. By the name, you were thinking about this variable like a flag to loop or not again and to manage the way your second loop would go. Since you are reading it from stdin(scanf) you'll lost the control over it. Since you already have one scanf in your implementation and since it is a loop, you won't need recursive calls and you can use always the same scanf, using the loopagain variable/flag in the proper way. Even better is that in this way, there's no char wich its integer value is 4(it woul never pass the scanf test with value 1, but still...) besides the EOT (ascii - cntr-D) wich is a non-common one, and you can think of it as an alternative way to break your program.

One soluiton is this(I guess, by my interpretation) :

 #include <stdio.h>
    void load_menu(void);

    int main(void)
    {
        load_menu();
        return 0;
    }

    void load_menu(void)
    {
    int choice;
    int loopagain = 1;

    do
    {
        if(loopagain != 0){    /*You'll set it to different from 0 if the user entered a 'bad' number so the menu is only printed once*/
           printf("Menu \n\n");
           printf("Please enter your choice: \n");
           printf("1. \n");
           printf("2.\n");
           printf("3.\n");
           printf("4. Exit\n");
        }
        if (scanf("%d",&choice)==1)
        {

            switch(choice)
            {
                case 1:
                        break;
                case 2:
                        break;
                case 3:
                        break;
                case 4: printf("Quitting program!\n");
                        break;
                default:printf("Invalid choice! Please try again\n");
                        loopagain = 0;
                        printf("\n");
                    break;
            }
        }else{
            printf("Characters are invalid, please enter a number: \n ");
            loopagain = 0;
        }

    }while(choice !=4);
 }

Hope it helped.

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129314

I believe, aside from the problems identified so far, is that the offending "letter" is stuck in the input buffer. When reading a number with scanf, it stops as soon as it hits anything not whitespade and not a digit. So if the buffer contains "a\n", and we call scanf("%d", ...), then scanf will return immediatelty, and will keep on doing so until the offening 'a' has been removed from the buffer.

What we need is a little loop to remove the offending "rubbish" from the input buffer.

Here's that question asked before (although the flushing is for a slightly different reason, the solution is the same): Question about flushing buffer

Upvotes: 1

femtoRgon
femtoRgon

Reputation: 33341

After you enter something the is not a digit, and as such is not accepted by scanf("%d",&choice) the input buffer is not flushed. I believe you should be able to fix this issues with a call to fflush(stdin) when handling unacceptable inputs. Better, you would probably be better servde to flush the input buffer after each time you call scanf.

To my mind, your handling of an incorrect input doesn't make sense. It should be handled more like your default: case, I think. The recursive call, as has been stated by others, doesn't make sense, nor does calling scanf again for input when you are about to go back to displaying the menu and getting user input yet again.

Upvotes: 0

Ry-
Ry-

Reputation: 224857

If the character input is invalid, the loopagain in the newly-called load_menu() won’t be the same as in its caller. Don’t recurse at all:

else
{
    printf("Characters are invalid, please enter a number: \n ");
    choice = 0; // Unused, so continue the loop
}

Upvotes: 4

Related Questions