Does this actually ensure that a number is between 1-9?

Viewed 103
int position = 0;

void set_position() {

  std::cout << "Player " << player << "'s Turn (Enter 1-9): ";

  while (!(std::cin >> position)) {

    std::cout << "Player " << player << ", please enter a valid number between 1 and 9: ";
    std::cin.clear();
    std::cin.ignore();

  }

  std::cout << "\n";

  while (board[position-1] != " ") {

    std::cout << "Oops, there's already something in that position!\n\n";

    std::cout << "Player " << player << "'s Turn (Enter 1-9): ";
    std::cin >> position;

    std::cout << "\n";
  }

}

This is a solution to a tic tac toe challenge in Codecademy and I would like to understand if the function while (!std::cin >> position)) actually checks if it is 1 to 9. Position is just an int, declared as int position = 0;. How does this actually check if it's 1 through 9? Or does it just check if it's an integer? So far Codecademy's C++ course seems to be pretty bad and doesn't go through that much.

1 Answers

Too Long Didn't Read (TLDR)

That code only filters out non-numbers.

Explanation:

To help you understand, lets look at what actually happens inside

while(!(std::cin >> position))

On the inside of all that lies std::cin >> position. >> is the "extraction operator", so we're going to extract something from std::cin (standard input). Using the >> operator really just turns around and calls operator>>() on the given object. The given object in this case is a std::istream. It's operator>>() call signature looks like:

istream& operator>> (int& val)

It returns an istream (itself), and takes a reference to an int, position in your case.

So if we evaluate std::cin >> position mentally (or in a debugger, which is much better: zero guesswork), we'll see that we've returned that istream (which is almost certainly a return *this; at the end of the function).

Now lets replace std::cin >> position with the effective return value std::cin and see what the code looks like.

while(!(std::cin))

Okay, so we need to apply the ! operator to the istream named cin. "Wait what?!" you cry... Any class/struct can define a variety of different operators, such as <<, >>, =, ==, >, <, !, *, ->... there's a bunch of them. The relevant one is the ! operator, with the following function signature and documentation:

bool operator!() const

Returns true if either failbit or badbit is set, and false otherwise. This is equivalent to calling member fail.

Incidentally, the const on the end means "we promise not to change the object running the function". This allows the compiler to make various optimizations, knowing the object's state won't change. It also lets our fellow programmers know what sorts of things are happening (and not happening) inside the function.

We'd expect that this would return true (fail or bad was set) when you type a non-digit into operator>>(int&), and we'd be right. Cheers to the library designers for following the "Principle of Least Surprise".

The return of value of operator!() is then passed into the while loop. So if someone types a letter or punctuation or what have you, they'll see the error message and have to type again.

Conclusion:

This doesn't do anything for filtering out numbers outside of 1-9, it just filters out non-numbers. You'd need new code for that, such as the suggestion in the comment by @Eljay.

Related