【问题标题】:Cin isn't waiting for inputCin 不等待输入
【发布时间】:2015-07-21 20:37:21
【问题描述】:

这是程序:

#include <iostream>
#include <string>
#include <stdlib.h>


using namespace std;

int main(){


string strKingdom = "";
bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
int gold;
int food;
int citizens;
int soldiers;



cout << endl <<"Name of kingdom: ";
cin >> strKingdom;
cout << endl << "were you conquered (true/false): ";
cin >> conquered_me;
cout << endl << "How many gold do you have?:";
cin>>gold;
cout << endl << "How many food do you have?:";
cin >> food;
cout << endl << "How many citizens do you have?:";
cin >> citizens;
cout << endl << "How many soldiers do you have?:";
cin >> soldiers;


return 0;
}

问题是,当我编译它时,程序只允许我插入前 2 个变量,然后它会显示其余的问题(编译后):

王国名称:史蒂夫

你被征服了吗(真/假):假

你有多少金币?: 你有多少食物?: 你有多少公民?: 你有多少士兵?:

【问题讨论】:

  • 您给出的确切输入是什么?我猜它正在读取您作为“6”值给出的“2”输入。 (您的王国名称中是否有空格?看看:cplusplus.com/reference/string/string/getline
  • 只是不要使用istream::operator&gt;&gt;。很难正确使用。要获取用户输入,请使用 std::getline() 并解析结果字符串。
  • 所以存储 std::string 是唯一有效的方法。接下来的数据类型,包括那个 bool,导致了你的失控行为。这是给你的线索。 :-)
  • just don't use istream::operator&gt;&gt;. 这是一个非常愚蠢的建议。新手应该首先学习如何使用标准流,因为它是一个非常基本的接口,基本上可以在任何地方使用。一旦你了解了它的工作原理,你就可以对是否使用它有意见。
  • @sbabbi 我没有建议他不学习标准流。 operator&gt;&gt; 界面非常微妙。当您可以使用 std::getline()也适用于标准 I/O 流...)时,为什么要让自己陷入危险之中?

标签: c++ cin


【解决方案1】:

bool 变量中输入字符串“true”不起作用。您应该输入10。你的“真实”不能被“消费”,所以它留在缓冲区中。接下来,您尝试读取int 值,因此“true”也不匹配。以此类推……直到程序结束。

我就是这样做的:

#include <string>
#include <iostream>

#include <errno.h>
#include <stdlib.h>

using namespace std;

void askForString(string aPrompt, string &aValue) {
    cout << aPrompt << " ";
    cin >> aValue;
}

void askForBool(string aPrompt, bool &aValue) {
    string tString;
    while (1) {
        cout << aPrompt << " ";
        cin >> tString;
        if (tString == "true") {
            aValue = true;
            break;
        } else if (tString == "false") {
            aValue = false;
            break;
        } else {
            cout << "Repeat, please?" << endl;
        }
    }
}

void askForInt(string aPrompt, int &aValue) {
    string tString;
    char *endptr;
    while (1) {
        cout << aPrompt << " ";
        cin >> tString;
        errno = 0;
        aValue = strtol(tString.c_str(), &endptr, 10);
        if (errno || tString.c_str() == endptr || (endptr != NULL && *endptr != 0)) {
            cout << "Repeat, please?" << endl;
        } else {
            break;
        }
    }
}

int main(void) {
    string strKingdom;
    bool conquered_me;
    int gold;
    int food;
    int citizens;
    int soldiers;

    askForString("Name of kingdom:", strKingdom);

    askForBool("were you conquered (true/false):", conquered_me);

    askForInt("How many gold do you have?:", gold);

    askForInt("How many food do you have?:", food);

    askForInt("How many citizens do you have?:", citizens);

    askForInt("How many soldiers do you have?:", soldiers);

    cout << "Kingdom: " << strKingdom << endl;
    cout << "Conquered: " << (conquered_me ? "true" : "false") << endl;
    cout << "Gold: " << gold << endl;
    cout << "Food: " << food << endl;
    cout << "Citizens: " << citizens << endl;
    cout << "Soldiers: " << soldiers << endl;

    return 0;
}

【讨论】:

  • 正确,但建议一个解决方案和一些演示该解决方案的示例代码将使这个答案有用。
  • @user4581301:特别为您改进了我的答案;)
【解决方案2】:

将它们全部转换为字符串,并根据需要进行转换。

【讨论】:

    【解决方案3】:

    出于某种原因(可能与旧代码兼容)iostreams 默认在 I/O 期间将 true 转换为 1false 转换为 0

    这只是默认设置 - 有一个名为 boolalpha 的操纵器会将流设置为使用 truefalse(或本地化等效项)。

    所以,代码如下:

    std::cout << 1 == 0;               // produces `0`
    std::cout << boolalpha << 1 == 0;  // produces `false`
    

    这也适用于输入,因此您可以将代码更改为以下内容:

    cin >> boolalpha >> conquered_me;
    

    ...它应该按预期工作(并且在:它应该接受falsetrue 的输入,并从它们产生falsetrue 的值,如果不是这样标准库中的错误)。

    【讨论】:

      【解决方案4】:

      您的所有读取命令都不会检查错误。所有这些都应该写成这样的:

      while (!(std::cin >> strKingdom)) {
          std::cerr << 'Bad input' << std::endl;
          std::cin.clear();  // clear the error
          std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // ignore the rest of the line
          // output the same prompt again?
      }
      

      为了使这更容易,您可能需要编写一个辅助函数:

      template<typename T> void get_input(const char *prompt, T &result) {
          std::cout << prompt << std::endl;
          while (!(std::cin >> result)) {
              std::cerr << 'Bad input' << std::endl;
              std::cin.clear();
              std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
              std::cout << prompt << std::endl; } }
      

      然后您可以专门为 bool 类型正确读取 true/false...

      【讨论】:

      • ...或者您可以使用boolalpha,因为流已经被设计为支持(有关详细信息,请参阅我的答案)。
      【解决方案5】:

      这一行:

      cin >> conquered_me;
      

      应该是这样的:

      cin >> boolalpha >> conquered_me;
      

      否则输入需要“0”或“1”。

      通过使用boolalpha,您的输入可以是“真”或“假”。

      【讨论】:

        【解决方案6】:

        您需要使用 std::getline 和 std::string 来读取各种值。 (然后您可以使用 atoi 之类的函数来解析它们。)这是您使用 std::getline 函数的代码示例。

        #include <iostream>
        #include <string>
        #include <cstdlib>
        
        int main(){
        
        
        std::string strKingdom = "";
        bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
        int gold;
        int food;
        int citizens;
        int soldiers;
        
        std::string tString = ""; // Used to read and subsequently parse the string.
        
        
        std::cout << std::endl <<"Name of kingdom: ";
        std::getline(std::cin,strKingdom);
        
        std::cout << std::endl << "were you conquered (true/false): ";
        std::getline(std::cin,tString);
        conquered_me = (tString == "true");
        
        std::cout << std::endl << "How many gold do you have?:";
        std::getline(std::cin,tString);
        gold = std::atoi(tString.c_str());
        
        std::cout << std::endl << "How many food do you have?:";
        std::getline(std::cin,tString);
        food = std::atoi(tString.c_str());
        
        std::cout << std::endl << "How many citizens do you have?:";
        std::getline(std::cin,tString);
        citizens = std::atoi(tString.c_str());
        
        std::cout << std::endl << "How many soldiers do you have?:";
        std::getline(std::cin,tString);
        soldiers = std::atoi(tString.c_str());
        
        
        return 0;
        }
        

        【讨论】:

        • 不,它没有。例如,conqured_me 的输入可能类似于“true”(带空格),它会被解释为 false。或者,如果您没有在 goldfood 中输入数字,则会出现未捕获的异常。
        • @sbabbi,实际上这更有趣。我们在其中包含 stdlib.h 和字符串以及 using namespace std,因此我们在确定要获得哪个 atoi 时遇到了一些有趣的混乱,旧的 C 或 C++11 的。
        • @user4581301 已修复。不错的收获。
        猜你喜欢
        • 2017-05-03
        • 2018-06-01
        • 2023-03-10
        • 2012-01-24
        • 2012-08-29
        • 1970-01-01
        • 2012-05-20
        • 2019-04-21
        • 2012-08-21
        相关资源
        最近更新 更多