0

Okay, so I have an input file input.txtthat contains a CSV sequence: 1,1,1,2,2,3,3,4,4 and I am trying to separate it at the commas using a stringstream; however I'm getting a little problem here. For some reason the first number from the sequence is not even getting read by the stream. To show this, I created a some debugging code to see what is happening and I found out that the first number is being stored inside csvLine and every other number is being read and coverted just fine. I don't understand why just the first number is being omitted. Below is an example pic showing exactly what I mean. num should have the same exact values and Line, but it's not. It has all the values except the first one, which is being stored inside csvLine. Why is this happening?!

program output showing how it skips the first number

#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

int main(int argc, const char * argv[]) {
    ifstream file;
    string line;
    string csvLine; //comma seperated value line
    int num = 0;
    file.open(argv[1]);
    if(file.is_open()) {
        while(getline(file, line)) { //get the whole line and use string stream to break at commas
            cout << "\nLine: " << line << endl;
            //using stringstream to seperate at commas
            stringstream ss(line);
            while(getline(ss, csvLine, ',')) {
                cout << "csvLine: " << csvLine << " " << endl;
                //using stringstream to convert to int
                ss >> num;
                cout << "num: " << num << " " << endl;
            }
        }
    }
    return 0;
}
Damian
  • 89
  • 2
  • 14
  • Don't mix `getline` and `>>`. http://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction – chris Oct 26 '14 at 20:00

2 Answers2

2

The problem arises since you're using getline and then extracting integer from your stringstream

You should only use getline

 while(getline(ss, csvLine, ',')) 
{
    cout << "csvLine: " << csvLine << " " << endl;
    num = std::stoi( csvLine ) ;        
}
P0W
  • 42,046
  • 8
  • 62
  • 107
1

When you read getline(ss, csvLine, ',') the first time it reads the number followed by the the ','. For the next numbers it just reads the comma as the number was already extracted using ss >> num. That is, the simplest fix is to only read everything up to and including the comma after the loop was executed. Since the value of string extracting the comma isn't used it makes sense to use ignore() instead of std::getline():

for (; ss >> num; ss.ignore(std::numeric_limits<std::streamsize>::max(), ',')) {
    // do something with the number
}

Restructuring the loop this way has the added benefit that it is checked whether reading the number was successful.

Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356