Вопрос по c++, c, visual-studio-2010, unicode – Почему printf не форматирует параметры Unicode?

7

При использовании printf для форматирования двухбайтовой строки в однобайтовую строку:

<code>printf("%ls\n", L"s:\\яшертыHello");   // %ls for a wide string (%s varies meaning depending on the project's unicode settings).
</code>

Ясно, что некоторые символы не могут быть представлены как символы ascii, поэтому иногда я видел поведение, когда двухбайтовые символы превращаются в '?' пометить персонажа. Но, похоже, это зависит от конкретных персонажей. Для приведенного выше printf выводом является:

<code>s:\
</code>

Я надеялся получить что-то вроде:

<code>s:\??????Hello
</code>

Боюсь, что я потерял пример, но я думаю, что для одной строки, где встречаются символы Юникода, заменил первую на '?' а потом отказался от отдыха.

Итак, мой вопрос, что должно произойти, когда вы форматируете широкую строку в однобайтовую строку. Документация здесь:http: //msdn.microsoft.com/en-us/library/hf4y5e3w.asp говорит: «Символы отображаются с точностью до первого нулевого символа». Но я этого не вижу. Это ошибка в printf, или поведение, которое я вижу, задокументировано где-то, если так, где.

Спасибо за вашу помощь

ОБНОВИТ

Спасибо за ответы людей, дающих мне альтернативы использованию printf. Я собираюсь перейти на альтернативу, но мне действительно интересно из любопытства, почему printf не имеет надежного документированного поведения. Похоже, что его разработчик сделал все возможное, чтобы это не сработало.

Кажется, этоsprintf/printf выпуск.wsprintfA работает отлично Abyx
OK% S% s Значение не меняется независимо от того, определен юникод или нет, зависит от того, используете ли вы printf или wprintf. Scott Langham
Вы использовали "% S" в качестве спецификатора формата вместо "% ls"? Daniel Schlößer
да. Я считаю, что% S и% ls имеют одинаковое значение, если в вашем проекте не определен UNICODE. Scott Langham
Читая спецификации формата (что я согласен, не ясно). S для широкой строки, когда в настройках вашего проекта не определен UNICODE, S для однобайтовой строки, если у вас определен UNICODE. % ls предназначен для широкой строки независимо от того, создаете ли вы UNICODE или нет. % s также меняет значение,% hs всегда для однобайтовых строк. Scott Langham

Ваш Ответ

2   ответа
5

В С ++ я обычно используюstd::stringstream для создания форматированного текста. Я также реализовал собственный оператор для использования функции Windows для кодирования:

ostream & operator << ( ostream &os, const wchar_t * str )
{
  if ( ( str == 0 ) || ( str[0] == L'\0' ) )
   return os;
  int new_size = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, NULL, NULL, NULL );
  if ( new_size <= 0 )
    return os;
  std::vector<char> buffer(new_size);
  if ( WideCharToMultiByte( CP_UTF8, 0, str, -1, &buffer[0], new_size, NULL, NULL ) > 0 )
    os << &buffer[0];
  return os;
}

Этот код конвертировать в UTF-8. Для других возможностей проверьте:WideCharToMultiByte.

Отличный пример того, как это сделать:) jcoder
@ JohnB: спасибо! :) Naszta
12

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

#include <locale.h>
#include <stdio.h>

int main()
{
    int c;
    char* l = setlocale(LC_ALL, "");
    if (l == NULL) {
        printf("Locale not set\n");
    } else {
        printf("Locale set to %s\n", l);
    }
    printf("%ls\n", L"s:\\яшертыHello");
    return 0;
}

а вот трассировка выполнения:

$ env LC_ALL=en_US.utf8 ./a.out
Locale set to en_US.utf8
s:\яшертыHello

Если он говорит, что локаль не установлена или установлена на "C", это нормально, что вы не получите ожидаемый результат.

Редактировать: увидеть ответы наэтот вопро для эквивалента en_US.utf8 для Windows.

Hmm. Этот ответ кажется правильным. Интересно, как вы установили ваш языковой стандарт на utf8, хотя ... когда я пытаюсь это сделать, setlocale дает сбой. Документы здесь: Msdn.microsoft.com / EN-US / библиотека / x99tb11d.aspx (если вы ищете utf-8) говорит, что если вы попробуете utf-8, произойдет сбой. Может быть, это просто не работает в реализации Microsoft. Scott Langham
@ ScottLangham, названия локалей не стандартизированы, и я не знаю, что поддерживается в Windows, но я бы удивился, если бы у них не было Unicode - не обязательно UTF8 - локали. AProgrammer
Windows не поддерживает локали Unicode. Во всех реализациях кодировка wchar_t не зависит от локали, поэтому кодировка локали относится только к узкой кодировке символов. Таким образом, для локали Unicode требуется UTF-8, а Windows не предоставляет локали, использующие UTF-8. Windows поддерживает Unicode, используя UTF-16 в качестве кодировки wchar_t. bames53

Похожие вопросы