Это ошибка cout и getline в g++ 4.7.2?

Обновление 13 ноября 2012 г. Я обнаружил, что мой вопрос уже задан. Вот хорошее решение для обработки различных текстовых файлов с окончанием строки: std :: ifstream для обработки LF, CR и CRLF?

Можно ли внести свой вклад в libstdС++? Как?


2012/11/11

Я обнаружил, что что-то не так с cout.
Если есть две строки, возвращенные из getline(),
вторая строка перезапишет первую в выходных данных.

Это пример кода:

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

int main()
{
    //normal code
    cout << "Normal result:" << endl;
    string str1 = "hello";
    cout << str1;
    str1 = "123";
    cout << str1;

    cout << endl;

    //broken code
    cout << "Bug?" << endl;
    ifstream fin;
    fin.open("test.dat");

    string str;

    getline(fin, str);
    cout << str;

    getline(fin, str);
    cout << str;

    fin.close();
    return 0;
}

А вот входной файл (test.dat):

hello
123

Вывод будет:

Normal result:
hello123
Bug?
123lo

Я использую Ubuntu 12.10 64-бит,
и версия компилятора g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2.
Есть совет? Кто-нибудь подскажет, куда написать ошибку?


person EriCSN    schedule 11.11.2012    source источник
comment
Обновление: возможно, это не ошибка, а улучшение. Кто-нибудь может сказать мне, куда подать этот вопрос? Можно ли размещать сообщения на Bugzilla?   -  person EriCSN    schedule 13.11.2012


Ответы (1)


Более вероятно, чем ошибка в libstdc++ (которая может возникнуть, как и в gcc, но довольно редко в наши дни), в вашем входном файле неправильное завершение строки - вероятно, оно использует окончания строк DOS/Windows CR+LF, что - поскольку getline() отбрасывает LF - в результате вторая строка записывается поверх первой. Вы можете легко увидеть это, если запустите вывод своей программы через какой-нибудь шестнадцатеричный дампер, например. xxd.

Либо проверьте наличие \r в конце строк, которые вы читаете (кстати, MacOS до версии 9 использовала именно это как маркер EOL), исправьте ввод или должным образом добавьте новые строки в вывод при печати.

person peterph    schedule 11.11.2012
comment
Я понял. Большое спасибо! Я забыл, что раньше устанавливал режим CR+LF для своего текстового редактора Geany. Я проверю это. - person EriCSN; 12.11.2012
comment
Я переписал свой входной файл в режиме LF, и код работает. Но мне было интересно, почему мой текстовый редактор может распознавать эти разные окончания строк, а компилятор — нет? :( - person EriCSN; 13.11.2012
comment
C++ использует \n в качестве разделителей строк, текстовые редакторы пытаются угадать, что использовать (для нового файла они используют системное значение по умолчанию, для существующего обычно проверяют окончание первой строки). - person peterph; 13.11.2012
comment
@peterph Я думаю, пришло время нарушить правило. Кто-нибудь знает, куда обратиться с этим вопросом? - person EriCSN; 14.11.2012
comment
@EriCSN Если вы хотите пожаловаться на то, что '\n' является разделителем строки, я думаю, вам придется подать жалобу в комитет по стандартизации C++ см. Википедию. Хотя я не уверен, что вы добьетесь большого успеха. - person peterph; 14.11.2012
comment
Я тоже. Думаю, да... lol Несмотря на эти стандартные правила, есть ли шанс заставить компилятор принять этот обходной путь? Дело в том, что существует три разных типа окончания строки. Более того, сегодня у нас больше возможностей обрабатывать текстовые файлы с разных платформ. Я бы хотел, чтобы компилятор имел возможность обрабатывать эти окончания строк. - person EriCSN; 15.11.2012
comment
На самом деле это встроено в стандартную библиотеку C++. Так что теоретически вы можете исправить его и перекомпилировать, но вряд ли вы захотите это сделать. Я бы предпочел конвертировать файлы перед их использованием - нет особого смысла реализовывать ту же магию, которую используют редакторы. На самом деле, если вы придерживаетесь разумных систем, конец строки всегда будет содержать '\n', поэтому единственное, что вам нужно, это избавиться от '\r' в начале или конце ваших строк, как только вы их прочитаете. - person peterph; 15.11.2012
comment
@peterph Ответ действительно полезен для меня. С ним все кажется очень простым и эффективным. Может быть, я просто слишком много думал... Большое спасибо! - person EriCSN; 15.11.2012