I've just completed an exercise from a book wherein the task is to display a menu of choices each associated to an alphabetical character. The program is to reject invalid characters and only finishing when a valid choice is made. Below is my solution, it achieves the task but I'd like to know if there is a completely easier approach.

// chap05q03.cpp  
// C++ Primer Plus, Fifth Edition
// Chapter 6, Page 276.
// Programming Exercise # 3
// 4 Dec, 2007.

#include <iostream>

int main()
{
   using namespace std;
   char ch;
   char msg[] = "\nPlease enter  c, p, t or g: ";
   bool invalid = true;
		
   cout << "Please enter on of the following choices:\n\n";
   cout << "c) carnivore        p) pianist\n";
   cout << "t) tree             g) game\n";
	
   while (invalid)
   {
      cin >> ch;
      if ((ch != 'c') && (ch != 'p') && (ch != 't') && (ch != 'g'))
      {
         cin.clear();
	 while (cin.get() != '\n')
	    continue;
	 cout << msg;
      }
      else 
         invalid = false;	// we've got a correct entry, exit loop.
   }
   switch (ch)
   {
	case 'c'	: cout << "Option 'c' selected"; break;
	case 'p'	: cout << "Option 'p' selectd"; break;
	case 't'	: cout << "Option 't' selected"; break;
	case 'g'	: cout << "Option 'g' selected"; break;
	default 	: cout << "It will never get her"; break;
   }
   system("PAUSE");
   return 0;
}

Any advice welcome.

You could put the switch inside the loop (better as a do...while), let the default case handle the erroneous inputs. What is your if( ) condition becomes the while( ) condition.

Val

You could put the switch inside the loop (better as a do...while), let the default case handle the erroneous inputs. What is your if( ) condition becomes the while( ) condition.

Val

Thanks for the advice, very much appreciated. I've altered the code as suggested and is a lot 'cleaner' looking. Below is the result.

// chap05q03-a.cpp  
// C++ Primer Plus, Fifth Edition
// Chapter 6, Page 276.
// Programming Exercise # 3
// 4 Dec, 2007.

// modified after advice from DaniWeb C++ forum.

#include <iostream>

int main()
{
using namespace std;
char ch;
char msg[] = "\nPlease enter  c, p, t or g: ";
bool invalid = false;
		
cout << "Please enter on of the following choices:\n\n";
cout << "c) carnivore        p) pianist\n";
cout << "t) tree             g) game\n";
	
do 
{
	cin >> ch;
	invalid = false;  
	switch (ch)
	{
		case 'c': cout << "Option 'c' selected\n"; break;
		case 'p': cout << "Option 'p' selectd\n"; break;
		case 't': cout << "Option 't' selected\n"; break;
		case 'g': cout << "Option 'g' selected\n"; break;
		default : cout << msg;
			cin.clear();
			while (cin.get() != '\n')
				continue;
			invalid = true;
	}
} while (invalid);
system("PAUSE");
return 0;
}

You can also let 'c','p' & 't' fall through to 'g'

switch (ch)
	{
		case 'c': 
		case 'p': 
		case 't': 
		case 'g': cout << "Option '" << ch << "' selected\n";
                             break;

		default : cout << msg;
			cin.clear();
			while (cin.get() != '\n')
				continue;
			invalid = true;
	}

You can also let 'c','p' & 't' fall through to 'g'

Thanks, very much appreciated.

Thanks for the advice, very much appreciated. I've altered the code as suggested and is a lot 'cleaner' looking.

Not bad, although it's still not formatted properly.
By the way, what does cin.clear(); do? You might want to look it up.
Another thing to look at is system("PAUSE"); See this

Not bad, although it's still not formatted properly.
By the way, what does cin.clear(); do? You might want to look it up.
Another thing to look at is system("PAUSE"); See this

My understanding re cin.clear() is that if the cin fails (eof or mismatch of data) then further access or use of cin is prevented; to avoid this use the clear() method.

I guess you're probably suggesting that in this particular case it's not needed. Looking at the code I can't see how a mis-match of data cin >> ch could occur and I don't think EOF is an issue either. I hope I haven't embarrassed myself with this answer or response.

Taking this a step further in relation to cin.clear(). If the receiving variable is of a numeric type is that when cin.clear() would be considered in fixing up erroneous data entries.

My understanding re cin.clear() is that if the cin fails (eof or mismatch of data) then further access or use of cin is prevented; to avoid this use the clear() method.

True. So what error are you expecting that needs to be cleared at this point?

I guess you're probably suggesting that in this particular case it's not needed. Looking at the code I can't see how a mis-match of data cin >> ch could occur and I don't think EOF is an issue either. I hope I haven't embarrassed myself with this answer or response.

That's what I'm suggesting, yes. And you have definitely NOT embarrassed yourself. It's a correct analysis.

Taking this a step further in relation to cin.clear(). If the receiving variable is of a numeric type is that when cin.clear() would be considered in fixing up erroneous data entries.

Actually, no. All cin.clear() does is clear the error flags. If they were set, it does not fix any data entries. The way you're using it, the error is simply cleared and ignored. You never test for one, so you don't even know it happened.

What you suggested above is "If the receiving variable is of a numeric type" and you type in a letter instead, cin.clear() magically changes the letter to a digit. What in fact happens is the error flags are set, nothing is loaded into the variable (previous value remains unchanged), and the letter stays in the input stream for the next cin .

Actually, no. All cin.clear() does is clear the error flags. If they were set, it does not fix any data entries. The way you're using it, the error is simply cleared and ignored. You never test for one, so you don't even know it happened.

What you suggested above is "If the receiving variable is of a numeric type" and you type in a letter instead, cin.clear() magically changes the letter to a digit. What in fact happens is the error flags are set, nothing is loaded into the variable (previous value remains unchanged), and the letter stays in the input stream for the next cin .

The above makes sense and is 100% consistent with what I've read though I know I wasn't too clear with my explanation.

Thanks for the advice, and everyone else as well, it's really helped.

the code actually has a bug, for example you've entered something like this: c2,
the program will behave unexpectedly, how to remedy this?

the code actually has a bug, for example you've entered something like this: c2,
the program will behave unexpectedly, how to remedy this?

Good pick up. It appears that the variable ch needs to be checked prior to the switch statement. I've modified my original program that I posted at the top of this thread. What needed to be done is simply make sure that the next character was a newline, if it was then only a single character was input. If the next character wasn't a newline then something like c2 was entered.

Here's the code:

// chap06q03.cpp  
// C++ Primer Plus, Fifth Edition
// Chapter 6, Page 276.
// Programming Exercise # 3
// 4 Dec, 2007.
// 15 Apr, 2008 - modified - disregarding c2 etc.

#include <iostream>

int main()
{
    using namespace std;
    char ch;
    char msg[] = "\nPlease enter  c, p, t or g: ";
    bool invalid = true;
	
    cout << "Please enter on of the following choices:\n\n";
    cout << "c) carnivore        p) pianist\n";
    cout << "t) tree             g) game\n";
	
    while (invalid)
    {
        cin >> ch;
        if ((ch != 'c') && (ch != 'p') && (ch != 't') && (ch != 'g'))
        {
            while (cin.get() != '\n')
                continue;
            cout << msg;
        }
        else
            if (cin.get() == '\n')
                 invalid = false;
            else
            {
                while (cin.get() != '\n')
                    continue;
                cout << msg;
            }
    }
    switch (ch)
    {
        case 'c' : cout << "Option 'c' selected"; break;
        case 'p': cout << "Option 'p' selectd";break;
        case 't' : cout << "Option 't' selected";break;
        case 'g': cout << "Option 'g' selected"; break;
        default : cout << "It will never get her"; break;
    }
    // exit routine
    cout << "\n\n...Press ENTER to Exit System...";
    cin.get();
    return 0;
}

Given some time I'm sure the above program can be smoothed out, but at least it demonstrates only accepting a single character (not using strings and other methods). As it stands now, clearly there are a couple of snippets which are candidates to be functions.

well, thanks. it is a great help to me. I really find it hard before. thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.