0

I want to read only first number in each line which is delimited with \n and skip other data. Example:

123 123 456 asdf\n234 ewdwedwed should be parsed, for example, into a vector with values {123, 234}.

My first attempt is the following snippet:

int main()
{
    std::stringstream ss { "123 123 456 asdf\n234 ewdwedwed" };
    std::vector<int>  values;
    int               value;
    std::string       skip;
    while (ss >> value) {
        values.push_back(value);
        std::getline(ss, skip);
    }

    return 0;
}

But I wonder whether getline will actually copy data into temp string. In such a case it will do unnecessary copying and consume more memory than needed. Am I right? Should the getline be replaced with some kind of peek and ignore methods:

while (ss >> value) {
    values.push_back(value);
    while (ss.peek() != '\n'){
        ss.ignore();
    }
}
2
  • 2
    @qloq "I wonder whether getline will actually copy data into temp string" - yes it will Commented Jul 10 at 0:39
  • Why do you need "... the most efficient way..."? I/O is a known bottleneck for programs, so don't expect too much efficiency from reading or writing. Commented Jul 10 at 1:16

1 Answer 1

2

If you just want to empty out the stream until the next newline, there is a built-in way to do this already. The stream's ignore() method has defined behavior that if the size passed to it is std::nuneric_limits<std::streamsize>::max() then it will ignore everything in the stream until the specified character. This lets the code become:

while (ss >> value) {
    values.push_back(value);
    ss.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
}

and now there is no copying to an unused string, and you aren't constantly checking the stream yourself.


std::numeric_limits<std::streamsize>::max() is a bit of a mouthful, but it can be simplified with an alias like:

constexpr auto no_limit = std::numeric_limits<std::streamsize>::max();

and then you would use it like:

ss.ignore(no_limit, '\n')
2
  • 1
    I'd suggest no_limit for the nsame of the constant here. Yes, ignore() uses max() to represent "no limit", but that's an implementation detail not important to the reader of the loop.
    – Ben Voigt
    Commented Jul 10 at 15:03
  • @BenVoigt Great suggestion. Added. Commented Jul 10 at 15:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.