开发者

std::getline does not work inside a for-loop

I'm trying to collect user's input in a string variable that accepts whitespaces for a specified amount of time.

Since the usual cin >> str doesn't accept whitespaces, so I'd go w开发者_运维问答ith std::getline from <string>

Here is my code:

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

Any idea?


You can see why this is failing if you output what you stored in local (which is a poor variable name, by the way :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;
}

You will see it prints a newline after > immediately after inputting your number. It then moves on to inputting the rest.

This is because getline is giving you the empty line left over from inputting your number. (It reads the number, but apparently doesn't remove the \n, so you're left with a blank line.) You need to get rid of any remaining whitespace first:

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

This the works as expected.

Off topic, perhaps it was only for the snippet at hand, but code tends to be more readable if you don't have using namespace std;. It defeats the purpose of namespaces. I suspect it was only for posting here, though.


Declare a character to get in the carriage return after you have typed in the number.char ws;int n;cin>>n;ws=cin.get(); This will solve the problem.

Using cin>>ws instead of ws=cin.get(),will make first character of your string to be in variable ws,instead of just clearing '\n'.


It's quite simple. U jst need to put a cin.get() at the end of the loop.


Are you hitting enter? If not get line will return nothing, as it is waiting for end of line...


My guess is that you're not reading n correctly, so it's converting as zero. Since 0 is not less that 0, the loop never executes.

I'd add a bit of instrumentation:

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


why this happens : This happens because you have mixed cin and cin.getline. when you enter a value using cin, cin not only captures the value, it also captures the newline. So when we enter 2, cin actually gets the string “2\n”. It then extracts the 2 to variable, leaving the newline stuck in the input stream. Then, when getline() goes to read the input, it sees “\n” is already in the stream, and figures we must have entered an empty string! Definitely not what was intended.

old solution : A good rule of thumb is that after reading a value with cin, remove the newline from the stream. This can be done using the following :

std::cin.ignore(32767, '\n'); // ignore up to 32767 characters until a \n is removed

A better solution : use this whenever you use std::getline() to read strings

std::getline(std::cin >> std::ws, input); // ignore any leading whitespace characters

std::ws is a input manipulator which tell std::getline() to ignore any leading whitespace characters

source : learncpp website goto section (Use std::getline() to input text)

hope this is helpful


  • Is n properly initialized from input?
  • You don't appear to be doing anything with getline. Is this what you want?
  • getline returns an istream reference. Does the fact that you're dropping it on the ground matter?


On which compiler did you try this? I tried on VC2008 and worked fine. If I compiled the same code on g++ (GCC) 3.4.2. It did not work properly. Below is the versions worked in both compilers. I dont't have the latest g++ compiler in my environment.

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


The important question is "what are you doing with the string that gives you the idea that the input was skipped?" Or, more accurately, "why do you think the input was skipped?"

If you're stepping through the debugger, did you compile with optimization (which is allowed to reorder instructions)? I don't think this is your problem, but it is a possibility.

I think it's more likely that the string is populated but it's not being handled correctly. For instance, if you want to pass the input to old C functions (eg., atoi()), you will need to extract the C style string (local.c_str()).


You can directly use getline function in string using delimiter as follows:

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

you can input str as many times as you want but one condition applies here is you need to pass '#'(3rd argument) as delimiter i.e. string will accept input till '#' has been pressed regardless of newline character.


Before getline(cin, local), just add if(i == 0) { cin.ignore(); }. This will remove the last character (\n) from the string, which is causing this problem and its only needed for the first loop. Otherwise, it will remove last character from the string on every iteration. For example,

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

and so on.


just use cin.sync() before the loop.


just add cin.ignore() before getline and it will do the work

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜