【问题标题】:why does cin works wheras cin.getline doesn't?为什么 cin 有效而 cin.getline 无效?
【发布时间】:2013-12-02 17:47:19
【问题描述】:

我的代码是

char buffer[10]={0};
cin>>buffer; //here i enter the contents as "12345678912345"
//Now i tried to enter 14 characters into a buffer of 10
cin>>buffer; //This works as it waits for input on the console
cout<<buffer;

char buffer[10]={0};
cin>>buffer;//same input as above "12345678912345"
cin.getline(buffer,10);//This doesn't wait for input on console and returns 
cout<<buffer;

为什么会这样?

感谢: 感谢大家的回答,他们很有帮助

【问题讨论】:

  • 您是否在问为什么在缓冲区溢出后会出现未定义的行为?那是因为缓冲区溢出会导致未定义的行为。
  • 但如果是 cin>> 它工作正常
  • 不,它没有;它写入超过缓冲区的末尾,破坏内存并导致未定义的行为。如果损坏的内存中碰巧没有什么重要的东西,它似乎对你有用;但原则上任何事情都可能发生。

标签: c++ cin getline


【解决方案1】:

您的代码-sn-ps 都没有“工作”,因为它们都溢出了第一行输入行中的缓冲区。这根本不是一件好事。

由于operator&gt;&gt;getline 之间的技术差异,第二种情况不会等待输入 - 它们对您输入的换行符的反应不同。读取第一个cin &gt;&gt; buffer 时,输入末尾的换行符留在输入流中(cin)。在您的第一种情况下,第二个 cin &gt;&gt; buffer 将跳过输入缓冲区中的换行符,然后等待更多输入。

在第二种情况下,由于getline 的工作原理,它接受剩余的换行符作为输入,并且缓冲区没有填充任何内容。

这是混合getlineoperator&gt;&gt; 进行输入时的常见问题。解决该特定问题的最佳解决方案是仅使用 operator &gt;&gt; 或仅使用 getline - 还有各种其他解决方案,但它们通常很难做到恰到好处。

【讨论】:

  • 那么这是否意味着在cin.getline缓冲区溢出后只会发生一次,下一次getline会等待输入?
  • 假设你没有溢出缓冲区,下一个 getline 应该可以工作。由于您正在溢出缓冲区,谁知道什么被覆盖以及发生了什么 - 这被称为未定义的行为,它确实意味着“可能会发生一些奇怪的事情”。例如,您是否检查过您的cin 流没有处于错误状态?
  • if (cin) cout &lt;&lt; "Error on cin\n"; 之类的东西会这样做。
【解决方案2】:

首先你有一个缓冲区溢出:当流变坏时停止读取char*,找到一个空间,或者如果width() 大于 0 则耗尽。你想使用

std::cin >> std::setw(10) >> buffer;

假设存在这种未定义的行为,使用格式化输入和未格式化输入进行第二次读取之间的区别在于格式化输入从跳过前导空格开始,而未格式化输入则不这样做。您的第一个输入在回车键产生的换行符之前停止。该换行符对于getline() 来说已经足够好了,但在使用&gt;&gt; 时会被跳过。

在格式化和未格式化 I/O 之间切换时,您通常希望使用例如 std::ws 操纵符跳过前导空格:

(std::cin >> std::ws). getline(buffer, 10);

您还应该考虑将std::stringstd::getline() 一起使用。

【讨论】:

    【解决方案3】:

    当你在控制台输入buffer的值时,返回值仍然存储在输入流中。

    因此终止字符'\n' 已经被getline() 从先前的读取操作中读取。这就是为什么这个函数不再等待用户输入的原因。

    尝试在cin &gt;&gt; 操作之前读取getline()

    另外,正如 Mike 所说,您应该小心不要导致缓冲区溢出。

    【讨论】:

    • 但即使我在那之后添加了一个while循环......它每次都会继续执行并且从不等待输入......
    • 您是否尝试过我建议的更改?
    • 我想知道这种行为的原因......所以我正在使用这个序列
    • @singh 看到这个。 cplusplus.com/reference/string/string/getline/?kw=getline 从链接中可以清楚地看出 getline 在 EOL 字符处终止。此 EOL 字符在您第二次输入之前由 getline() 读取,因为您在输入第一次输入时按 Enter。 cin 不读取此“输入”,但保留在输入缓冲区中。
    【解决方案4】:

    &gt;&gt; 运算符不使用任何空格,包括换行符。 getline 函数在看到换行符时返回。您的问题是 &gt;&gt; 语句留在缓冲区的换行符。您可以通过使用所有字符(包括换行符)来解决此问题,直到您在缓冲区中看到换行符。见ignore function

    char buffer[10]={0};
    cin>>buffer;
    cin.ignore('\n', 256);
    cin.getline(buffer,9); 
    cout<<buffer;
    return 0;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-09
      • 2011-07-05
      • 2012-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多