std :: getline在for循环中不起作用

时间:2010-01-11 04:29:14

标签: c++ getline

我正在尝试在一个字符串变量中收集用户的输入,该变量在指定的时间内接受空格。

由于通常的cin >> str不接受空格,所以我从< string>

开始使用std :: getline

这是我的代码:

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

有什么想法吗?

12 个答案:

答案 0 :(得分:12)

如果你输出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;
}

这可以按预期工作。

偏离主题,也许只针对手头的代码段,但如果您没有using namespace std;,代码往往更多可读。它违背了名称空间的目的。我怀疑这只是为了张贴在这里。

答案 1 :(得分:2)

在输入数字后,声明一个字符进入马车char ws;int n;cin>>n;ws=cin.get(); 这将解决问题。

  

使用cin>>ws代替ws=cin.get(),会使字符串的第一个字符变为ws,而不是仅仅清除'\n'

答案 2 :(得分:1)

你打进入吗?如果没有获取行将不会返回任何内容,因为它正在等待行结束...

答案 3 :(得分:1)

我的猜测是你没有正确阅读n,所以它转换为零。由于0不小于0,因此循环永远不会执行。

我会添加一些仪器:

int n;
cin >> n;
std::cerr << "n was read as: " << n << "\n"; // <- added instrumentation
for // ...

答案 4 :(得分:0)

  • 是否已从输入中正确初始化?
  • 您似乎没有对getline做任何事情。这是你想要的吗?
  • getline返回一个istream引用。事实上,你是否将它放在地上?

答案 5 :(得分:0)

您尝试使用哪个编译器?我试过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;
}

答案 6 :(得分:0)

重要的问题是“你在用字符串做什么让你知道输入被跳过?”或者,更准确地说,“为什么你认为输入被跳过?”

如果您正在单步执行调试器,是否使用优化进行编译(允许重新排序指令)?我不认为这是你的问题,但这是一种可能性。

我认为字符串更有可能被填充,但是没有正确处理。例如,如果要将输入传递给旧的C函数(例如,atoi()),则需要提取C样式字符串(local.c_str())。

答案 7 :(得分:0)

您可以使用分隔符直接在字符串中使用getline函数,如下所示:

#include <iostream>
using namespace std;
int main()
{
    string str;
    getline(cin,str,'#');
    getline(cin,str,'#');
}

你可以根据需要多次输入str,但是这里适用一个条件是你需要传递#&#39;(第三个参数)作为分隔符,即字符串将接受输入直到&#39;#& #39;无论换行符都被按下了。

答案 8 :(得分:0)

这很简单。 首先,需要在循环末尾放置一个cin.get()。

答案 9 :(得分:0)

getline(cin, local) 之前,只需添加 if(i == 0) { cin.ignore(); }。这将从字符串中删除最后一个字符 (\n),这会导致此问题并且仅在第一个循环中需要它。否则,它将在每次迭代时从字符串中删除最后一个字符。例如,

i = 0 -> string
i = 1 -> strin
i = 2 -> stri

等等。

答案 10 :(得分:-1)

只需在循环前使用 Text Field Equal To = string exp = "(Name =\"India\")"; Text Field NOT Equal To = string exp = "(Name !=\"India\")"; Text Field Contains = string exp = "(Name.Contains (\"Ind\"))"; Text Field Starts With = string exp = "(Name.StartsWith (\"Ind\"))"; Text Field Ends With = string exp = "(Name.EndsWith (\"a\"))"; Number Field Equal to = string exp = "(Id = 1)"; Number Field Between with multiple conditions = string exp = "(Id > 1 AND Id <= 3) OR Id =3"; Number Field Between and greater than equal to = string exp = "(Id > 1 AND Id >= 3)"; Date Field Between = string exp = "(Dt > Convert.ToDateTime(\"2/5/2021 4:46:04 AM\") AND Dt >= Convert.ToDateTime(\"2/3/2021 4:46:04 AM\"))";

答案 11 :(得分:-1)

只需在 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;
}