-1

I was doing a project for an online course and the final project was to make a Build Your Adventure program where the user has choices and they lead to endings. I deleted the huge intro and just now copied the part where I have the first choice. So basically, it all works when I don't write valid numbers, but when I write in a letter... the whole program begins an infinite loop. Please help! Here is the code:

#include <iostream>

int main() {

    int c1;

    std::cout << "After what felt like thirty minutes of "
                 "walking you reached a wall. Yes, a wall.\n"
                 "A wall so tall and wide you couldn't imagine "
                 "climbing over it or walking around it.\n";
    std::cout << "Luckly, you see two animals willing to help you.\n"
                 "1) A mole that can build a tunnel under the wall\n"
                 "2) An eagle that can carry you over the wall\n";
    std::cout << "Enter 1 or 2 to make a choice: ";
    std::cin >> c1;

    while (!(std::cin >> c1) || c) {
        std::cout << "Error! Please enter a valid input!\n";
        std::cout << "Enter 1 or 2 to make a choice: ";
        std::cin >> c1;
        std::cout << "\n"
    }
JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
Cade
  • 1
  • 2
  • And also when I try input the correct value it is also wrong...I am new to C++ so I need help – Cade Apr 17 '20 at 16:14
  • If you enter a non-digit, the formatted input of `int` fails and sets the `std::cin` into fail state. You have to `clear()` the error _and_ to `ignore()` the wrong input (to empty your input queue and get rid of the wrong stuff). – Scheff's Cat Apr 17 '20 at 16:15
  • Can you just briefly show what you mean. Is it after or before the new input? – Cade Apr 17 '20 at 16:16
  • FYI: [SO: Why would we call cin.clear() and cin.ignore() after reading input?](https://stackoverflow.com/a/5131654/7478597) – Scheff's Cat Apr 17 '20 at 16:16
  • So I just need to add those two lines before the new input? – Cade Apr 17 '20 at 16:18
  • IMHO, you should distinguish `std::cin >> c1` (it returns `false` when formatted input failed and hence you need to `clear()` the error flag and `ignore()` the wrong input) from a valid integer for which you need a range check. E.g. if you input `7` this leaves the formatted input in good state but your range check should sort it out, shouldn't it. – Scheff's Cat Apr 17 '20 at 16:21
  • Yepp. `cin` is a global variable in `namespace std`. So, everytime you use it you should prefix it with its scope -> `std::cin` (regardless if you use it with `>>` or call member functions for it). – Scheff's Cat Apr 17 '20 at 16:22
  • [**Sample on coliru**](http://coliru.stacked-crooked.com/a/7f112d45c7814c1d). Please note, in your code, you do `std::cin >> c1;` (without error check) before `while (!(std::cin >> c1) || c) {`. So, these are two inputs to `c1` but you want only one. – Scheff's Cat Apr 17 '20 at 16:32
  • JohnFilleau is there a way to send codes to specific people? If you want I can send you my finished version. – Cade Apr 18 '20 at 17:11
  • You can add a [self-answer](https://stackoverflow.com/help/self-answer). Btw. if you want to address specific people in comments you have to prefix their name with an `@`. In this case, they will get a notification. – Scheff's Cat Apr 18 '20 at 18:08

1 Answers1

0

When you input invalid inputs for int, the stream goes into failed state and can't read further inputs. So you have to clear the error state of the stream and ignore anything left in the input stream.

#include <iostream>
#include <limits>

int main() {

    int c1;

    while (true)
    {
        std::cout << "Enter 1 or 2 to make a choice: ";

        if ((std::cin >> c1) && (c1 == 1 || c1 == 2)) break;
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "Error! Please enter a valid input!\n";
    }

    // Now c1 is either 1 or 2 
}
P.P
  • 117,907
  • 20
  • 175
  • 238