Неожиданное поведение getline () с ifstream - PullRequest
2 голосов
/ 18 августа 2010

Для упрощения я пытаюсь прочитать содержимое CSV-файла, используя класс ifstream и его функцию-член getline ().Вот этот CSV-файл:

1,2,3
4,5,6

И код:

#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;
}

Я ожидаю, что все числа будут прочитаны, так как getline предполагает взять то, что написано споследнее чтение и прекратить при обнаружении ',' или '\ n'.

Но, похоже, все хорошо читается, кроме «4», то есть первого числа второй строки (см. console):

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

Таким образом, мой вопрос: что делает это '4' после (я полагаю) настолько специфическим '\ n', что getline даже не пытается принять это во внимание?

(Спасибо!)

Ответы [ 3 ]

6 голосов
/ 18 августа 2010

Вы читаете значения через запятую, поэтому в следующей последовательности вы читаете: 1, 2, 3\n4, 5, 6.

Затем каждый раз вы печатаете первый символ массива: то есть 1, 2, 3, 5, 6.

Чего вы ожидали?

Кстати, ваш чек на eof находится не в том месте. Вы должны проверить, успешен ли вызов getline. В вашем конкретном случае это в настоящее время не имеет значения, потому что getline читает что-то и запускает EOF все в одном действии, но в целом он может потерпеть неудачу, ничего не читая, и ваш текущий цикл все равно будет обрабатывать pStock, как если бы он был снова заполнен успешно.

В общем, что-то вроде этого было бы лучше:

while (csvFile.getline(pStock,5,',')) {
    cout << "Iteration number " << i << endl;
    cout << *pStock<<endl;
    i++;
}
3 голосов
/ 18 августа 2010

AFAIK, если вы используете параметр терминатора, getline() читает, пока не найдет разделитель.Это означает, что в вашем случае он прочитал

3\n4

в массив pSock, но вы печатаете только первый символ, поэтому вы получаете только 3.

1 голос
/ 18 августа 2010

проблема с вашим кодом в том, что getline, когда указан разделитель, ',' в вашем случае использует его и игнорирует разделитель по умолчанию '\ n'. Если вы хотите отсканировать этот файл, вы можете использовать функцию токенизации.

...