Смешивание cout и wcout в одной программе - PullRequest
21 голосов
/ 21 января 2012

Я читал «Кулинарную книгу C ++», в которой был следующий фрагмент:

// cout  << s  << std::endl;  // You shouldn't be able to
wcout << ws << std::endl;     // run these at the same time

Если вам интересно увидеть реальный пример, вот ссылка на страницу в книгах Google.

Кроме того, я нашел ТАК вопрос , который, кажется, говорит о том, что смешивать wcout и cout можно.Может ли кто-нибудь объяснить мне, о чем идет речь в этом комментарии?

РЕДАКТИРОВАТЬ

Из стандарта C ++ [27.4.1]:

Микшированиеоперации с соответствующими широкими и узкими символьными потоками следуют той же семантике, что и смешивание таких операций над файлами, как указано в поправке 1 к стандарту ISO C.

из стандарта C [7.19.2]:

Каждый поток имеет ориентацию.После того, как поток связан с внешним файлом, но перед выполнением каких-либо операций с ним, поток не имеет ориентации.Как только функция ввода / вывода широких символов была применена к потоку без ориентации, поток становится широко ориентированным потоком.Точно так же, как только байтовая функция ввода / вывода была применена к потоку без ориентации, поток становится потоком с байтовой ориентацией.В противном случае только вызов функции freopen или функции fwide может изменить ориентацию потока.(Успешный вызов freopen удаляет любую ориентацию.)

Байтовые функции ввода / вывода не должны применяться к широко ориентированному потоку, а широкие символьные функции ввода / вывода не должны применяться к байтово ориентированному потоку.

Итак, стандарт, кажется, говорит, что вы не должны смешивать их.Однако я нашел эту цитату из этой статьи :

Для Visual C ++ 10.0 функция fwide задокументирована как невыполненная.И с практической точки зрения, по крайней мере на уровне вывода целых строк, он, очевидно, прекрасно работает, чтобы смешать использование cout и wcout.Так что, к счастью, Visual C ++ явно игнорирует требования стандарта и не поддерживает непрактичную явную ориентацию потока C FILE.

А также, что касается gcc, я нашел эту цитату из здесь :

Это (новая) функция, а не ошибка, см. Libstdc ++ / 11705 и общий поиск ориентации потока в стандарте C (C99, 7.19.2).Короче говоря, вы не можете смешивать байтово-ориентированный и широко-ориентированный ввод-вывод.На данный момент, из-за ошибки , указанной в libstdc ++ / 11705, вы можете получить что-то близкое к вашим ожиданиям, вызвав std :: ios :: sync_with_stdio (false);в начале вашей программы.

Ответы [ 5 ]

19 голосов
/ 22 января 2012

Когда cout или wcout вызывается впервые, устанавливается ориентация для stdout. В случае cout, stdout становится байтовым потоком, а в случае wcout, stdout становится широко ориентированным потоком. Согласно стандарту C ++ [27.4.1] и стандарту C [7.19.2], после установки ориентации потока не следует вызывать функцию, несовместимую с ориентацией этого потока.

2 голосов
/ 21 января 2012

Понятия не имею.

За исключением потоков, вы не можете запустить любой два оператора "одновременно". Вы, конечно, можете использовать cout и wcout в разных точках вашей программы. Они оба отображаются на STDOUT, и это все ... хотя в некоторых случаях вы можете не справиться с различными буферами и получить немного неожиданный порядок.

По-видимому, каждый из них направляет ориентацию в "целевой" поток STDOUT, и ему не разрешено смешивать операции с потоком, который был наполнен ориентацией [C++11: 27.4.1] и [C99: 7.19.2] .

1 голос
/ 21 января 2012

Нарушение «не» из стандарта обычно ставит вас в область неопределенного поведения. Неопределенное поведение может очень хорошо работать должным образом в некоторых реализациях.

1 голос
/ 21 января 2012

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

0 голосов
/ 21 января 2012

В качестве предположения: cout и wcout - это два разных потока, а предоставленные вами кавычки ничего не говорят о том, как ориентация потока коррелирует с ориентацией основного файла.Может быть, потоки молча переориентируются stdout под капотом?

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