Thread: menu

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    55

    menu

    Hi all,
    I've got a problem with a simple menu. After a question that I print to the terminal, I want to enter an answer. What actually happens is that the while loop executes twice before I can enter my answer (y or n). The first execution goes to the default switch, and the second execution allows me to enter my answer. Why does this happen, and how can I get round this problem?

    thanks
    Spiros

    PS I'm not posting all te code as its getting near 500 lines...

    Code:
            while(1) {
                    printf("...question... (yes/no) ");
                    ch=toupper(getchar());
                    switch(ch) {
                            case('Y'): 
                                    operation1;
                                    break;
                            case('N'):
                                    operation2
                                    break;
                            default: printf("Incorrect choice, try again\n");
                    }
                    if (ch=='Y' || ch=='N') {
                            break;
                    }
            }

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You need to clear the input buffer; the second time around the getchar() reads the '\n' that the user entered the first time as "Y\n" or something.

    http://faq.cprogramming.com/cgi-bin/...&id=1043284392

    This ought to do:
    Code:
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    thank you. I did have a look at this before you posted, but I cannot understand what is happening in the which statement. I don't see any operation being performed, just a conditional, so how is the buffer cleared?

    I did what you suggested and it works now, but I don't understand what's going on. Can you please provide a brief explanation?

    thank you

    Spiros

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    int c;
    while ((ch = getchar()) != '\n' && ch != EOF);
    is the same as
    Code:
    int c;
    for(;;) {
        ch = getchar();  /* get a character from the buffer */
        if(ch == '\n' || ch == EOF) {  /* if it's the last character in the line */
            break;  /* stop reading in characters from the input buffer */
        }
    }
    Better?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    I think I understand now, so thanks. I don't want to be a pain, but I've got another question. Why is:
    Code:
            while ((ch = getchar()) != '\n' && ch != EOF);
            do {
                    printf("Ring elements? (yes/no) ");
                    ch=toupper(getchar());
                    switch(ch) {
                            case('Y'):
                                    for (i=11; i<=15; i++) {
                                            printf("Group %s: ", group_name[i]);
                                            scanf("%i", &groups[i]);
                                    }
                                    break;
                            case('N'):
                                    break;
                            default: printf("Incorrect choice, try again\n");
                    }
                    if (ch=='Y' || ch=='N') {
                            break;
                    }
            } while (1);
    working, and
    Code:
            do {
                    printf("Ring elements? (yes/no) ");
                    while ((ch = toupper(getchar())) != '\n' && ch != EOF);
                    switch(ch) {
                            case('Y'):
                                    for (i=11; i<=15; i++) {
                                            printf("Group %s: ", group_name[i]);
                                            scanf("%i", &groups[i]);
                                    }
                                    break;
                            case('N'):
                                    break;
                            default: printf("Incorrect choice, try again\n");
                    }
                    if (ch=='Y' || ch=='N') {
                            break;
                    }
            } while (1);
    isn't (ie still printing twice)?

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Neither of them should work; the first one has the input-clearer outside the loop, so unless you have input-reading code before the loop it won't do what you want; and the seond is an infinite/one-time loop because you got rid of the getchar(). [edit] Or rather, ch will always contain '\n' or EOF. Which is still infinite. [/edit]

    This should work:
    Code:
    int c;
            while(1) {
                    printf("...question... (yes/no) ");
                    ch=toupper(getchar());
                    while ((c = getchar()) != '\n' && c != EOF);
                    switch(ch) {
                            case('Y'): 
                                    operation1;
                                    break;
                            case('N'):
                                    operation2
                                    break;
                            default: printf("Incorrect choice, try again\n");
                    }
                    if (ch=='Y' || ch=='N') {
                            break;
                    }
            }
    See, the thing is that you have to use a different variable in the input-clearer than the rest of the loop. The variable used in the input-clearer should be unique and not used elsewhere. If it is, it will always contain '\n' or EOF, and never 'Y' or whatever the user entered.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    thank you very much for your time, now I understand very well what's going on.

    Spiros

  8. #8
    Jaguar
    Join Date
    Sep 2006
    Posts
    12
    Hey Spiros,

    Nothing wrong with your original code. It works. I just compiled it and executed with Turbo C.
    Cause for your problem may be a previous input. It probably gets the enter of your previous input.

    Jag

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Yes, that's true, there may be a '\n' already sitting in the buffer; but what happens if you enter "hmm... yes" with the original code? First of all, you get lots of "incorrect choise"es, second lots of stuff is left in the buffer (which also happens with the updated code).
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. Replies: 2
    Last Post: 03-05-2009, 10:25 AM
  3. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  4. Constructive Feed Back (Java Program)
    By xddxogm3 in forum Tech Board
    Replies: 12
    Last Post: 10-10-2004, 03:41 AM