2

Sorry if I fail to be clear enough or make any mistakes, this is my first time posting.

My code runs without errors when complied but the first while loop (in int main) gets stuck looping whenever a user types a letter (like "a") for cin >> select; instead of the required 1, 2, or 3.

However, when I input "4" or any other random string of numbers, it runs fine and goes to my error message like it should.

Why is this and what can I do to make it run normally? (run the error message in response to letters entered as if they were numbers).

My code:

#include <iostream>
#include <string>
using namespace std;

void calculator();
void unavailableitem();

int main()
{
    string select;
    while (true)
    {
        cout << "\t[Main Menu]\n";
        cout << " 1. Calculator\n";
        cout << " 2. [unavailable]\n";
        cout << " 3. [unavailable]\n";
        cout << "\n Enter the number of your selection: ";
        cin >> select;

        if (select == "1")
        {
            cout << endl;
            calculator();
            break;
        }
        else if (select == "2")
        {
            unavailableitem();
            break;
        }
        else if (select == "3")
        {
            unavailableitem();
            break;
        }
        else
            cout << "\nInvalid response.\n";
    }
}

void unavailableitem()
{
    string react;
    cout << "\n \t [ITEM UNAVAILABLE]\n";
    while (true)
    {
        cout << "\nEnter 'menu' to return to main menu: ";
        cin >> react;

        if (react == "menu")
        {
            cout << endl;
            main();
            break;
        }
        else
            cout << "\nInvalid response.\n";
    }
}

void calculator()
{
    int choice;
    double num1;
    double num2;
    double answer;
    string choicesymbol;

    cout << "List of operations:\n";
    cout << " 1. Addition\n";
    cout << " 2. Subtraction\n";
    cout << " 3. Multiplication\n";
    cout << " 4. Division\n";
    cout << "Enter the number on the left to pick an operation: ";
    cin >> choice;
    cout << "\nEnter number 1: ";
    cin >> num1;
    cout << "\nEnter number 2: ";
    cin >> num2;

    if (choice == 1)
    {
        answer = num1 + num2;
        choicesymbol = " + ";
    }

    if (choice == 2)
    {
        answer = num1 - num2;
        choicesymbol = " - ";
    }

    if (choice == 3)
    {
        answer = num1 * num2;
        choicesymbol = " * ";
    }

    if (choice == 4)
    {
        answer = num1 / num2;
        choicesymbol = " / ";
    }

    cout << endl;
    cout << num1 << choicesymbol << num2 << " = " << answer;
}

New code:

#include <iostream>
#include <string>
using namespace std;

void calculator();
void unavailableitem();


int main()
{
    int select;
    while (true)
    {
        cout << "\t[Main Menu]\n";
        cout << " 1. Calculator\n";
        cout << " 2. [unavailable]\n";
        cout << " 3. [unavailable]\n";
        cout << "\n Enter the number of your selection: ";
        cin >> select;

        if(!(cin >> select))
        {
        cout << "Input must be an integer.\n";
        cin.clear();
        continue;
        }
        else if (select == 1)
        {
            cout << endl;
            calculator();
            break;
        }
        else if (select == 2)
        {
            unavailableitem();
            break;
        }
        else if (select == 3)
        {
            unavailableitem();
            break;
        }
    }
}



void unavailableitem()
{
    string react;
    cout << "\n \t [ITEM UNAVAILABLE]\n";
    while (true)
    {
        cout << "\nEnter 'menu' to return to main menu: ";
        cin >> react;

        if (react == "menu")
        {
            cout << endl;
            return;
            break;
        }
        else
            cout << "\nInvalid response.\n";
    }
}

void calculator()
{
    int choice;
    double num1;
    double num2;
    double answer;
    string choicesymbol;

    cout << "List of operations:\n";
    cout << " 1. Addition\n";
    cout << " 2. Subtraction\n";
    cout << " 3. Multiplication\n";
    cout << " 4. Division\n";
    cout << "Enter the number on the left to pick an operation: ";
    cin >> choice;
    cout << "\nEnter number 1: ";
    cin >> num1;
    cout << "\nEnter number 2: ";
    cin >> num2;

    if (choice == 1)
    {
        answer = num1 + num2;
        choicesymbol = " + ";
    }

    if (choice == 2)
    {
        answer = num1 - num2;
        choicesymbol = " - ";
    }

    if (choice == 3)
    {
        answer = num1 * num2;
        choicesymbol = " * ";
    }

    if (choice == 4)
    {
        answer = num1 / num2;
        choicesymbol = " / ";
    }

    cout << endl;
    cout << num1 << choicesymbol << num2 << " = " << answer;
}
user3369725
  • 23
  • 1
  • 4
  • 2
    Please read about the failbit - http://www.cplusplus.com/reference/ios/ios/fail/ – Ed Heal Mar 02 '14 at 02:04
  • Thanks for the response. I read this but I don't understand. I'm new to C++. – user3369725 Mar 02 '14 at 02:06
  • 1
    There must be millions of similar questions about this by now. Please spend a day or three browsing Stack Overflow. – Kerrek SB Mar 02 '14 at 02:10
  • You shouldn't be calling `main` in your program. Since you're calling `unavailableitem` from `main`, just type `return;` to exit the function. Also, while your program is "short" and compilable, programs that require input are usually harder to debug, especially if it requires a long string of input. Try minimizing your program so that it requires little to no input. Finally, please remove the `letter` tag. –  Mar 02 '14 at 02:12
  • Don't call main in your program it isn't allowed. Look at [Is it legal to recurse into main() in C++?](http://stackoverflow.com/a/4518625) – AliciaBytes Mar 02 '14 at 02:24
  • @RaphaelMiedl Thank you both, I didn't notice that. I removed the main calls and I'm going to take a look at that post you linked Raphael. Program still gets stuck looping but I'm looking into it. – user3369725 Mar 02 '14 at 02:45

2 Answers2

3

Ad Ed Heal mentioned, the issue here is cin's failbit. When you do cin >> choice, and the user types "a", then the conversion to int fails. This sets cin's failbit, making all future reads from it fail until the failbit is cleared. So the next time you reach cin >> choice, the user won't even get to type anything.

You can use cin.clear() to restore to working order.

To do this a bit more robustly, you could do something like

while(true)
{
    cout >> "Enter choice [1-4]: ";
    if(!(cin >> choice))
    {
        cout << "Input must be an integer.\n";
        cin.clear();
        continue;
    }
    do_stuff_with_choice();
 }    
amaurea
  • 4,950
  • 26
  • 35
  • Okay, thanks a lot, this is starting to make more sense to me now that you cleared it up. I added your code and made a `do_stuff_with_choice();` function but I still run into the same loop error after first inputting "a" into my program. I posted my new code above right under the old one. – user3369725 Mar 02 '14 at 02:48
  • You have `cin >> select;` followed by `if(!(cin >> select))`. Get rid of the first `cin >> select;` – fredoverflow Mar 02 '14 at 07:23
  • I was referring to the loop in `calculator` actually. The one in `main` used a `string`, not `int`, and so would not get any conversion failures. – amaurea Mar 02 '14 at 11:07
1

I am a newbie to programming in general, but playing with your code and looking up stuff made me find some sort of solution. The cin.clear only clears the error log of the input, and I believe that it still retains the value of the letter.

What you should add right after is a cin.ignore(#,'\n') (# being a very, very large number) to have it avoid the line and skip right through it.

Found the solution in another question that explains the use of both cin commands.

Community
  • 1
  • 1
FefeHern
  • 71
  • 9
  • Oh my god. It works! Goes straight to the error now. Thank you so much! I don't understand exactly how this works but I will read that question you linked. I'm so happy, I was so stuck on this. Thanks again. Time to get reading and learn some things. I am quite surprised that you consider yourself a newbie but can figure out something like that since it seems so cryptic to me. Time to get learning. – user3369725 Mar 02 '14 at 19:47