1
#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

Joel Rondeau
  • 7,486
  • 2
  • 42
  • 54
user1930901
  • 211
  • 3
  • 9

4 Answers4

4

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
}
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • I arranged it but it still gives an infinite loop if the input isn't an integer – user1930901 Dec 26 '12 at 23:48
  • @user1930901: "Infinite" how? If you keep entering non-integers, then no, it won’t end... – Ry- Dec 26 '12 at 23:50
  • i arranged the infinte loop but now if i enter a character it just displays that characters are not valid and doesn't give me a chance to reenter an integer. That is why I used the load_menu twice – user1930901 Dec 26 '12 at 23:57
  • @user1930901: Ah, you need to flush it, too. Check the other answers. – Ry- Dec 27 '12 at 00:45
1

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

Community
  • 1
  • 1
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

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.

femtoRgon
  • 32,893
  • 7
  • 60
  • 87
  • As explained in the link I posted a few seconds ago, fflush(stdin) _ONLY_ works on certain platforms with the right C library. In Linux for example, it won't work (and it is undefined, so it's perfectly legitimate for the compiler to generate code that CRASHES if you do so - I don't believe that's likely, but it's not without possibility) – Mats Petersson Dec 26 '12 at 23:57
0

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.

Afonso Tsukamoto
  • 1,184
  • 1
  • 12
  • 21