Как проверить, имеет ли строка действительные символы UTF-8 в C ++? - PullRequest
3 голосов
/ 03 марта 2012

Я пытаюсь использовать библиотеки ICU , чтобы проверить, содержит ли строка недопустимые символы UTF-8. Я создал конвертер UTF-8, но никакие неверные данные не дают мне ошибки при конвертации. Ценю вашу помощь.

Спасибо, Prashanth

int main()                                                                                        
{                                     
    string str ("AP1120 CorNet-IP v5.0 v5.0.1.22 òÀ MIB 1.5.3.50 Profile EN-C5000");
    //  string str ("example string here");
    //  string str (" ����������"     );                  
    UErrorCode status = U_ZERO_ERROR;                   
    UConverter *cnv;            
    const char *sourceLimit;    
    const char * source = str.c_str();                  
    cnv = ucnv_open("utf-8", &status);                                                              
    assert(U_SUCCESS(status));                                                                      

    UChar *target;                                                                                  
    int sourceLength = str.length();                                                                
    int targetLimit = 2 * sourceLength;                                                             
    target = new UChar[targetLimit];                                                                

    ucnv_toUChars(cnv, target, targetLimit, source, sourceLength, &status);
    cout << u_errorName(status) << endl;
    assert(U_SUCCESS(status));                          
}       

1 Ответ

4 голосов
/ 03 марта 2012

Я изменил вашу программу, чтобы распечатать фактические строки, до и после:

#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.

Однако операция преобразования по-прежнему возвращает состояние «успех».Похоже, что библиотека не считает ошибку преобразования пользовательских данных ошибкой вызова функции.Скорее всего, состояние ошибки зарезервировано для таких вещей, как нехватка места.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...