getline, кажется, не работает правильно - PullRequest
0 голосов
/ 08 июня 2011

Пожалуйста, скажите мне, что я здесь не так делаю. Что я хочу сделать, это:
1. Имеет текстовый файл с четырьмя числами, каждый из которых имеет 15 цифр:

std::ifstream file("numbers.txt",std::ios::binary);

Я пытаюсь прочитать эти числа в моем массиве:

  char num[4][15];

И то, что я думаю, я делаю так: до тех пор, пока вы не дойдете до конца файлов, пишите каждую строку (максимум 15 символов, заканчивающихся на '\ n') в num [строки]. Но это несколько не работает. Во-первых, он правильно читает только первое число, rest это просто "" (пустая строка), а во-вторых, file.eof () тоже не работает правильно. В текстовом файле, который я представляю ниже этого кода, я достиг строки, равной 156. Что происходит?

                for (unsigned lines = 0; !file.eof(); ++lines)
                {
                    file.getline(num[lines],15,'\n');  
                }

Итак, вся «рутина» выглядит так:

int main()
{
std::ifstream file("numbers.txt",std::ios::binary);

char numbers[4][15];

            for (unsigned lines = 0; !file.eof(); ++lines)
            {
                file.getline(numbers[lines],15,'\n');// sizeof(numbers[0])
            }
}

Это содержимое моего текстового файла:

111111111111111
222222222222222
333333333333333
444444444444444

приписка
Я использую VS2010 sp1

Ответы [ 5 ]

6 голосов
/ 08 июня 2011

Не используйте функцию eof ()! Канонический способ чтения строк:

while( getline( cin, line ) ) {
    // do something with line
}
1 голос
/ 08 июня 2011

Согласно ifstream doc , чтение останавливается либо после чтения n-1 символов, либо после обнаружения знака разделителя: сначала чтение займет всего 14 байтов.

Он читает байты: '1' (символ) равен 0x41: ваш буфер будет заполнен 0x41 вместо 1, как вы, вероятно, ожидаете, последний символ будет 0 (конец c-строки)

Примечание: ваш код не проверяет, что строки не выходят за пределы вашего массива.

Использование getline предполагает, что вы ожидаете текст и открываете файл в двоичном режиме: мне кажется, это неправильно.

1 голос
/ 08 июня 2011

file.getline() извлекает 14 символов, заполняя num[0][0] .. num[0][13]. Затем он сохраняет '\0' в num[0][14] и устанавливает failbit в file, потому что это то, что он делает, когда буфер заполнен, но завершающий символ не достигнут.

Дальнейшие попытки вызова file.getline() ничего не делают, потому что установлен failbit.

Тесты для !file.eof() возвращают true, потому что eofbit не установлен.

Редактировать: чтобы привести рабочий пример, лучше всего использовать строки, конечно, но для заполнения массива char вы можете сделать следующее:

#include <iostream>
#include <fstream>
int main()
{
    std::ifstream file("numbers.txt"); // not binary!
    char numbers[4][16]={}; // 16 to fit 15 chars and the '\0'
    for (unsigned lines = 0;
         lines < 4 && file.getline(numbers[lines], 16);
         ++lines)
    {
        std::cout << "numbers[" << lines << "] = " << numbers[lines] << '\n';
    }
}

протестировано на Visual Studio 2010 SP1

0 голосов
/ 08 июня 2011

Похоже, что '\ n' в конце первого подобного не рассматривается и остается в буфере.Таким образом, в следующем getline() он будет прочитан.

Попробуйте добавить file.get () после каждого getline ().

Если один file.get () не работает, попробуйте двапотому что в кодировке файла Windows по умолчанию строка заканчивается на «\ n \ r \» (или «\ r \ n», я никогда не знаю :)

0 голосов
/ 08 июня 2011

Измените его на следующее:

#include <cstring>

int main()
{
    //no need to use std::ios_base::binary since it's ASCII data
    std::ifstream file("numbers.txt");

    //allocate one more position in array for the NULL terminator
    char numbers[4][16];

    //you only have 4 lines, so don't use EOF since that will cause an extra read
    //which will then cause and extra loop, causing undefined behavior
    for (unsigned lines = 0; lines < 4; ++lines)
    {
        //copy into your buffer that also includes space for a terminating null
        //placing in if-statement checks for the failbit of ifstream
        if (!file.getline(numbers[lines], 16,'\n'))
        {
            //make sure to place a terminating NULL in empty string
            //since the read failed
            numbers[lines][0] = '\0';
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...