Как заставить cout вести себя как в бинарном режиме? - PullRequest
14 голосов
/ 13 апреля 2011

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

Есть ли на земле способ остановить это, и просто выводить "\ n" при каждом 'cout << "\ n"'? </p>

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

Ответы [ 2 ]

6 голосов
/ 19 декабря 2014

Это работает с использованием 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].

4 голосов
/ 13 апреля 2011

Я не верю, что вы можете заставить 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
    }
}
...