首页 文章

在do-while循环中输入验证时出现C错误

提问于
浏览
1

我正在为一个学校项目创建一个非常简单的猜数游戏,并且在重复主菜单时遇到问题 . 我使用 do-while loop 创建了它,我遇到的问题是菜单选择变量是 int ,所以当我(或用户)从菜单中选择 }while(condition) 时,偶然输入 non-int 输入主循环无法捕获它,程序无限重复 . 相反,如果您在菜单选择中输入 invalid int ,则程序捕获它会显示"invalid input"消息,然后重复主菜单 .

它保存为.cpp并使用 g++ -ansi -pedantic -Wall -Werror 在linux中进行编译 . 教师禁止在条件语句中进行硬编码,因此全局常量 .

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
const int PLAY = 1, HIGH_SCORE = 2, EXIT = 3;
const char YES = 'y', NO = 'n';

int main()
{
// Randomly generated value
  int randomNumber;
// User input
  int userGuess, menuChoice;
  char repeat;
// Calculated value
  int numberOfGuesses;
// Place-holder values (to be replaced by calculated values)
  int score1 = 1000, score2 = 2000, score3 = 3000;

  cout << endl << endl;
  cout << "Greetings! This is a number guessing game where I think of" << endl
       << "a whole number between one and ten and you try to guess it!" << endl
       << "You can guess as many times as you like, so don't be afraid" << endl
       << "to use trial and error, but your score is based on the " << endl
       << "number of guesses you make (the lower the better) so don't " << endl
       << "guess too haphazardly. Remember, only guess whole numbers!" << endl
       << endl;

  do
  {
    cout << endl << "Main menu." << endl
         << "1. Play game" << endl
         << "2. Display high scores" << endl
         << "3. Exit game" << endl
         << "Please select an option: ";
    cin >> menuChoice;

    if (cin.fail()){     
      cout << "Please enter a valid choice" << endl;
      continue;
    } 
    cin.ignore();

    switch(menuChoice)
    {
      case PLAY:
      do
      {
        unsigned seed = time(0);
        srand(seed);
        randomNumber = 1 + rand() % 10;

        cout << endl << "Press enter when you're ready to begin!";
        cin.ignore();
        cout << "Ok I thought of one!" << endl << endl;

        numberOfGuesses = 0;

        do
        {
          numberOfGuesses++;

          cout << "Enter your guess: ";
          cin >> userGuess;
          cin.ignore();

// Check user's guess
          if (userGuess == randomNumber)
            cout << "Correct! That was impressive!" << endl << endl;
          else if (userGuess < randomNumber)
            cout << "Not quite, you guessed low." << endl << endl;
          else if (userGuess > randomNumber)
            cout << "Not quite, you guessed high." << endl << endl;
        }while (userGuess != randomNumber);

        cout << "Your score for this game was " << numberOfGuesses << endl;

// Determine if a high score was beaten
        if (numberOfGuesses <= score1)
        {
          score3 = score2;
          score2 = score1;
          score1 = numberOfGuesses;
          cout << "That's a new all time high score!" << endl;
        }
        else if (numberOfGuesses <= score2)
        {
          score3 = score2;
          score2 = numberOfGuesses;
          cout << "That's a new high score!" << endl;
        }
        else if (numberOfGuesses <= score3)
        {
          score3 = numberOfGuesses;
          cout << "That's a new high score!" << endl;
        }
        else
        {
          cout << endl; 
        }

        cout << "Would you like to play again? y/n: ";
        cin.get(repeat);
        cin.ignore();

        while (tolower(repeat) != YES && tolower(repeat) != NO)
        {
          cout << endl;
          cout << "Sorry, that is an invalid choice." << endl
               << "Please enter 'y' for yes or 'n' for no: ";
          cin.get(repeat);
          cin.ignore();
        }
      }while (tolower(repeat) == YES); 
        break;

      case HIGH_SCORE:
      cout << endl << "High Score 1: " << score1 << endl
           << "High Score 2: " << score2 << endl
           << "High Score 3: " << score3 << endl << endl;
      cout << "Press enter to continue. ";
      cin.ignore();
        break;

      case EXIT: 
      cout << endl << "Thanks for playing, I'll see you next time!" << endl << endl;
        break;

      default:
      cout << endl << "That is an invalid selection, please enter '1', '2' or '3'"
           << endl;
        break;
    } 
  }while (menuChoice != EXIT);

  return 0;
}

代码就当前答案编辑 .

如果您需要更多信息,请告知我们,谢谢您的先进!

2 回答

  • 0

    像这样使用 cin.fail() (而不仅仅是 cin >> menuChoice; )(以this post为模型):

    cin >> menuChoice;
    if (cin.fail()) {
      cout << "Please enter a valid choice" << endl;
      cin.clear();
      cin.ignore();
      continue;
    }
    //Remove the cin.ignore() at this place!
    

    有关更多详细信息,请参阅this SO thread

  • 0

    使用do-while确保循环体至少运行一次 .

    通过使用do-while并在循环外提示用户,您假设用户想要玩一次可能不是这种情况的游戏 .

    更简洁的方法IMO将使用while循环 . 显示菜单 outside the loop 并在 end of the loop . 用户可以选择立即退出 .

    cout << "Greetings.....
     cout << menu
     // Get menuChoice input here.    
        while(menuChoice != EXIT){
            ...
    
             cout << menu //reprompt at end to continue or exit cleanly
             // Get menuChoice input here
        }
    

    输入验证是使用do-while的最佳时机

    do{
       if(!cin){
          cout << "Invalid input"
          cin.clear()
          cin.ignore(numeric_limits<streamsize>::max(), '\n');
       }
    }while(!(cin >> menuChoice)) // This gets console input. If fail, loop.
    
    • 使用 numeric_limits<streamsize>::max() 完全清除缓冲区 .

    • 使用 cin.clear() 重置 cin 上的失败标志,因此它不会始终为false .

    cin.fail() 很好 . 然而有些人会认为 !cin 更自然 .

相关问题