c ++检查字符串是否有有效的utf-8字符

时间:2012-03-02 20:06:41

标签: c++ utf-8

我正在尝试使用ICU库来测试字符串是否包含无效的UTF-8字符。我创建了一个utf-8转换器,但没有无效数据给我转换错误。感谢您的帮助。

谢谢, 普拉香特

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 个答案:

答案 0 :(得分:4)

我修改了你的程序,打印出之前和之后的实际字符串:

#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(可在十六进制编辑器中验证),以及将执行字符集设置为UTF-8的GCC。

您可以强制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。

但是,转换操作仍会返回“成功”状态。看来该库不会将用户数据转换错误视为函数调用的错误。相反,错误状态似乎保留用于空间不足等事情。

相关问题