views:

46

answers:

3

To simplify, I'm trying to read the content of a CSV-file using the ifstream class and its getline() member function. Here is this CSV-file:

1,2,3
4,5,6

And the code:

#include <iostream>
#include <typeinfo>
#include <fstream>

using namespace std;

int main() {
    char csvLoc[] = "/the_CSV_file_localization/";
    ifstream csvFile;
    csvFile.open(csvLoc, ifstream::in);
    char pStock[5]; //we use a 5-char array just to get rid of unexpected 
                    //size problems, even though each number is of size 1
    int i =1; //this will be helpful for the diagnostic
    while(csvFile.eof() == 0) {
        csvFile.getline(pStock,5,',');
        cout << "Iteration number " << i << endl;
        cout << *pStock<<endl;
        i++;
    }
    return 0;
}

I'm expecting all the numbers to be read, since getline is suppose to take what is written since the last reading, and to stop when encountering ',' or '\n'.

But it appears that it reads everything well, EXCEPT '4', i.e. the first number of the second line (cf. console):

Iteration number 1
1
Iteration number 2
2
Iteration number 3
3
Iteration number 4
5
Iteration number 5
6

Thus my question: what makes this '4' after (I guess) the '\n' so specific that getline doesn't even try to take it into account ?

(Thank you !)

+3  A: 

AFAIK if you use the terminator parameter, getline() reads until it finds the delimiter. Which means that in your case, it has read

3\n4

into the array pSock, but you only print the first character, so you get 3 only.

jpalecek
+6  A: 

You are reading comma separated values so in sequence you read: 1, 2, 3\n4, 5, 6.

You then print the first character of the array each time: i.e. 1, 2, 3, 5, 6.

What were you expecting?

Incidentally, your check for eof is in the wrong place. You should check whether the getline call succeeds. In your particular case it doesn't currently make a difference because getline reads something and triggers EOF all in one action but in general it might fail without reading anything and your current loop would still process pStock as if it had been repopulated successfully.

More generally something like this would be better:

while (csvFile.getline(pStock,5,',')) {
    cout << "Iteration number " << i << endl;
    cout << *pStock<<endl;
    i++;
}
Charles Bailey
"What were you expecting?" Actually, if I take a look at http://www.cplusplus.com/reference/iostream/istream/getline/ , it seems to me that getline acts with '\n' just like it acts with the specified delimiter. Namely, just stopping to read when it is encountered (thus, just like with "1,2" it stops before 2, with "3\n4" it should have stopped before 4).But I guess it's not the case, I that I don't understand everyinthing well ! Thank you for the answer.
Kamixave
@Kamixave: With my reading of cplusplus.com, I don't think it is incorrect. `\n` is just the default delimiter if you don't supply one. If you do supply one it is used instead (not as well).
Charles Bailey
@Charles Bailey: Can you please add std::getline(<stream>,<string>) example. This version has a potential for buffer overflow.
Martin York
@Charles: Yup indeed, you are right, I didn't get it the good way. Thank you :)
Kamixave
@Martin York: How does this version allow buffer overflow? (I know that there are magic numbers which is not ideal practice but I don't see an immediate buffer overflow danger.)
Charles Bailey
@Charles: Sorry wrong way around. It has the potential of not reading all of an integer into the buffer, if the file contained a 6 digit number. I see that currently each number is supposed to be one digit. But I am sure this is not documented in the input file and it would take only one small incorrect edit of the file to cause incorrect behavior. Better to use defensive programming and read each complete number no matter what the size.
Martin York
+1  A: 

Hi, the problem with your code is that getline, when a delimiter is specified, ',' in your case, uses it and ignores the default delimiter '\n'. If you want to scan that file, you can use a tokenization function.

Andrea Monelli