Search code examples
c++getlinestringstreamistringstream

using stringstream and getline to read the first two numbers of each line


What I need to do: I have a vector of lines right now, v[0] is the first line and so on. I would like to read the first number from each line as the challenge and the second number from each line as the judge and then apply the conditions in the code. I want to use a stringstream to read extract the numbers from the lines.

What my code is doing right now: It is reading only the first number from each line. So the first number of the first line is the challenge and the first number of the second line is the judge and the first number of the third line is the challenge.

    std::vector<string> v;
    string line;
    int i;
    double challenge;
    int judge;

    while (getline(cin, line)) {
        if (line.empty()) {
            break;
        }

        v.push_back(line);
    }

    for (i = 0; i < v.size();i++ ) {
        cin >> v[i];
        std::stringstream ss(v[i]);
        ss << v[i];
        ss >> challenge >> judge;

        if (challenge < 1 || challenge > 5) {
            cout << "bad_difficulty" << endl; //must add the condition or empty
            v.erase(v.begin() + i);
        }

        if (judge != 5 || judge != 7 ) {
            cout << "bad_judges" << endl; //must add the condition or empty
            v.erase(v.begin() + i);
        }

        cout << v[i] << endl;

    }

    return 0;
}

For example:

Input:
 5.1 7 5.4 3.0 9.6 2.9 2.8 2.0 5.4
-3.8 7 2.9 1.1 5.7 7.2 4.8 8.5 3.9
 2.2 5 9.4 4.7 7.3 1.9 5.7 6.0 7.1
 2.4 6 9.2 5.2 1.0 2.9 4.9 7.4 7.9
 2.1 7 7.9 4.9 0.0 7.2 9.1 7.8 6.7 4.3
 3.8 5
 2.0
 4.0 7 2.4 1.9 3.2 8.3 14.8 0.1 9.7
 2.5 7 8.4 -8.0 5.0 6.0 8.0 1.3 3.3
 1.6 -1 9.5 2.5 5.8 7.9 5.5 1.6 7.9

Output should be:
bad_difficulty
bad_difficulty
2.2 5 9.4 4.7 7.3 1.9 5.7 6.0 7.1
bad_judges
2.1 7 7.9 4.9 0.0 7.2 9.1 7.8 6.7 4.3
3.8 5
bad_judges
4.0 7 2.4 1.9 3.2 8.3 14.8 0.1 9.7
2.5 7 8.4 -8.0 5.0 6.0 8.0 1.3 3.3
bad_judges

Current Output:
bad_difficulty
bad_judges
2.2 5 9.4 4.7 7.3 1.9 5.7 6.0 7.1
bad_judges
2.1 7 7.9 4.9 0.0 7.2 9.1 7.8 6.7 4.3
bad_judges
2.0
bad_judges
2.5 7 8.4 -8.0 5.0 6.0 8.0 1.3 3.3
bad_judges
1.6 -1 9.5 2.5 5.8 7.9 5.5 1.6 7.9

Solution

  • Let's go walking through that delete loop.

    i = 0
    v[0] contains line 1. 
    Line 1 is 5.1 7
    challenge > 5, remove 0. The vector shifts up by 1 v[0] now contains line 2
    Judge == 7 do not remove 0
    increment i
    
    i = 1
    v[1] contains line 3. Line 2 has been skipped
    Line 3 is 2.2 5
    challenge < 5, do not remove 1. 
    Judge is not 5 or 7. remove 1. The vector shifts up by 1 v[1] now contains line 4
    increment i
    
    i = 2
    v[2] contains line 5. Line 4 has been skipped
    Line 5 is 2.1 7
    challenge < 5, do not remove 2. 
    Judge is 7. do not remove 2. 
    increment i
    
    i = 3
    v[3] contains line 6. 
    Line 6 is 3.8 5
    challenge < 5, do not remove 3. 
    Judge is 5. do not remove 3. 
    increment i
    
    i = 3
    v[3] contains line 7. 
    Line 7 is  2.0
    challenge < 5, do not remove 3. 
    Judge is UNDEFINED! PANIC! PANIC! Crom only knows what happens.
    increment i
    

    Anyway, the basic pattern here should be clear. When you remove an element from a vector, all subsequent elements are shifted up. Solution: When you remove an element, do not increment i. An elsestatement will take care of this for you.

    Next because there are two separate if statements there is the possibility that both conditions will be true and v[i] will be removed twice. There are a bunch of ways around this. Manthan Tilva's solution with continue is simple and effective, but this can be handled more obviously with an else if or by rolling both tests into the same if.

    Third, using values that were not read from the stream are undefined. and should not be used. Discard the line without looking any further. if (ss >> challenge >> judge) will help here.