cin.getline 不执行 c++

发布于 2024-11-26 06:03:45 字数 2208 浏览 0 评论 0原文

由于某些奇怪的原因,当我将输入行 cin.getline(oneLine, 80); 放入 else if 块中时,它被完全忽略。我不明白为什么,因为当我将它移到程序中的其他位置时,它就可以工作。

     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;
}

For some weird reason my input line cin.getline(oneLine, 80); is completely ignored when I put it in this else if block. I can't understand why because when I move it somewhere else in the program, it works.

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

Here's the rest of my code. I'm new to C++ so I'm sure a lot of my conventions may be questionable at best.

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

香橙ぽ 2024-12-03 06:03:45

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

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

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

Your std::cin object is in a bad state (std::cin.good() == false) from a previous input operation. For example, you might have tried to read a number, but there were only nun-numeric characters in the input buffer.

Always check for input success before continuing using a std::istream.

Note: Don't use the old input functions operating with char*, as they are more complicated and less safe to use than the new ones operating on std::string. In your case, use std::getline(std::istream&, std::string&, char = '\n').

世俗缘 2024-12-03 06:03:45

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

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

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

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

twsaef's comment's substantively correct... you're streaming a string into choice, which consumes the characters up until but excluding the next whitespace character - you're probably typing a newline to terminate your input, so it's left in the buffer. Then you use getline which sees that newline and reads an empty string.

Easiest solution is to call getline() to read the initial string too, then check if choice is "name\n" or "user-id\n". Better - write a "trim" function to remove the whitespace from the line before comparison (boost string library has this already). Otherwise, you could use read and ignore characters from std::cin until you get a '\n'. Or even read a line then put in into a stringstream and read a string from there.... Lots of choices.

And, please check your stream state! Try to use:

if (std::cin >> x)
    // x was parsed from stream... use it
else
    // print an error so you know where things failed!
黑白记忆 2024-12-03 06:03:45

FWIW,在看到更新之前我就猜到了问题是什么(这是愚蠢的普遍现象),并对其他猜测咯咯地笑(尽管他们提出了很好的观点,即使他们错过了OP的问题)。

该代码行工作正常且如广告所示。它恰好没有按照您希望的方式工作。

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

输入一次一行地输入到您的程序中。请记住,控制台窗口也是一个程序。它负责将用户的按键转换为文本字符(实际上是字节),处理退格键等内容,并将其全部收集到行中。

假设您使用 operator>> 读取 int,然后使用 getline 读取一行。在用户按下 Return 键之前,程序不会看到 int,因为这会触发控制台向程序提供一行输入。

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

getline()不跳过任何前导空格,并读取直到下一个换行符。下一个字符恰好是换行符,因此 getline() 愉快地读取一个空行,然后程序继续执行。

那么如何解决这个问题呢?如果您正在从 cin 读取所有输入,则您可能希望程序在每次执行读取操作时暂停。做到这一点的方法是确保此时永远不存在任何可用数据,而做到这一点的方法是在每次读取内容时读取所有可用的内容(即整行)。

因此,请始终从 cin 读取整行。 正如 wilx 所指出的,请使用免费函数 std::getline 来实现此目的。不要使用流的 .getline 成员函数。使用 std::string 表示文本字符串。这就是它的用途。这将使您的生活变得更加轻松。这也意味着,如果您期望一个整数并且用户输入“76 trombones”,您将摆脱“trombones”数据(并且可以决定 无论你是想把它扔掉,还是对用户大喊大叫,让他重新输入一个数字,而没有任何有趣的评论)。

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

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

幸运的是,通过单独的stringstream,我们避免了各种复杂情况。如果读取失败,那么所有这些事情都会发生在 stringstream 对象上,而不是发生在 std::cin 上。 getline 操作在 std::cin 上总是会成功,除非用户明确指示文件结束符(Linux 上的 control-D 字符,或 Linux 上的 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 由标准库头 提供。当然,std::string 来自

FWIW, I guessed what the problem would be (it's stupidly common) before seeing the update, and chuckled to myself at the other guesses (although they make very good points even if they missed the OP's problem).

The line of code is working correctly and as advertised. It doesn't happen to be working the way you want it to.

When you read from std::cin, that does not pause the program and wait for input. What causes the pause is the lack of sufficient input data for the read operation.

Input is fed to your program a line at a time. Remember, the console window is a program, too. It is responsible for translating the user's key-presses into text characters (bytes, really), handling things like the backspace key, and gathering it all up into lines.

So say you read an int with operator>>, and then read a line with getline. The program will not see an int until the user hits the Return key, because that triggers the console to feed a line of input to your program.

operator>> will skip leading whitespace, read the integer, and leave trailing whitespace alone. Newline characters are whitespace. There is a newline character in the input (at the end of the line, obviously).

getline() will not skip any leading whitespace, and read until the next newline. The very next character happens to be a newline, so getline() happily reads an empty line and the program proceeds with that.

So how do you fix that? Chances are, if you're reading all your input from cin, that you want the program to pause every time you come to a reading operation. The way to do that is to ensure that there is never any available data at that point, and the way to do that is to read everything that's available - i.e., the whole line - every time that you read something.

So, always read a full line from cin. As noted by wilx, please use the free function std::getline for this. Do not use the .getline member function of the stream. Use std::string to represent strings of text. That's what it's there for. It will make your life much, much easier. That also means that if you're expecting an integer and the user types "76 trombones", you get rid of the "trombones" data (and can decide whether you want to just throw it away, or yell at the user and make him re-enter a number without any funny commentary).

But then what? You just have a string, where you may have wanted an int. Fortunately, there is a simple solution for that. We can treat the string as a source of stream data, using the standard library class std::stringstream. We just construct a stringstream from the string, and then use it just like std::cin - i.e. we can read from it with operator>>, check the stream state to see if reading was successful, etc.

As noted by sbi, always check whether reading succeeded! If you try to read an int and the stream contains text like "hi mom", then (a) the int variable will not be altered (so if it was uninitialized it is still uninitialized, a very dangerous state to be in), and (b) the stream will go into a "failed" state and will not read any more until you clear it, and (c) even if you clear it, the data will still be there, which can trigger an infinite loop if you're not careful.

Fortunately, with the separate stringstream, we avoid all kinds of complications. If reading fails, then all those things happen to the stringstream object - not to std::cin. The getline operation will always succeed on std::cin unless perhaps the user explicitly indicates an end-of-file (control-D character on Linux, or control-Z on Windows). We can easily check if the stringstream is in the failed state, loop and just create another one - the old one will automatically get cleaned up.

We can even make a helper function like:

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 is provided by the standard library header <sstream>. std::string comes from <string>, of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文