Как заставить cout вести себя как в бинарном режиме?

Каждый раз, когда я делаю 'cout ‹‹ endl' или даже 'cout ‹‹ "\n"', а затем запускаю свою программу под Windows для вывода в файл ("a.exe ‹ test.in > result.out"), я получаю Строка "\r\n" заканчивается в "result.out".

Есть ли способ остановить это и просто выводить «\n» на каждый «cout ‹‹ «\n»»?

Заранее спасибо.


person lithuak    schedule 13.04.2011    source источник
comment
Зачем это делать? Windows предпочитает CRLF LF. Несколько плохо написанных приложений (включая, по крайней мере, более старые версии текстового редактора по умолчанию) будут иметь проблемы с этим. Если вы на самом деле не имеете дело с двоичными данными (в вопросе это явно не указано), вам не о чем беспокоиться.   -  person    schedule 13.04.2011
comment
denlan: по требованиям мой код должен работать под Windows И производить вывод, определенный в спецификации, которая, к сожалению, говорит, что разделители строк строго \n. \r\n ломает другие утилиты, которые также следуют спецификации и ожидают ТОЛЬКО файлов с разделителями \n на входе :( Это более или менее стандартный беспорядок с поддержкой устаревшего кода/системы.   -  person lithuak    schedule 13.04.2011


Ответы (2)


Это работает с использованием Visual Studio 2013:

#include <io.h>
#include <fcntl.h>
#include <iostream>

int main( int argc, char * argv[] )
{
    _setmode( _fileno( stdout ),  _O_BINARY );
    std::cout << std::endl;
}

Будет выведено только [0A], а не [0D][0A].

person Rob K    schedule 19.12.2014

Я не верю, что вы можете заставить std::cout выводить двоичные данные. Интерфейс самого низкого уровня, доступный пользователю через C++, — это streambuf в std::cout.rdbuf(). Вы вполне можете предположить, что объект имеет тип basic_filebuf, а раздел §27.9.1.4 стандарта C++11 требует, чтобы basic_filebuf реализовывал отдельные текстовый и двоичный режимы.

Проверьте расширения для вашей платформы, чтобы узнать, как открыть другой поток для stdout, используя его файловый дескриптор. Затем вы можете указать std::binary в флагах режима.

Однако, вероятно, проще направить вывод через вторую программу, которая преобразует окончания строк.

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

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

В самом начале вашей программы, прежде чем cout получит какие-либо выходные данные, сделайте следующее:

std::cout.rdbuf()->pubsetbuf( 0, 0 ); // go to unbuffered mode

Если вы хотите вывести новую строку, сделайте это так:

_write( STDOUT_FILENO, 1, "\n" ); // do not convert line ending

Вы можете обернуть этот маленький... самородок... внутри пользовательского манипулятора:

#include <unistd.h>

std::ostream &endln( std::ostream &s ) {
    if ( s->rdbuf() == std::cout.rdbuf() ) { // this is cout or cerr into cout
        _write( STDOUT_FILENO, 1, "\n" ); // do not convert line ending
        return s; // stream is unbuffered, no need to flush
    } else {
        return std::endl( s ); // other streams do convert to \r\n
    }
}
person Potatoswatter    schedule 13.04.2011