-1

I have a menu created where the user has to input a number between 1-5, anytime the user inputs a numeric value it works perfect, it will either go to the specified case or in case of an invalid digit, it will go to default and an error message will appear.

Now my problem is when the user inputs an alphabet letter, the program keeps looping and looping, it won't stop, each time going through the default.

I've tried many things! Using an if statement to check whether the number is 1 <= value <= 5, doesn't work. I tried hard-coding in a number if the input is not between those values, it still loops forever. I tried doing cim.good(), not sure if I did it right, but the way I did it doesn't work. I also tried to use the isdigit() function, but same problem, it doesn't work... I really don't know what I gotta do. Here is what I have (simplified).

int menu()
{
    int key;
    cout << endl << "--------- Main Menu ----------" << endl;
    cout << "1: Sort" << endl << "2: Add" << endl;
    cout << "3: Search" << endl << "4: History" << endl << "5: Exit" << endl;

    cout << "Please pick one: ";
    cin >> key;

    return(key);
}`

void main()
{
    Menu:
            key = menu();

            switch(key)
            {
            case 1:
                goto Menu;
            case 2:
                goto Menu;
            case 3:
                goto Menu;
            case 4:
                goto Menu;
            case 5:
                break;
            default:
                cout << endl << "Invalid entry, please try again" << endl;
                goto Menu;
            }
}

I deleted what's inside the cases to make it look nicer. When I type in a key, I keep getting the "Invalid entry, please try again" message, so that's where it is going through.

EDIT: Well I apologize for the 'goto', didn't know it was frown upon, still learning! Thank you everyone for all the help though. I will start removing them for sure.

Maty
  • 95
  • 2
  • 12
  • 4
    `goto`? in C++? orly? http://stackoverflow.com/questions/3517726/what-is-wrong-with-using-goto – Jack Jan 13 '15 at 19:13
  • 4
    Avoid `goto` unless it makes things easier to understand. Tip: That means an expert might use it once in a decade or such... – Deduplicator Jan 13 '15 at 19:16
  • "I tried doing cim.good(), not sure if I did it right, but the way I did it doesn't work." Please try to give more details what you did next time, so we can try to give you some specific hints for your errors. – LiKao Jan 13 '15 at 19:27
  • 1
    To everyone else: Please do not downvote because of bad coding style, only if you believe the question is unclear, could be improved. We all have been beginners once and had worse style than today. If you downvote, please comment why you downvoted (to help the person improve the question). Similarly give help how the style could be improved in the comments. – LiKao Jan 13 '15 at 19:29
  • cin and cout are for "Strings" not for "int" Consider using "int" by using getchar() function; – Paulie Jan 13 '15 at 19:29
  • @LiKao I'm certainly not down-/close voting for _bad coding style_ but for LQ questions that miss any debugging efforts. – πάντα ῥεῖ Jan 13 '15 at 19:30
  • @πάνταῥεῖ: Ok, then comment what could be improved, please. Beginners should be educated, not be discouraged. – LiKao Jan 13 '15 at 19:33
  • @LiKao I don't care about beginner or not. It's their duty, to [inform themselves](http://stackoverflow.com/help) before asking here. – πάντα ῥεῖ Jan 13 '15 at 19:35
  • @πάνταῥεῖ: From your Link: "Be welcoming, be patient, and assume good intentions. Don't expect new users to know all the rules — they don't. And be patient while they learn. If you're here for help, make it as easy as possible for others to help you. Everyone here is volunteering, and no one responds well to demands for help." – LiKao Jan 13 '15 at 19:38
  • @LiKao Good point. May be too much grumpyness from my side ... – πάντα ῥεῖ Jan 13 '15 at 19:39
  • 3
    @Kenyanke: Sorry but that's nonsense. Formatted I/O is one of the powerful features of C++ streams, and `std::cin`/`std::cout` are both C++ streams. `getchar` is an antiquated C function. – Lightness Races in Orbit Jan 13 '15 at 19:45
  • I am going to research Elliott's approach. I don't mind the downvote if I deserve it or not, I am just seeking help and thank you that helped me out. I learned a few things. And if the problem was debugging/effort, I didn't knew any of the functions I mentioned in the 3rd paragraph. Should of researched it more I guess. – Maty Jan 13 '15 at 19:47
  • @πάνταῥεῖ: No offense taken or meant by me... Also I didn't mean that downvoting isn't ok. However it's a binary signal ("you did something wrong"). Better to give this signal and point out what it was that the person did wrong. – LiKao Jan 13 '15 at 19:55
  • @LiKao All fine. [Look here though ...](http://stackoverflow.com/questions/27929839/program-throwing-exception#comment44256885_27929839) – πάντα ῥεῖ Jan 13 '15 at 19:59
  • @πάνταῥεῖ: If you don't mind, I'll recommend that on Meta ;-). P.s. we should take this some other place as soon as possible so not to clutter the comment section. – LiKao Jan 13 '15 at 20:07
  • @LiKao I certainly don't mind, but wasn't still annoyed enough so far to do so. – πάντα ῥεῖ Jan 13 '15 at 20:12
  • @Maty: You should accept an answer you find helpful. – LiKao Jan 14 '15 at 21:46

2 Answers2

1

Rather then using goto, I suggest you use a simple do {} while loop like

#include <iostream>

using namespace std;

int menu() {
    int key;
    cout << endl << "--------- Main Menu ----------" << endl;
    cout << "1: Sort" << endl << "2: Add" << endl;
    cout << "3: Search" << endl << "4: History" << endl << "5: Exit" << endl;

    cout << "Please pick one: ";
    cin >> key;

    return(key);
}

int main(int argc, char *argv[]) {
        int key;
        do {
                key = menu();
        } while (key < 1 || key > 5);
        cout << key << endl;
}

Which loops while the key < 1 or the key > 5.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • I never seen arguments used in the main(), what does argc and argv do? I did not know goto was frown upon, however to me these simple goto look a lot neater and easier to follow than that (probably because I don't get it). But how does this code work? – Maty Jan 13 '15 at 19:25
  • @Maty They're irrelevant for your case, and optional anyway. Many programmers just use it from a template code snippet, no matter if these parameters are used or not. – πάντα ῥεῖ Jan 13 '15 at 19:27
  • 1
    AH, OK. I will do my research on the do {} function and see how it works. But one last question here, there are no cases, so how does it know where to go? Or did Elliott just left that part out, and cases go inside while? – Maty Jan 13 '15 at 19:29
  • @Maty: Have a look at this paper http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html to see why goto is frowned upon (not only in C++ but generally in programming). – LiKao Jan 13 '15 at 19:31
  • @Maty: do{} while(...) is a statement, not a function. Functions perform operations or return a result. Statements structure how the code runs. – LiKao Jan 13 '15 at 19:32
  • @LiKao So you're really going to start teaching the OP all of their text book here? Do you think feeding such expectations is helpful for the quality of SO?!? – πάντα ῥεῖ Jan 13 '15 at 19:37
  • Ah! Well I guess I never used a statement like that before. – Maty Jan 13 '15 at 19:38
  • @Elliot: While this has much better style, it will still have the problem of producing an infinite loop if a letter is input. You should add a cin.good() and cin.clear(). – LiKao Jan 13 '15 at 19:57
1

Have a look at this posting from the C++ FAQ lite and this posting.

Checking with cin.good() is the first part of the solution. If a non integer is entered cin.good() will return false. However, the incorrect input will be left in the buffer. So if you encounter the cin >> key again, it will again fail to read anything.

You have to clear the state using cin.clear() and then ignore the rest of the buffer (until end of line) using cin.ignore(INT_MAX, '\n')

So your method would become:

int menu() {
    int key;
    cout << endl << "--------- Main Menu ----------" << endl;
    cout << "1: Sort" << endl << "2: Add" << endl;
    cout << "3: Search" << endl << "4: History" << endl << "5: Exit" << endl;

    cout << "Please pick one: ";
    while(cin >> key) { // same as querying cin.good()
      cout << "Not a number" << endl;
      cin.clear();
      cin.ignore(INT_MAX, '\n');
    }

    return(key);
}
Community
  • 1
  • 1
LiKao
  • 10,408
  • 6
  • 53
  • 91
  • I did one test where I had an if statement that tested if cin.good() was invalid. And when I put a character in, I assumed it wasn't (like you mentioned), and so I hard coded the key value in there (inside the if statement), key = 6, which should of cleared it? Or no? – Maty Jan 13 '15 at 19:32
  • 1
    @Maty: Not sure what you mean by your comment. Please post the code of what you tried as an edit to your question. Real code gives a better impression of what you tried. – LiKao Jan 13 '15 at 19:41