Рассмотрим этот пример программы:
#include <cstdio>
#include <cwchar>
#include <string>
int main()
{
std::string narrowstr = "narrow";
std::wstring widestr = L"wide";
printf("1 %s \n", narrowstr.c_str());
printf("2 %ls \n", widestr.c_str());
wprintf(L"3 %s \n", narrowstr.c_str());
wprintf(L"4 %ls \n", widestr.c_str());
return 0;
}
Выход этого:
1 narrow
2 wide
Я задаюсь вопросом:
Вам нужно сделать:
wprintf(L"3 %hs \n", narrowstr.c_str());
wprintf(L"4 %s \n", widestr.c_str());
Зачем? Потому что для printf
, % s говорит узкий символ За wprintf
, % Ls говорит широкий.
Но для wprintf
, % s подразумевает широкий, % Ls будет означать сам по себе. % вс будет означать узкий (для обоих). За printf
, % s, таким образом, будет просто означать % вс
На VC ++ / Windows, %S
(заглавная S), обратный эффект. Therfore для printf("%S")
это будет означать широкий и wprintf("%S")
будет означать узкий Это полезно для _tprintf
,
Обратите внимание, что вы используете C-потоки. C потоки имеют очень особое качество, называемое «ориентация». Поток либо неориентирован, либо широк, либо узок. Ориентация определяется первым выводом, сделанным для любого конкретного потока (см. http://en.cppreference.com/w/cpp/io/c для сводки потоков ввода / вывода C)
В твоем случае, stdout
начинается неориентированным, и выполняя первый printf
Вы устанавливаете это узко. Однажды узкий, он застрял узкий, и wprintf
не удается (проверьте его код возврата!). Единственный способ изменить поток C — это freopen
это, которое не совсем работает с stdout. Вот почему 3 и 4 не печатали.
Разница между 1 и 3 состоит в том, что 1 — это узкая выходная функция, которая использует спецификатор преобразования узкой строки% s: она читает байты из массива char и отправляет байты в поток байтов. 3 — это широкая функция вывода с узким спецификатором преобразования строки% s: сначала она читает байты из массива char и mbtowc
с ними в wchar_t
с, затем отправляет wchar_t
в широкий поток, который затем wctomb
их в байты или многобайтовые последовательности, которые затем вставляются в стандарт с write
Наконец, если widestr находится в utf16, вы должны использовать Windows, и все ставки отключены; на этой платформе очень мало поддержки, кроме ASCII. Вы можете также сдаться и использовать WinAPI (вы можете обойтись со стандартным C ++ 11 для некоторых вещей в Юникоде и даже сделать этот вывод на C, используя магические слова _setmode(_fileno(stdout), _O_U16TEXT);
Обсуждали достаточно раз)
Ответы на 1 и 2 в вопросе находятся в документации. Подойдет любой хороший набор документации. Они говорят cppreference очень хорошо.
Что касается 3, языковой стандарт не определяет какую-либо конкретную кодировку для строк или какой-либо конкретный размер wchar_t
, Вы должны обратиться к документации для вашей реализации, а не для самого языка (хотя написание кода, зависящего от реализации, редко рекомендуется).