std::getline 在 for 循环中不起作用
Posted
技术标签:
【中文标题】std::getline 在 for 循环中不起作用【英文标题】:std::getline does not work inside a for-loop 【发布时间】:2011-01-03 15:19:50 【问题描述】:我正在尝试在一个字符串变量中收集用户的输入,该变量在指定的时间内接受空格。
由于通常的 cin >> str
不接受空格,所以我会使用 std::getline from
这是我的代码:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
int n;
cin >> n;
for(int i = 0; i < n; i++)
string local;
getline(cin, local); // This simply does not work. Just skipped without a reason.
//............................
//............................
return 0;
有什么想法吗?
【问题讨论】:
很少有事情会无缘无故地失败。 在 for 循环之前尝试以下操作: std::cout 是的。 n 被正确读取。我为 n 输入了 2,它打印出“n: 2” 我想我已经解决了你的问题。但是关于您的调试,您确实尝试了 2 以外的其他值,对吗?进入循环,它只是“跳过”第一个条目。 【参考方案1】:如果您输出存储在local
中的内容(顺便说一句,这是一个糟糕的变量名:P),您就会明白为什么会失败:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
int n;
cin >> n;
for(int i = 0; i < n; i++)
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
//............................
return 0;
您将看到它在输入您的号码后立即在>
之后打印一个换行符。然后继续输入其余部分。
这是因为getline
为您提供了输入号码后剩下的空行。 (它会读取数字,但显然不会删除 \n
,因此您会留下一个空白行。)您需要先删除任何剩余的空格:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
int n;
cin >> n;
cin >> ws; // stream out any whitespace
for(int i = 0; i < n; i++)
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
//............................
return 0;
这按预期工作。
题外话,也许它只是为了手头的 sn-p,但如果你没有using namespace std;
,代码往往更可读。它违背了命名空间的目的。不过,我怀疑这只是为了在这里发帖。
【讨论】:
我自己倾向于明确使用 std:: 命名空间前缀,但是在 cpp(不是 h)文件中使用 using 声明并没有错。 或许在这样一个简单的例子中。不过,在命名空间std
中有很多 的东西。函数级是我将使用using
指令的最全局性。【参考方案2】:
声明一个字符以在您输入数字后进入马车返回。char ws;int n;cin>>n;ws=cin.get();
这样就可以解决问题了。
使用
cin>>ws
而不是ws=cin.get()
,将使字符串的第一个字符位于变量ws
中,而不是仅仅清除'\n'
。
【讨论】:
【参考方案3】:这很简单。 你只需要在循环的末尾放一个 cin.get() 。
【讨论】:
【参考方案4】:你按回车了吗?如果没有得到线将不会返回任何内容,因为它正在等待行尾......
【讨论】:
【参考方案5】:我的猜测是你没有正确阅读n
,所以它转换为零。由于 0 不小于 0,因此循环永远不会执行。
我会添加一些工具:
int n;
cin >> n;
std::cerr << "n was read as: " << n << "\n"; // <- added instrumentation
for // ...
【讨论】:
没有。循环确实执行。我使用的是VC++ 2008,所以我可以通过逐行跟踪代码来调试。【参考方案6】: n 是否从输入正确初始化? 您似乎没有对 getline 进行任何操作。这是你想要的吗? getline 返回一个 istream 引用。你把它丢在地上这件事重要吗?【讨论】:
是的。我尝试打印它,n
已正确初始化。 --- 我在getline之后把代码剪掉了。【参考方案7】:
你在哪个编译器上试过这个?我在 VC2008 上试过,效果很好。如果我在 g++ (GCC) 3.4.2 上编译了相同的代码。它不能正常工作。以下是在两个编译器中工作的版本。我的环境中没有最新的 g++ 编译器。
int n;
cin >> n;
string local;
getline(cin, local); // don't need this on VC2008. But need it on g++ 3.4.2.
for (int i = 0; i < n; i++)
getline(cin, local);
cout << local;
【讨论】:
【参考方案8】:重要的问题是“你对字符串做了什么,让你觉得输入被跳过了?”或者,更准确地说,“你为什么认为输入被跳过了?”
如果您正在单步调试调试器,您是否在编译时进行了优化(允许重新排序指令)?我不认为这是你的问题,但有可能。
我认为更有可能填充了字符串,但没有正确处理。例如,如果要将输入传递给旧的 C 函数(例如,atoi()
),则需要提取 C 样式字符串(local.c_str()
)。
【讨论】:
【参考方案9】:你可以直接在使用分隔符的字符串中使用getline函数,如下:
#include <iostream>
using namespace std;
int main()
string str;
getline(cin,str,'#');
getline(cin,str,'#');
您可以根据需要多次输入 str,但这里适用的一个条件是您需要传递 '#'(第三个参数)作为分隔符,即字符串将接受输入,直到按下 '#' 为止,无论换行符如何。
【讨论】:
同样可以插入循环中。【参考方案10】:在getline(cin, local)
之前,只需添加if(i == 0) cin.ignore();
。这将从字符串中删除最后一个字符 (\n
),这会导致此问题,并且仅在第一个循环中需要它。否则,它将在每次迭代时从字符串中删除最后一个字符。例如,
i = 0 -> string
i = 1 -> strin
i = 2 -> stri
等等。
【讨论】:
【参考方案11】:只需在循环前使用cin.sync()
。
【讨论】:
仅仅分发修复并没有帮助。请同时解释您的答案,以便对社区中的 OP 和其他人有益。背后的“原因”比“修复”更重要。【参考方案12】:只需在 getline 之前添加 cin.ignore() 即可完成工作
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
int n;
cin >> n;
for(int i = 0; i < n; i++)
string local;
cin.ignore();
getline(cin, local);
return 0;
【讨论】:
这对 Pranav Rani 两个月前发布的答案有何改进?此外,他们提供了一个解释并且他们的答案有效。以上是关于std::getline 在 for 循环中不起作用的主要内容,如果未能解决你的问题,请参考以下文章