символ против wchar_t - PullRequest
       28

символ против wchar_t

7 голосов
/ 21 сентября 2011

Я пытаюсь распечатать строку wchar_t *.Код идет ниже:

#include <stdio.h>
#include <string.h>
#include <wchar.h>

char *ascii_ = "中日友好";  //line-1
wchar_t *wchar_ = L"中日友好";  //line-2

int main()
{
    printf("ascii_: %s\n", ascii_);  //line-3
    wprintf(L"wchar_: %s\n", wchar_);  //line-4
    return 0;
}

//Output
ascii_: 中日友好

Вопрос:

  1. Очевидно, я не должен назначать символы CJK указателю char * в строке-1, ноЯ только что сделал это, и вывод строки-3 правильный, так почему?Как printf () в строке 3 может дать мне символы не ascii?Знает ли он кодировку как-нибудь?

  2. Я предполагаю, что код в строке-2 и строке-4 верен, но почему я не получил никакого вывода строки-4?

Ответы [ 3 ]

8 голосов
/ 21 сентября 2011

Прежде всего, обычно не очень хорошая идея использовать не-ascii символы в исходном коде.Вероятно, происходит то, что китайские символы кодируются как UTF-8, который работает с ascii.

Теперь о том, почему wprintf() не работает.Это связано с ориентацией потока.Каждый поток может быть установлен только на нормальный или широкий.После установки его нельзя изменить.Устанавливается при первом использовании.(что связано с printf).После этого wprintf не будет работать из-за неправильной ориентации.

Другими словами, если вы используете printf(), вам нужно продолжать использовать printf().Точно так же, если вы начинаете с wprintf(), вам нужно продолжать использовать wprintf().

Вы не можете смешивать printf() и wprintf().(кроме Windows)

EDIT:

Чтобы ответить на вопрос о том, почему строка wprintf не работает даже сама по себе.Вероятно, это потому, что код компилируется так, что формат UTF-8 中日友好 сохраняется в wchar_.Однако для wchar_t требуется 4-байтовое кодирование Unicode.(2 байта в Windows)

Итак, я могу придумать два варианта:

  1. Не беспокойтесь о wchar_t, а просто придерживайтесь многобайтовых char s.Это простой способ, но он может сломаться, если система пользователя не настроена на китайский язык.
  2. Используйте wchar_t, но вам нужно будет кодировать китайские символы, используя escape-последовательности Юникода.Это, очевидно, сделает его нечитаемым в исходном коде, но оно будет работать на любом компьютере, который может печатать шрифты китайских символов независимо от локали.
6 голосов
/ 21 сентября 2011

Строка 1 не ascii, это какая-то многобайтовая кодировка, используемая вашим компилятором во время компиляции. На современных системах это, вероятно, UTF-8. printf не знает кодировку. Это просто отправка байтов на стандартный вывод, и, если кодировки совпадают, все в порядке.

Одна проблема, о которой вы должны знать, это то, что строки 3 и 4 вместе вызывают неопределенное поведение. Вы не можете смешивать основанные на символах и широкие символы на одном и том же FILE (stdout). После первой операции FILE имеет «ориентацию» (байтовую или широкую), и после этого любая попытка выполнить операции противоположной ориентации приводит к UB.

1 голос
/ 21 сентября 2011

Вы пропускаете один шаг и поэтому думаете, что ошиблись.

У вас есть файл C на диске, содержащий байты. У вас есть строка "ASCII" и широкая строка.

Строка ASCII берет байты точно так же, как они находятся в строке 1, и выводит их. Это работает, если кодировка на стороне пользователя такая же, как и на стороне программиста.

Широкая строка сначала декодирует данные байты в кодовые точки Unicode и сохраняется в программе - возможно, это пойдет не так с вашей стороны. На выходе они снова кодируются в соответствии с кодировкой на стороне пользователя. Это гарантирует, что эти символы выводятся так, как они предназначены, а не как они введены.

Либо ваш компилятор использует неправильную кодировку, либо выходной терминал настроен неправильно.

...