Search code examples
c++stringio

Parsing string input separated over several lines fails


I am trying to parse a string input and my way of parsing it is not behaving the way I want it to. I fail to see where I am going wrong, and hopefully you can guide me a bit.

The input is a sequence of triple string inputs like the following

1 4 1 2
1 2 2 4
1 2 4 2

The input is provided by a service which I have no control over. At the end of the line there is no extra whitespace, e.g. the line is 1 4 1 2, full stop. My current way of parsing the input is

string line;
while (getline(cin, line) && !line.empty()) input += line;

The problem arises after I have finished parsing the input, which becomes

1 4 1 21 2 2 41 2 4 2
      --     --

I have highlighted where the problem arises by underlining it in the result of the parsing. As you can see the first digit of the next line gets concatenated with the first. This causes the input to be unusable for further processing because 21and 41 are unexpected inputs.

I expect the result of the input parsing to be

1 4 1 2 1 2 2 4 1 2 4 2

I've tried to reproduce this manually by passing in an input where I manually add whitespace after each line, which produces the result I want but seeing that the service does not do this I am bit at a loss on how to proceed.

Thank you for taking your time to read this and for any help you can provide.


Solution

  • getline operates on an istream. It reads the istream until it encounters the delimiter character or end of file. It populates the string with all characters up to the delimiter, not including the delimiter, and advances the stream to one past the delimiter. You're already being given the input line-by-line, but then reconcatenating each line with the delimiter missing. You ARE being given the data with a newline, but you're discarding it. What do you want to do with the data?

    The canonical way to operate on input data line-by-line is to take advantage of the return value of getline being the istream that you passed into it, and further taking advantage of an istream being convertible to a boolean. You don't need to check if the line was empty, unless it's valid for your input to have empty lines (multiple newlines in a row).

    What you probably want is something like:

    std::string line;
    while (std::getline(std::cin, line))
    {
      // do something with the line here
    }