在我看来,好像 std::getline 没有正确处理新行?

It seems to me as if std::getline doesn't handle new lines correctly?

使用下面的代码,我希望用户在终端中写一段文字,然后打印出该文字的最后一句话。也许我应该提到我 运行 在 Linux 桌面上。

#include <string>
#include <iostream> 

int main()
{
    std::string user_text{};

    while(std::getline(std::cin, user_text))
    {

    }

    std::cout << "Text: " << user_text << std::endl;

    return 0;
}

无论如何,如果我在 运行 程序之后,写例如:

Hi my name is

然后按'ctrl+d',输出确实是"Text: Hi my name is"

但是,如果我改为这样做:

Hi my name is 'press enter'

Name my is hi 'press enter'

然后按'ctrl+d'。输出将是 "Text: "。为什么是这样?当我按下 'ctrl+d' 时,getline 不应该停止吗?

提前致谢!

std::getline() 在尝试从流中读取之前擦除输出 std::string

在你的第二种情况下,前两次调用 std::getline() 已经读取了你输入的所有内容,当你按下 CTRL-D第三次调用,所以 std::getline() 没有任何输出到 std::string.

将最后一次成功读取的行保存到一个单独的变量中,例如:

std::string user_text, line;

while(std::getline(std::cin, line))
{
    user_text = line;
}

std::cout << "Text: " << user_text << std::endl;

Ctrl+D 导致进程的 read 从终端立即到 return。如果您在键入 Hi my name is 后按 Ctrl+D,该过程将读取:Hi my name isgetline 将找不到 \n 并将重新开始阅读。然后您再次按 Ctrl+D(您没有说,但我确定您说了)。这将中断 read,导致它变为 return 0,就好像终端已关闭一样。 getline 将 return 当前值:Hi my name is.

在第二种情况下,自从上次\n之后你没有输入任何内容,所以当你按Ctrl+D时,read直接returns 0和getline returns 为空字符串。

std::getline 正在按预期工作:它正在排队。如果你按下回车键,它会创建一个新的空行;如果您随后按 ctrl+d,您将终止 std::getline,即 returns 该(空)行的内容。

来自docs

getline reads characters from an input stream and places them into a string:

  1. Behaves as UnformattedInputFunction, except that input.gcount() is not affected. After constructing and checking the sentry object, performs the following:
    1. Calls str.erase()
    2. Extracts characters from input and appends them to str until one of the following occurs (checked in the order listed) a) end-of-file condition on input, in which case, getline sets eofbit. b) the next available input character is delim, as tested by Traits::eq(c, delim), in which case the delimiter character is extracted from input, but is not appended to str. c) str.max_size() characters have been stored, in which case getline sets failbit and returns.
    3. If no characters were extracted for whatever reason (not even the discarded delimiter), getline sets failbit and returns.
  2. Same as getline(input, str, input.widen('\n')), that is, the default delimiter is the endline character.