?
Solved

simple C++ text menu

Posted on 2003-03-20
24
Medium Priority
?
4,635 Views
Last Modified: 2007-12-19
I am just trying to implement a simple 5 option menu. The menu functions well except upon bad input. I am looking for a way (possibly using cin.get or cin.ignore) to prevent the program from screwing up when there is bad input from the user.  heres my code thusfar:

#include<iostream.h>
#include <stdlib.h>

//function prototypes
void DisplayMenu();

int main()
{
     //variable declarations
     char menuChoice;

     //while loop to display menu until user exits
     while(menuChoice != 5)
     {
          DisplayMenu();
          cin >> menuChoice;
         
          switch(menuChoice)
          {
          case '1':
               system("cls");
               cout << "Option 1 code goes here \n";
               cout << endl;
               system("pause");
               system("cls");
               break;
          case '2':
               system("cls");
               cout << "Option 2 code goes here \n";
               cout << endl;
               system("pause");
               system("cls");
               break;
          case '3':
               system("cls");
               cout << "Option 3 code goes here \n";
               cout << endl;
               system("pause");
               system("cls");
               break;
          case '4':
               system("cls");
               cout << "Option 4 code goes here \n";
               cout << endl;
               system("pause");
               system("cls");
               break;
          case '5':
               cout << "\n*THANK YOU HAVE A NICE DAY*\n";
               return 1;
          default:
               system("cls");
               cout << "\n*YOU DID NOT ENTER A VALID MENU OPTION. PLEASE TRY AGAIN* \n \n";
               cout << endl;
               system("pause");
               system("cls");
               break;

          }//ends switch
     
     }//ends while
         
     return 0;
}//ends main
//========================================================================================
//Displays User Options Menu
void DisplayMenu()
{
     cout << "=============================================== \n";
     cout << "||  please choose an item on the menu below  || \n";
     cout << "||-------------------------------------------|| \n";
     cout << "||               (1) Option 1                || \n";
     cout << "||               (2) Option 2                || \n";
     cout << "||               (3) Option 3                || \n";
     cout << "||               (4) Option 4                || \n";
     cout << "||               (5) Quit                    || \n";
     cout << "=============================================== \n";
     cout << "Your Choice: ";
}
//=========================================================================================
0
Comment
Question by:spoontangclan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
  • 4
  • +3
24 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 8172664
I think it's better to use getch instead of
cin >> menuChoice;
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 8172666
I am confused by your definition of screwing up.
The code you have written so far will always fall through to the default clause of the switch statement, which you have programmed to display an error message.

If you do not want to display this message you can simply lose the system("pause") call and stick NULL on there; this will of course negate the effect of outputting a message as the user will not be able to see it, and will just redisplay the menu.

I think the code you have got so far is fine.
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 8172671
ammendment to second sentence:

The code you have written so far will always fall through to the default clause of the switch statement, which you have programmed to display an error message *when the user enters an invalid choice*.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 30

Expert Comment

by:Mayank S
ID: 8172674
Your program will not screw up as far as I can see. It will catch an unwanted character and display "You did not enter a valid menu option. " and still carry on with the while loop as long as 5 is not pressed.

I would just like to give you 2 suggestions:

1. Initialize 'menuChoice' with a value not equal to 5 (in case the compiler assigns it a default value of 5,  then it won't enter the while loop at all) - or else, make it a do-while loop.

2. Write fflush ( stdin ) ; after every cin >> where you're reading a character. (Also, include stdio.h for that.)

If there are any other problems, please let us know.

Mayank.
0
 
LVL 22

Expert Comment

by:nietod
ID: 8173267
>> I think it's better to use getch instead of
>> cin >> menuChoice;
BAD ADVICE.  Stick with standard C++.   Even if you have the option to use getch()  (and you certainly might not)  stay away from it.

>> The code you have written so far will always fall through to the
>> default clause of the switch statement,
IWhy???  It shouldn't unless they type something invalid.  

>>  Initialize 'menuChoice' with a value not equal to 5 (in case the
>> compiler assigns it a default value of 5,
Better than that.   change the line

   while(menuChoice != 5)

to

    while (true)

Then the loop will always run.  That's okay.  The previous loop shoudl have allways run too.  The code doesn't exist through the test for "choice" being 5.   It exits by returning from the function or by "break"ing the loop.  so there is no need for that test at the top of the loop.
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 8173290
nietod,

I did actually correct myself on that incorrect reference I made at 02:06AM PST; it is directly below the incorrect post.

:)
0
 
LVL 22

Expert Comment

by:nietod
ID: 8173346
I didn't read that as a correction, just an addition.  You don't seem to say that the problem you pointed out earlier isn't there--and its not there that I can see.
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 8173369
"ammendment to second sentence:

The code you have written so far will always fall through to the default clause of the switch statement, which you have programmed to display an error message *when the user enters an invalid choice*. "

-- Better when rewritten as

"Correction to second sentence:

The code you have written so far will always fall through to the default clause of the switch statement *when (and if) the user enters an invalid choice*.  You have programmed the code to display an error message in this case."
0
 

Author Comment

by:spoontangclan
ID: 8177364
thank you all for the advice, perhaps my question was not clear before. i am having a problem with specific input. such as, if i enter "55" for menuChoice, the program will cin the first 5 and exit the program. Additionally, if i enter "999" it outputs "you did not enter a valid menu option" 3 times. is there anyway to avoid these things from happening?
0
 
LVL 22

Expert Comment

by:nietod
ID: 8177412
One solution would be to work with integers, like

int main()
{

   //while loop to display menu until user exits
   while(true)
   {
   //variable declarations
   int menuChoice;  // its better here, but you coudl have this at the top too.


   DisplayMenu();
   cin >> menuChoice;
                   
    switch(menuChoice)
    {
    case 1:    // note complare for 1 not '1'.
       system("cls");
       cout << "Option 1 code goes here \n";
       *      *     *
     }//ends switch
               
   }//ends while
}

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 8177460
This is a little better.   For example, If they enter 999 it will be treated as one number and you will get only 1 error message.  

However its not perfect.    If they enter "abc" you will get an error as that can't be converted to an integer value.  The stream (cin) will set an error flag and will appear to not operate.  You can clear that error flag, but you also need to clear out the abc and that is a pain.

So if you want to get really good results, you need to take a different approach.  One that is better, but not too hard, is to  read the input as a word, then conver that word to an integer, and use the integer like I posted in the above code.  For example

while(true)
{
   string InputLine;

   getline(cin,InputLine);

   int MenuChoice = atoi(InputLine.c_str());
   switch (MenuChoice)  
   {
      case 1:
   }
}

the advantage here is that if they enter input that is not a number, the invalid input will still be read safely fromt he stream so it doesn't continue to cause problems.  When atoi() is given the invalid input it will return 0 and that will cause the invalid input error message.
0
 

Author Comment

by:spoontangclan
ID: 8177465
working with integers would cause an infinite loop to occur if a bad input of a character was entered.
0
 

Author Comment

by:spoontangclan
ID: 8177491
nietod, i tried to implement your suggestion, what include file do i need for string and getline?
0
 

Author Comment

by:spoontangclan
ID: 8177539
thank you all for the advice, perhaps my question was not clear before. i am having a problem with specific input. such as, if i enter "55" for menuChoice, the program will cin the first 5 and exit the program. Additionally, if i enter "999" it outputs "you did not enter a valid menu option" 3 times. is there anyway to avoid these things from happening?
0
 
LVL 22

Expert Comment

by:nietod
ID: 8177856
>> working with integers would cause an infinite loop to occur if a
>> bad input of a character was entered.
There is no reason for that.  If you had a mistake in your code it might.  but you could say the same thing about working with char.  There is nothing intrinsically wrong with working with integers for this!

>>  string and getline?
#include <string>

>>  perhaps my question was not clear before. i am having a problem with
>> specific input. such as, if i enter "55" for menuChoice, the program will
>> cin the first 5 and exit the program
That was clear.  The code I posted was for 2 different solutions to those sorts of problems.  The first one is simpler, but doesn't work well if the user enters text that is not a number.  (It does work well for multi-digit numbers.)   the 2nd one is more complex, but handles any input reasonably well.  Ther are even better solutions, but they are still more complex.
0
 

Author Comment

by:spoontangclan
ID: 8178413
i believe i discovered the solution i was looking for:

char input[80];
char menuChoice;
//while loop to display menu until user exits
while(true)
{
     DisplayMenu();
     cin >> input;
     menuChoice = input[0];
         
        //to prevent input such as '55' from quitting the program
     if (input[0] == input[1])
     {    
          menuChoice = -1;
     }
     
     switch(menuChoice)
     {
     case '1':
          system("cls");
          cout << "Option 1 code goes here \n";
          cout << endl;
          system("pause");
          system("cls");
          break;
     *   *   *
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 8178586
That doesn't really work.  what if they enter 52?   It will act like they entered 5, and will quit.

What was wrong with the solutions I gave you.  (not that anything was wrong with them, but what problems did  you have with them?)
0
 
LVL 22

Expert Comment

by:nietod
ID: 8178601
If you don't want to use string objects and prefer to use character arrays instead--which is definitely a bad idea, then you could use

while(true)
{
   char InputLine[80];

   cin >> InputLine;

   int MenuChoice = atoi(InputLine);

   switch (MenuChoice)  
   {
      case 1:
          etc etc etc
   }
}
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8178955
>> if i enter "55" for menuChoice, the program will cin the first 5 and exit the program

Yes, it will, because you have defined menuChoice as a character, so it can accept only a single character value and therefore, it takes the first '5' and exits the program.

>> if i enter "999" it outputs "you did not enter a valid menu option" 3 times

Same reason.... menuChoie can hold one character at a time and so, it accepts the first '9' and the rest of the 2 are there in the input buffer. So, the next 2 times, it again reads these two '9's from the input buffer and ends up saying "Invalid input" three times.

You can try the following:

char str[10] ;
int menuChoice ;

do
{
  cout << "\n Enter your choice: " ;
  cin.getline ( str, 80 ) ;
  fflush ( stdin ) ; // might be needed to clear the input buffer - while entering characters or strings in a loop, it often causes trouble

  menuChoice = atoi ( str ) ;

  switch ( menuChoice )
  {
    case 1: ..
            ..



  } // end of switch

} while ( menuChoice != 5 ) ; // end of do-while


The function atoi () takes a string as argument (which may include an optional positive or negative sign too), converts it to an integer and returns that integer. If the string cannot be converted, it returns a 0. You need to include <stdlib.h> for that.

Hope that much helps!

Mayank.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8178962
Oops - please define str[] as char str[80] instead of char str[10] in the above example..

Mayank.
0
 

Author Comment

by:spoontangclan
ID: 8179539
nietod:
<<What was wrong with the solutions I gave you.  (not that anything was wrong with them, but what problems did  you have with them?)>>
i could not declare a string variable. I did #include<string> yet i still got errors on the variable declaration string stringName;

working w/ integers didnt work either because my teacher was saying that the input should be fullproof and if i entered a character when its expected an integer i had a problem.

<<That doesn't really work.  what if they enter 52?   It will act like they entered 5, and will quit.>>
i have tweaked the code even further and i think its finally done. heres what i got.
char input[80];
char menuChoice;
//while loop to display menu until user exits
while(true)
{
        DisplayMenu();
     cin.getline(input, 80);
     menuChoice = input[0];
     //if input is longer than a character the         menuchoice is set to a negative so it will fall through to the default case.
     if (strlen(input) > 1)
     {    
          menuChoice = -1;
     }
         
     switch(menuChoice)
     {
     case '1':
        etc etc etc...

im not sure how the points system here works, thanks for working along with me to help me solve this problem. Since i didn't use one of your solutions precisely do i still award the points to someone? or does in not matter?
0
 
LVL 22

Accepted Solution

by:
nietod earned 80 total points
ID: 8180104
>> i could not declare a string variable. I did #include<string> yet
>> i still got errors on the variable declaration string stringName;
You didn't say that before.   And you have't explained what the errors are.   so its hard for me to say what the problem is.

Have you used string objects before?

> working w/ integers didnt work either because my teacher
>> was saying that the input should be fullproof and if i entered
>> a character when its expected an integer i had a problem.
When I posted my 2 examples, I explained that this was a flaw with the 1st example, and this I posted a 2nd example without this flaw.

>>  have tweaked the code even further and i
>> think its finally done. heres what i got.
that's better still, but not perfect.   What if they enter "   1"  i.e if they enter spaces before their response.   That will be considered invalid.  I don't know if you care about that case or not.

>> do i still award the points to someone?
That's up to you.
0
 
LVL 9

Expert Comment

by:tinchos
ID: 9510721
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by: nietod

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 9513726
Points - nietod.
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses
Course of the Month12 days, 20 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question