简体   繁体   English

将“yy”输入到只应采用单个字符(例如“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

The code in the cont function asks the user if they want to play my game again. cont function 中的代码询问用户是否想再次玩我的游戏。

The code works when receiving proper character inputs such as 'y' or 'n' as well as their respective capital letter variants, and the else block works properly to loop the function if an invalid input such as 'a' or 'c' is entered.该代码在接收到正确的字符输入(例如'y''n'以及它们各自的else字母变体时)有效,并且如果无效输入(例如'a''c'是进入。

However during a test run, an input of 'yy' breaks the code causing the program to infinitely loop, running not only this cont function but my game function as well.然而,在测试运行期间,输入“yy”会破坏代码,导致程序无限循环,不仅运行此cont function,而且还运行我的game function。

choice is stored as a char variable.选择存储为char变量。 I am wondering why the code even continues to run upon inputting multi-character inputs such as 'yy' or 'yes' .我想知道为什么代码甚至在输入多字符输入(例如'yy''yes' )时继续运行。 What's interesting is 'nn', 'ny' and other variations of multi-character inputs that begin with 'n' causes no issues and properly results in the else if block running as intended.有趣的是'nn'、'ny'和以 'n' 开头的多字符输入的其他变体不会导致任何问题,并且正确地导致else if块按预期运行。 Which prints "Thanks for playing."上面写着“感谢您的参与”。 then ends the program.然后结束程序。

Can variables declared as char accept inputs greater than 1 character?声明为char的变量可以接受大于 1 个字符的输入吗? Does it only take the first value?它只取第一个值吗? And if so why does 'yy' cause a loop rather than the program running as intended by accepting a value of 'y' or 'Y' ?如果是这样,为什么'yy'会导致循环,而不是通过接受'y''Y'的值来按预期运行程序? How can I change my program so that an input of 'yy' no longer causes issues, without specific lines targeting inputs such as 'yy' or 'yes' .如何更改我的程序,以使输入'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?它只取第一个值吗?

Yes, the >> formatted extraction operator, when called for a single char value, will read the first non-whitespace character, and stop.是的,当为单个char值调用>>格式的提取运算符时,将读取第一个非空白字符并停止。 Everything after it remains unread.之后的所有内容都未读。

why does 'yy' cause a loop为什么'yy'会导致循环

Because the first "y" gets read, for the reasons explained above.因为第一个“y”被读取,原因如上所述。 The second "y" remains unread.第二个“y”仍然未读。

This is a very common mistake and a misconception about what >> does.这是一个非常常见的错误,也是对>>做什么的误解。 It does not read an entire line of typed input.不会读取整行键入的输入。 It only reads a single value after skipping any whitespace that precedes it.它只在跳过它之前的任何空格后读取单个

Your program stops until an entire line of input gets typed, followed by Enter , but that's not what >> reads.您的程序会停止,直到输入一整行输入,然后Enter ,但这不是>>读取的内容。 It only reads what it's asked to read, and everything else that gets typed in remains unread.它只读取它被要求阅读的内容,而输入的所有其他内容都保持未读状态。

So the program continues to execute, until it reaches this part:于是程序继续执行,直到到达这部分:

cin >> bettingAmount;

At this point the next unread character in the input is y .此时输入中的下一个未读字符是y The >> formatted extraction operator, for an int value like this bettingAmount , requires numerical input (following optional whitespace). >>格式化的提取运算符,对于像这样bettingAmountint值,需要数字输入(在可选空格之后)。 But the next character is not numerical.但下一个字符不是数字。 It's the character y .这是字符y

This results in the formatted >> extraction operator failing.这会导致格式化的>>提取运算符失败。 Nothing gets read into bettingAmount . bettingAmount没有任何内容被读入。 It remains completely unaltered by the >> operator. >>运算符保持完全不变。 Because it is declared in global scope it was zero-initialized.因为它是在全局 scope 中声明的,所以它是零初始化的。 So it remains 0.所以它仍然是0。

In addition to the >> extraction operator failing, as part of it failing it sets the input stream to a failed state.除了>>提取运算符失败之外,作为失败的一部分,它会将输入 stream 设置为失败的 state。 When an input stream is in a failed state all subsequent input operation automatically fail without doing anything.当输入 stream 处于失败 state 中时,所有后续输入操作都会自动失败而无需执行任何操作。 And that's why your program ends up in an infinite loop.这就是为什么您的程序会陷入无限循环的原因。

Although there is a way to clear the input stream from its failed state this is a clumsy approach.尽管有一种方法可以从失败的 state 中清除输入 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ,但这是一种笨拙的方法。 The clean solution is to fix the code that reads input.干净的解决方案是修复读取输入的代码。

If your intent is to stop the program and enter something followed by Enter then that's what std::getline is for.如果您的意图是停止程序并在Enter后输入一些内容,那么这就是std::getline的用途。 The shown program uses it to read some of its initial input.显示的程序使用它来读取它的一些初始输入。

The path of least resistance is to simply use std::getline to read all input.阻力最小的路径是简单地使用std::getline来读取所有输入。 Instead of using >> to read a single character use std::getline to read the next line of typed in input, into a std::string , then check the the string's first character and see what it is.不要使用>>读取单个字符,而是使用std::getline将输入的下一行读取到std::string中,然后检查字符串的第一个字符并查看它是什么。 Problem solved.问题解决了。

cin >> bettingAmount;

And you want to do the same thing here.你想在这里做同样的事情。 Otherwise you'll just run into the same problem: mistyped input will result in a failed input operation, and a major headache.否则你只会遇到同样的问题:输入错误会导致输入操作失败,并且非常头疼。

Why do you need this headache?为什么需要这个头痛? Just use std::getline to read text into a std::string , construct a std::istringstream from it, then use >> on the std::istringstream , and check its return value to determine whether it failed, or not.只需使用std::getline将文本读入std::string ,从中构造一个std::istringstream ,然后在std::istringstream上使用>> ,并检查其返回值以确定它是否失败。 That's a simple way to check for invalid input, and if something other than numeric input was typed in here, you have complete freedom on how to handle bad typed in input.这是检查无效输入的一种简单方法,如果在此处输入了数字输入以外的内容,您可以完全自由地处理错误输入的输入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM