2014-11-08 5 views
10

Рассмотрим пример программы:В чем разница между printf («% s»), printf («% ls»), wprintf («% s») и wprintf («% ls»)?

#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 

Я интересно:

  1. почему 3 & 4 не печатали
  2. , что разницы между 1 & 3 и 2 & 4.
  3. Не имеет значения, если узкий str находится в utf8, а widestr - в utf16?
+1

Вы прочитали документация? В частности, [cstdio] (http://www.cplusplus.com/reference/cstdio/)? –

+0

«widestr is in utf16» подразумевает, что вы используете Windows (более Unicode-совместимые системы используют UTF-32 по умолчанию для широких строк). Есть много тайных обручей, чтобы прыгать, если вы хотите сделать что-либо за пределами ASCII в системе WIndows, используя стандартные C++ или C. Вы можете также использовать WinAPI и использовать его. – Cubbi

+0

НЕ ДАЙТЕ В МИКРОСОФТ-СТУПИДНОСТИ. Спасите себя от боли и напишите свою собственную библиотеку строк. Для любви к Богу НЕ используйте преобразования макросов Windows и другое безумие, поверьте мне, это ужасно, и в замешательстве всевозможные ошибки ползут. – Owl

ответ

0

Ответы на вопросы 1 и 2 приведены в документации. Любой хороший набор документации будет делать. Говорят, cppreference очень хорошо.

Что касается 3, то в стандарте языка не указывается какая-либо конкретная кодировка для строк или какой-либо конкретный размер wchar_t. Вам нужно проконсультироваться с документацией для вашей реализации, а не с языком (хотя писать код, зависящий от реализации, редко бывает целесообразным).

5

Вам нужно сделать:

wprintf(L"3 %hs \n", narrowstr.c_str()); 
wprintf(L"4 %s \n", widestr.c_str()); 

Почему? Потому что для printf, % s говорит узкоколейная строка. Для wprintf, % ls говорит широко.

Но для wprintf, % s предполагает широкий, % Ls будет означать широкий сам. % hs будет означать узкий (для обоих). Для printf, % s, таким образом, будет просто означать % HS

На VC++/Windows, %S (капитал S), будет обратный эффект. Для printf("%S") это будет означать широкий, и wprintf("%S") будет означать узкий. Это полезно для _tprintf.

+0

Это тоже ничего не печатает. [link] (http://ideone.com/ZCiDb1) –

+0

Держитесь! Почему это даже не печатает цифры? Вы проверяли работу wprintf? – Ajay

5

Обратите внимание, что вы используете потоки C. C-потоки имеют очень особое качество, называемое «ориентация». Поток является либо неориентированным, либо широким, либо узким. Ориентация определяется первым выходом из к любому потоку (см http://en.cppreference.com/w/cpp/io/c для резюме потоков CI/O)

В вашем случае, stdout начинается неориентированным, и выполнив первую printf, вы устанавливаете его узким , После того, как он узкий, он застрял узким, и wprintf не работает (проверьте его код возврата!). Единственный способ изменить поток C - freopen, который не работает с stdout. Вот почему 3 и 4 не печатались.

Различия между 1 и 3 заключаются в том, что 1 представляет собой узкую функцию вывода, которая использует спецификатор узких строк% s: он считывает байты из массива символов и отправляет байты в поток байтов.3 представляет собой широкую выходную функцию с узкоспециализированным спецификатором преобразования% s: сначала считывает байты из массива char и mbtowc s их в wchar_t s, а затем отправляет wchar_t s в широкий поток, который затем wctomb s их в байты или многобайтовые последовательности которые затем вставляются в стандартное значение с write

Наконец, если widestr находится в utf16, вы должны использовать Windows, и все ставки отключены; поддержка ASCII на этой платформе очень мало. Вы можете также использовать WinAPI и использовать его с помощью стандартного C++ 11 для некоторых Unicode-приложений и даже делать этот вывод C с помощью магических слов _setmode(_fileno(stdout), _O_U16TEXT);, которые обсуждались достаточно раз)

Смежные вопросы