Home > Software engineering >  Problem extracting formatted input from an istringstream that has been set twice
Problem extracting formatted input from an istringstream that has been set twice

Time:12-19

Thanks for the help. My program reads lines from stdin. The first one has a single number which determines the mode at which the program is running, and the rest contain sequences of numbers of undetermined length. The number of lines is determined by the mode. I want to parse those lines into vectors of int. To do this, I am using getline and istringstream. I then get the numbers with formatted extraction >>. The first time I pass the string to the stream, there isn't any problem, the string is correctly passed to the stream, and I can read formatted input from it. However, if I get another line and pass it to the same stream, then something weird happens. The string is correctly copied to the stream, which I confer by writing

std::cout << iss.str() << std::endl

However, when I try to extract the numbers from the line, it doesn't.

Here is a Minimum Reproducible Example:

(I have tried to do it with two different streams and it works, the problem is that I have the cases inside a switch block, so it doesn't let me initialize streams inside it, and the number of streams changes quite a bit from mode to mode.)

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    string line;
    int problem_type = -1, input_number = -1;
    vector<int> sequence;
    istringstream iss;

    /* Get the problem type */
    getline(cin, line);
    iss.str(line);
    if (!iss)
        return -1;
    cout << "Stream contents: " << iss.str() << endl;
    iss >> problem_type;
    cout << "Extracted numbers: " << problem_type << endl;
    
    getline(cin, line);
    iss.str(line);
    if (!iss)
        return -1;
    cout << "Stream contents: " << iss.str() << endl;

    cout << "Extracted numbers:";
    while(iss >> input_number) {
        cout << " " << input_number;
        sequence.push_back(input_number);
    }
    cout << endl;
    return 0;
}

Input:

1
1 2 3 4 5

Output:

Stream contents: 2
Extracted numbers: 2
Stream contents: 1 2 3 4 5
Extracted numbers:

Expected Output:

Stream contents: 2
Extracted numbers: 2
Stream contents: 1 2 3 4 5
Extracted numbers: 1 2 3 4 5

CodePudding user response:

Once you read iss >> problem_type;,

cout << "eof: " << iss.eof() << endl;

outputs

eof: 1

The next iss.str(line); does not reset the stream state, the loop condition is false. You want

iss.clear();
while(iss >> input_number) {
    cout << " " << input_number;
    sequence.push_back(input_number);
}

Output

Stream contents: 1
Extracted numbers: 1
Stream contents: 1 2 3 4 5
Extracted numbers: 1 2 3 4 5
  • Related