Я изменил вашу программу, чтобы распечатать фактические строки, до и после:
#include <unicode/ucnv.h>
#include <string>
#include <iostream>
#include <cassert>
#include <cstdio>
int main()
{
std::string str("22 òÀ MIB 1");
UErrorCode status = U_ZERO_ERROR;
UConverter * const cnv = ucnv_open("utf-8", &status);
assert(U_SUCCESS(status));
int targetLimit = 2 * str.size();
UChar *target = new UChar[targetLimit];
ucnv_toUChars(cnv, target, targetLimit, str.c_str(), -1, &status);
for (unsigned int i = 0; i != targetLimit && target[i] != 0; ++i)
std::printf("0x%04X ", target[i]);
std::cout << std::endl;
for (char c : str)
std::printf("0x%02X ", static_cast<unsigned char>(c));
std::cout << std::endl << "Status: " << status << std::endl;
}
Теперь, с настройками компилятора по умолчанию, я получаю:
0x0032 0x0032 0x0020 0x00F2 0x00C0 0x0020 0x004D 0x0049 0x0042 0x0020 0x0031
0x32 0x32 0x20 0xC3 0xB2 0xC3 0x80 0x20 0x4D 0x49 0x42 0x20 0x31
То естьвход уже UTF-8 .Это заговор моего редактора, который сохранил файл в UTF-8 (проверяется в шестнадцатеричном редакторе), и GCC, который устанавливает набор символов выполнения в UTF-8.
Выможет заставить GCC изменить эти параметры.Например, принудительное выполнение символа выполнения ISO-8859-1 (через -fexec-charset=iso-8859-1
) приводит к следующему:
0x0032 0x0032 0x0020 0xFFFD 0xFFFD 0x0020 0x004D 0x0049 0x0042 0x0020 0x0031
0x32 0x32 0x20 0xF2 0xC0 0x20 0x4D 0x49 0x42 0x20 0x31
Как вы можете видеть, ввод теперь кодирован по ISO-8859-1, изапрос преобразования завершается с ошибкой и создает кодовые точки «недопустимых символов» U + FFFD.
Однако операция преобразования по-прежнему возвращает состояние «успех».Похоже, что библиотека не считает ошибку преобразования пользовательских данных ошибкой вызова функции.Скорее всего, состояние ошибки зарезервировано для таких вещей, как нехватка места.