Проблема WideCharToMultiByte
У меня есть прекрасные функции из моего предыдущего вопроса, которые прекрасно работают, если я делаю это:
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? Или спросили иначе: если бы я вывел ┬à┬ç┬é
через UTF8 Cout в Linux, будет ли это читать àçé
? Содержимое байта строки àçé
, читайте в UTF8 linux cin, точно так же, как то, что получает Win32 API?
Спасибо!
PS: причина, по которой я спрашиваю, заключается в том, что мне нужно много использовать строку для сравнения с другими значениями чтения (сравнение и объединение...).
2 ответа
Давайте начнем с того, что я говорю, что кажется, что просто нет способа вывести текст 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
Функция всегда будет выдавать одну и ту же последовательность байтов.
Когда вы преобразуете строку в UTF 16, это 16-байтовый широкий символ, вы не можете сравнить его со значениями ASCII, потому что они не являются 16-байтовыми значениями. Вы должны преобразовать их для сравнения или написать специальное сравнение для функции ASCII.
Я сомневаюсь, что Cout UTF8 в linux будет производить тот же правильный вывод, если только это не будут обычные значения ASCII, поскольку формы кодирования UTF-8 UTF8 двоично-совместимы с ASCII для кодовых точек ниже 128, и я предполагаю, что UTF16 следует после UTF8 аналогичным образом,
Хорошей новостью является то, что существует много конвертеров, написанных для преобразования этих строк в различные наборы символов.