cin.getline not executing c++

cin.getline not executing c++

本文关键字:c++ executing not getline cin      更新时间:2023-10-16

出于某种奇怪的原因,当我把它放在这个 else if 块中时,我的输入行cin.getline(oneLine, 80);被完全忽略了。 我不明白为什么,因为当我将其移动到程序中的其他地方时,它可以工作。

     else if (choice == "user-id")
     {   
        cout << endl << "Enter a full name e.g. John Smith ";
        char oneLine[80];
        cin.getline(oneLine, 80);
        cout << oneLine;                        
     }

这是我代码的其余部分。 我是C++新手,所以我确信我的很多约定充其量可能是有问题的。

int main( )
{
    while (true)
        {
        int pause;
        string choice = "proceed";
        string nameGiven;
        string userIdGiven;
        string result;
        using namespace std ;
        while ((choice != "name") && (choice != "user-id"))
        {   
            cout << "Would you like to search for a name or user-id? ";
            cin >> choice;
            if ((choice != "name") && (choice != "user-id"))
               cout <<"Please enter a valid choice (name or user-id)" << endl;
        }
        if (choice == "name") 
        {
            string dataType = "int";
            while (true)
            {    
                cout << endl << "Enter a valid user id (4 digit maximum) ";
                cin >> userIdGiven;
                if (valid(userIdGiven))
                   break;
                else
                    cout << endl << "Not a valid number. " << endl;
                   continue;
             }
             result = findData(userIdGiven, dataType);
             cout << "name: " << result;
         }
         else if (choice == "user-id")
         {   
            cout << endl << "Enter a full name e.g. John Smith ";
            char oneLine[80];
            std::getline(oneLine, 80);
            cout << oneLine;                       
         }
        string ans;
        cout << endl << "Would you like to play again? (yes/no) " << endl;
        cin >> ans;
        if ( (ans == "yes") || (ans == "Yes") || (ans == "Y") || (ans == "y") )
             continue;
          else
              break;
        cin >> pause;
     } 
return 0;
}

您的std::cin对象在之前的输入操作中处于错误状态(std::cin.good() == false(。例如,您可能尝试读取一个数字,但输入缓冲区中只有母数字字符。

在继续使用 std::istream 之前,请始终检查输入是否成功。

注意: 不要使用与char*一起操作的旧输入函数,因为它们比在std::string上运行的新输入函数更复杂且使用起来更不安全。在您的情况下,请使用 std::getline(std::istream&, std::string&, char = 'n') .

twsaef的评论基本上是正确的......您正在将字符串流式传输到 Choice,这会消耗字符,直到但不包括下一个空格字符 - 您可能正在键入换行符来终止输入,因此它保留在缓冲区中。然后你使用 getline 看到该换行符并读取一个空字符串。

最简单的解决方案是调用getline()来读取初始字符串,然后检查选择是"name"还是"user-id"。 更好的是 - 编写一个"trim"函数来在比较之前从行中删除空格(boost 字符串库已经有这个(。 否则,您可以使用读取和忽略std::cin中的字符,直到得到""。 或者甚至读取一行然后放入字符串流并从那里读取字符串...... 很多选择。

并且,请检查您的流状态! 尝试使用:

if (std::cin >> x)
    // x was parsed from stream... use it
else
    // print an error so you know where things failed!

FWIW,在看到更新之前,我猜到了问题是什么(这很常见(,并对其他猜测笑了笑(尽管即使他们错过了 OP 的问题,他们也提出了非常好的观点(。

代码行工作正常,并且如广告所示。它不会碰巧按照您想要的方式工作。

当您从 std::cin 读取时,不会暂停程序并等待输入。导致暂停的原因是缺少足够的输入数据用于读取操作。

输入一次一行地馈送到程序。请记住,控制台窗口也是一个程序。它负责将用户的按键转换为文本字符(实际上是字节(,处理诸如退格键之类的事情,并将其全部收集成行。

假设你读了一篇带有operator>> int,然后用getline阅读了一行。在用户点击 Return 键之前,程序不会看到int,因为这会触发控制台向程序提供一行输入。

operator>>将跳过前导空格,读取整数,并保留尾随空格。换行符为空格。输入中有一个换行符(显然在行尾(。

getline()不会跳过任何前导空格,并一直读到下一个换行符。下一个字符恰好是换行符,所以getline()愉快地阅读一个空行,程序继续。

那么如何解决这个问题呢?如果您正在读取来自cin的所有输入,则有可能您希望程序在每次进行读取操作时暂停。做到这一点的方法是确保在这一点上永远不会有任何可用数据,而做到这一点的方法是每次阅读某些内容时都读取所有可用数据 - 即整行。

因此,请始终阅读cin中的一整行。如 wilx 所述,请使用免费函数std::getline。不要使用流的.getline成员函数。使用 std::string 表示文本字符串。这就是它的目的。它会让你的生活更轻松。这也意味着,如果你期待一个整数并且用户输入"76长号",你可以摆脱"长号"数据(并且可以决定你是想把它扔掉,还是对用户大喊大叫,让他重新输入一个数字,没有任何有趣的评论(。

但那又如何?你只有一个字符串,你可能想要一个 int。幸运的是,有一个简单的解决方案。我们可以将字符串视为流数据源,使用标准库类 std::stringstream .我们只是从字符串构造一个字符串流,然后像std::cin一样使用它 - 即我们可以用 operator>> 从中读取,检查流状态以查看读取是否成功,等等。

正如 sbi 所指出的,始终检查读取是否成功!如果您尝试读取int并且流包含诸如"嗨妈妈"之类的文本,那么 (a( int变量不会被更改(因此,如果它未初始化,它仍然未初始化,这是一种非常危险的状态(,以及 (b( 流将进入"失败"状态,并且在您清除它之前不会再读取, (c(即使你清除了它,数据仍然会在那里,如果你不小心,这可能会触发无限循环。

幸运的是,有了 单独的stringstream ,我们避免了各种并发症。如果读取失败,那么所有这些事情都会发生在stringstream对象上 - 而不是std::cin .getline操作将始终在std::cin上成功,除非用户明确指示文件结尾(Linux 上的 control-D 字符或 Windows 上的 control-Z(。我们可以轻松检查stringstream是否处于失败状态,循环并创建另一个 - 旧的将自动清理。

我们甚至可以创建一个辅助函数,例如:

template <typename T>
// Attempt to read into to_read, and return whether successful.
bool read_primitive_from_input(std::istream& input, T& to_read) {
    std::string line;
    std::getline(std::cin, line);
    std::istringstream iss(line);
    return iss >> to_read;
}

std::stringstream由标准库标头<sstream>提供。 当然,std::string来自<string>