C++中如何验证Bulls & Cows游戏的4位整数用户输入?
Hey there! I see the issue with your input validation causing an infinite loop—let's break down why it's happening and fix it step by step.
The Root Cause
When a user enters something that isn't an integer (like a string or decimal), cin >> guess fails. This leaves the invalid input stuck in the input buffer, and since you only clear the error state with cin.clear() but don't remove the garbage data from the buffer, the next loop iteration will try to read the same invalid input again. That's why you're stuck in a loop of error messages.
The Fixes
Here are the key changes you need to make:
- Clear the input buffer after resetting error state: After
cin.clear(), you need to flush all invalid characters from the buffer until a newline is hit, so the next input attempt starts fresh. - Reorder validation checks: First confirm
cinsuccessfully read an integer before checking the numeric range—if the read fails, the value ofguessis undefined, so range checks don't make sense. - Add the
<limits>header: Required to usenumeric_limitsfor clearing the buffer completely.
Modified Code
Here's your updated code with fixes marked:
#include <iostream> #include <vector> #include <algorithm> #include <cstdlib> #include <limits> // Add this header for buffer clearing using namespace std; vector<int> getDigits(int modelValue) { vector<int> vectorValue; int extractedDigit = 0; int modulant = 10000; int divisor = 1000; for (int i = 0; i < 4; i++) { extractedDigit = (modelValue % modulant) / divisor; vectorValue.push_back(extractedDigit); modulant /= 10; divisor /= 10; } return vectorValue; } int main() { for (;;) { int model = rand() % 9000 + 1000; int guess = 0; // 0000 is equivalent to 0 in C++, so simplified here int bulls = 0; int cows = 0; int counter = 1; cout << "This is the random 4-digit integer: " << model << endl; cout << "Enter a value to guess: "; // First check if input was successfully read as integer if (cin >> guess) { // Then validate it's a 4-digit range (including 0000 = 0) if (guess >= 0 && guess <= 9999) { vector<int> modelVector = getDigits(model); vector<int> guessVector = getDigits(guess); for (int i = 0; i < 4; i++) { if (find(modelVector.begin(), modelVector.end(), guessVector[i]) != modelVector.end()) { if (modelVector[i] == guessVector[i]) { bulls += 1; } else { cows += 1; } } } cout << "There are " << bulls << " bulls and " << cows << " cows" << endl; } else { cout << "Please enter a valid 4-digit integer between 0000 and 9999" << endl; } } else { cout << "Please enter a valid 4-digit integer between 0000 and 9999" << endl; cin.clear(); // Reset cin's error state // Flush all invalid characters from buffer until newline cin.ignore(numeric_limits<streamsize>::max(), '\n'); } } return 0; }
Key Explanations
cin.ignore(numeric_limits<streamsize>::max(), '\n'): This line tells cin to ignore every character in the buffer until it hits a newline, ensuring no leftover invalid data messes up the next input attempt.- Validation order: By checking
cin >> guessfirst, we avoid evaluating an undefinedguessvalue when input fails. - Range adjustment: Updated to
0 <= guess <= 9999to match your error message mentioning 0000 (since 0000 is just the integer 0 in C++).
Now when a user enters invalid input, the buffer gets cleared, and the next iteration will wait for fresh input instead of looping infinitely.
内容的提问来源于stack exchange,提问作者mchd

