将 "yy" 输入到 char 变量时创建的无限循环应该只接受单个字符,例如 'y' 或 'n',"nn" 不会破坏代码

Infinite loop created when inputting "yy" into a char variable that should only take a single character such as 'y' or 'n', "nn" does not break code

cont 函数中的代码询问用户是否想再次玩我的游戏。

代码在接收到正确的字符输入时工作,例如 'y''n' 以及它们的相应的大写字母变体,如果 'a'[=65= 等无效输入,else 块将正常工作以循环函数] 已输入。

但是在测试 运行 期间,'yy' 的输入破坏了导致程序无限循环的代码,运行ning 不会只有这个 cont 函数,但我的 game 函数也是如此。

choice 存储为 char 变量。我想知道为什么在输入 'yy''yes'[= 等多字符输入时,代码甚至会继续 运行 47=]。有趣的是 'nn'、'ny' 和以 'n' 开头的多字符输入的其他变体不会导致任何问题并正确地导致 else if 按预期阻止 运行ning。打印出“感谢参与”。然后结束程序。

声明为 char 的变量可以接受大于 1 个字符的输入吗?它只取第一个值吗?如果是这样,为什么 'yy' 会导致循环,而不是程序 运行ning 通过接受值 'y' 还是 'Y'?我如何更改我的程序,以便 'yy' 的输入不再导致问题,没有针对输入的特定行,例如 'yy''yes'.

#include <iostream>
#include <string> // needed to use strings
#include <cstdlib> // needed to use random numbers
#include <ctime>

using namespace std;

// declaring functions
void cont();
void game();
void diceRoll();

// variable declaration
  string playerName;
  int balance; // stores player's balance
  int bettingAmount; // amount being bet, input by player
  int guess; // users input for guess
  int dice; // stores the random number
  char choice; 

// main functions
int main()
{
  srand(time(0)); // seeds the random number, generates random number
  cout << "\n\t\t-=-=-= Dice Roll Game =-=-=-\n";
  cout << "\n\nWhat's your name?\n";
  getline(cin, playerName);
  cout << "\nEnter your starting balance to play with : $";
  cin >> balance;

  game();
  cont();
}

// function declaration
void cont()
{
  cin >> choice;
  
  if(choice == 'Y' || choice == 'y')
  {
    cout << "\n\n";
    game();
  }
  else if (choice == 'N' || choice == 'n')
  {
    cout << "\n\nThanks for playing.";
  }
  else
  {
    cout << "\n\nInvalid input, please type 'y' or 'n'";
    cont(); // calls itself (recursive function!!!)
  }
}

void game()
{
  do
  {
    cout << "\nYour current balance is $ " << balance << "\n";
    cout << "Hey, " << playerName << ", enter amount to bet : $";
    cin >> bettingAmount;
    if(bettingAmount > balance)
      cout << "\nBetting balance can't be more than current balance!\n" << "\nRe-enter bet\n";
  } while(bettingAmount > balance);

  // Get player's numbers
  do 
  {
    cout << "\nA dice will be rolled, guess the side facing up, any number between 1 and 6 : \n";
    cin >> guess;
    if(guess <= 0 || guess > 6 )
    {
      cout << "\nYour guess should be between 1 and 6\n" << "Re-enter guess:\n";
    }
  } while(guess <= 0 || guess > 6); 

  dice = rand() % 6+1;
  diceRoll();

  if (dice == guess)
  {
    cout << "\n\nYou guessed correctly! You won $" << (bettingAmount * 6);
    balance = balance + (bettingAmount * 6);
  }
  else
  {
    cout << "\n\nYou guessed wrong. You lost $" << bettingAmount << "\n";
    balance = balance - bettingAmount;
  }
  cout << "\n" << playerName << ", you now have a balance of $" << balance << "\n";
  if (balance == 0)
  {
    cout << "You're out of money, game over";
  }
  cout << "\nDo you want to play again? type y or n : \n";
  cont();
}

void diceRoll()
{
  cout << "The winning number is " << dice << "\n";
}

Does it only take the first value?

是的,>> 格式化提取运算符,当为单个 char 值调用时,将读取第一个非空白字符,然后停止。之后的所有内容都未读。

why does 'yy' cause a loop

因为第一个“y”被读取,原因如上所述。第二个“y”仍未读。

这是一个非常常见的错误,也是对 >> 的误解。它 而不是 读取整行键入的输入。在跳过它前面的任何空格后,它只读取一个 value

您的程序会停止,直到输入了整行输入,然后是 Enter,但这不是 >> 读取的内容。它只读取它被要求读取的内容,而输入的所有其他内容都不会被读取。

于是程序继续执行,直到执行到这部分:

cin >> bettingAmount;

此时输入中的下一个未读字符是 y>>格式的提取运算符,对于int这样的值bettingAmount需要数值输入(跟随可选的空格)。但是下一个字符不是数字。是字符 y.

这导致格式化的 >> 提取运算符失败。 bettingAmount 中没有任何内容被读入。它完全没有被 >> 运算符改变。因为它是在全局范围内声明的,所以它是零初始化的。所以它仍然是 0.

除了 >> 提取运算符失败之外,作为失败的一部分,它将输入流设置为失败状态。当输入流处于失败状态时,所有后续输入操作都会自动失败而不做任何事情。这就是为什么您的程序会陷入无限循环。

虽然有一种方法可以将输入流从失败状态中清除,但这是一种笨拙的方法。干净的解决方案是修复读取输入的代码。

如果您的目的是停止程序并输入一些内容,然后输入 Enter,那么这就是 std::getline 的用途。显示的程序使用它来读取一些初始输入。

阻力最小的路径是简单地使用std::getline读取所有输入。不是使用 >> 读取单个字符,而是使用 std::getline 读取输入的下一行,进入 std::string,然后检查字符串的第一个字符并查看它是什么。问题已解决。

cin >> bettingAmount;

你想在这里做同样的事情。否则你会 运行 遇到同样的问题:输入错误会导致输入操作失败,令人头疼。

你为什么需要这种头痛?只需使用 std::getline 将文本读入 std::string,从中构造一个 std::istringstream,然后在 std::istringstream 上使用 >>,并检查其 return 值来判断是否失败。这是检查无效输入的简单方法,如果在此输入的不是数字输入,您可以完全自由地处理错误输入。