Проблема WideCharToMultiByte - PullRequest
       23

Проблема WideCharToMultiByte

1 голос
/ 30 июля 2010

У меня есть прекрасные функции из моего предыдущего вопроса , которые отлично работают, если я сделаю это:

wstring temp;
wcin >> temp;

string whatever( toUTF8(getSomeWString()) );

// store whatever, copy, but do not use it as UTF8 (see below)

wcout << toUTF16(whatever) << endl;

Оригинальная форма воспроизводится, но промежуточная форма часто содержит дополнительные символы. Если я введу, например, àçé в качестве ввода и добавлю оператор cout << whatever, я получу ┬à┬ç┬é в качестве вывода.

Могу ли я по-прежнему использовать эту строку для сравнения с другими, полученными из источника ASCII? Или по-другому спросить: если бы я вывел ┬à┬ç┬é через cout UTF8 в linux, он читал бы àçé? Является ли байтовое содержимое строки àçé, прочитанной в UTF8 linux cin, точно таким же, как то, что получает Win32 API?

Спасибо!

PS: я спрашиваю, потому что мне нужно много использовать строку для сравнения с другими значениями чтения (сравнение и объединение ...).

Ответы [ 2 ]

5 голосов
/ 30 июля 2010

Давайте начнем с того, что мне кажется, что существует просто нет способа вывода текста UTF-8 на консоль в Windows через cout (при условии, что вы компилируете с Visual Studio). Однако, что вы можете сделать для своих тестов, это вывести текст UTF-8 через Win32 API fn WriteConsoleA:

if(!SetConsoleOutputCP(CP_UTF8)) { // 65001
    cerr << "Failed to set console output mode!\n";
    return 1;
}
HANDLE const consout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD nNumberOfCharsWritten;
const char* utf8 = "Umlaut AE = \xC3\x84 / ue = \xC3\xBC \n";
if(!WriteConsoleA(consout, utf8, strlen(utf8), &nNumberOfCharsWritten, NULL)) {
    DWORD const err = GetLastError();
    cerr << "WriteConsole failed with << " << err << "!\n";
    return 1;
}

Это должно вывести: Umlaut AE = Ä / ue = ü если вы настроили консоль (cmd.exe) на использование шрифта Lucida Console.

Что касается вашего вопроса (взято из вашего комментария), если

Преобразованная строка Win23 API - это такой же как необработанная строка UTF8 (linux)

Я скажу да: учитывая последовательность символов Unicode, это представление UTF-16 (Windows wchar_t), преобразованное в представление UTF-8 (char) с помощью функции WideCharToMultiByte, всегда будет приводить к одной и той же последовательности байтов.

1 голос
/ 30 июля 2010

Когда вы преобразуете строку в UTF 16, это 16-байтовый широкий символ, вы не можете сравнить его со значениями ASCII, потому что они не являются 16-байтовыми значениями. Вы должны преобразовать их для сравнения или написать специальное сравнение для функции ASCII.

Я сомневаюсь, что cout UTF8 в linux будет выдавать тот же правильный вывод, если только это не будут обычные значения ASCII, поскольку формы кодирования UTF8 UTF-8 двоично совместимы с ASCII для кодовых точек ниже 128, и предположим, что UTF16 идет после UTF8 подобным образом.

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

...