что определяет, какие байты выводятся из std :: endl - PullRequest
3 голосов
/ 20 августа 2011

У меня есть большая кодовая база, которая использует std :: cout для генерации своего вывода, и он использует std :: endl повсеместно для генерации новых строк. Эта программа, похоже, генерирует только перевод строки для endl, что само по себе не является большой проблемой, но по какой-то причине оказалось не тем, чего я ожидал.

Итак, для проверки реальности я создал простую программу для закачки endl-ов в cout, скомпилировал ее с тем же компилятором и проверил вывод этой информации. Эта программа испускает и CR, и LF для endl.

Не похоже, что большая программа играет в какие-либо игры с cout, чтобы изменить способ работы endl, по крайней мере, я не могу это распознать, поэтому странно, что она должна вести себя иначе, чем маленькая программа. Кажется, что большая программа должна что-то делать, чтобы изменить значения по умолчанию. Что мне здесь не хватает?

Обе программы были скомпилированы с использованием MinGW gcc 4.5.2 в 32-битных окнах.

Ответы [ 3 ]

4 голосов
/ 20 августа 2011

std::endl определяется Стандартом C ++ для выполнения следующих действий:

  • Поток символа '\n';
  • Поток манипулятора std::flush I / O.

Если вы видите возврат каретки на другом конце потока, то это происходит на файловом интерфейсе (а не в самой функциональности потока);в частности, в Windows можно ожидать прозрачного перевода "\n" в "\r\n" во время вывода текстового режима в файлы.

Итак, убедитесь, что оба ваших файла открываютсяв текстовом или двоичном режиме соответственно.В C ++ больше нет ничего, что могло бы повлиять на это поведение.

Эта запись часто задаваемых вопросов в значительной степени охватывает и то, что я только что сказал.

3 голосов
/ 20 августа 2011

Чтобы добавить к ответу Томалака Гереткала: тот факт, что endl расширяется до конечной строки, характерной для платформы, является распространенным заблуждением.

Внутри приложения C / C ++ единственный "официальный" перевод строкипо крайней мере, если речь идет о потоках и связанных с ними функциях), то это '\n'.Перевод с '\n' на новую строку для конкретной платформы выполняется внутри потоков 1 , когда они открываются в текстовом режиме (т.е. без флага ios::bin).

endl вместо этого используется для принудительного сброса потока после '\n';это может быть полезно для вывода на консоль, но (1) часто это не тот случай (cout автоматически сбрасывается при запросе ввода от cin через механизм связанного потока) и только тратит время ЦП, и (2)вы часто обнаруживаете, что он используется также в файловых потоках, где он почти никогда не полезен, и приводит к низкой производительности записи файлов.

  1. Как обсуждалось в комментариях, что касается стандарта, перевод может фактически произойти на любом уровне ниже потока (например, поток может преобразовать присутствие / отсутствие ios::bin в флаг для основногоФункции управления файлами ОС, и ОС будет выполнять перевод);на самом деле основные ОС не имеют определенных флагов для этого вида перевода, главным образом потому, что их файловые API-интерфейсы не зависят от содержимого (вы говорите им, что писать, они пишут это без изменений).
1 голос
/ 20 августа 2011

Когда файл открывается в режиме «ТЕКСТ» (по умолчанию при создании файловых потоков).

Символ '\ n' преобразуется в специфическую для платформы "последовательность конца строки" при записиэто в файл.И наоборот, «конец строки» преобразуется в «\ n» при чтении из файла.

Обратите внимание, что если вы открываете файл в режиме «BINARY», это преобразование не происходит.

По отношению к std :: endl

stream << std::endl

Эквивалентно:

stream << '\n' << std::flush;

Таким образом, если ваш поток является std :: fstream (который был открыт нормально), тогда '\Символ n 'будет преобразован в "конец строки", который на некоторых платформах равен' \ r \ n '

...