我在C ++中阅读了一些关于字符串和字符编码的最佳实践的帖子,但我在寻找一种在我看来相当简单和正确的通用方法时遇到了一些困难。我可以就以下内容征求意见吗?我倾向于使用UTF-8和UTF-32,并定义类似于:
typedef std::string string8;
typedef std::basic_string<uint32_t> string32;
string8类将用于UTF-8,并且具有单独的类型只是对编码的提醒。另一种方法是将string8作为std :: string的子类,并删除那些不太适合UTF-8的方法。
当需要固定字符大小时,string32类将用于UTF-32。
UTF-8 CPP函数utf8 :: utf8to32()和utf8 :: utf32to8(),或甚至更简单的包装函数,将用于在两者之间进行转换。
如果你打算只传递字符串并且从不检查它们,你可以使用plain std::string
虽然这是一个穷人的工作。
问题是,大多数框架,甚至标准,都在内存中愚蠢地(我认为)强制编码。我说愚蠢,因为编码应该只对接口有影响,而那些编码不适合内存中的数据操作。
此外,编码很容易(它是一个简单的转置CodePoint - >字节和反向),而主要的困难实际上是操纵数据。
对于8位或16位,您可能会在中间切割字符,因为两者都没有 std::string
也不 std::wstring
知道Unicode字符是什么。更糟糕的是,即使使用32位编码,也存在将字符与适用于它的变音符号分开的风险,这也是愚蠢的。
因此,就标准而言,Unicode在C ++中的支持非常低。
如果您真的希望操作Unicode字符串,则需要一个支持Unicode的容器。通常的方法是使用 ICU
库,虽然它的界面真的是C-ish。但是,您将获得使用多种语言实际使用Unicode所需的一切。
所描述的特征方法 这里 可能会有所帮助。这是一种古老但有用的技术。
没有指定必须为字符串,wstring等使用什么字符编码。常见的方法是在宽字符串中使用unicode。应使用哪些类型和编码取决于您的要求。
如果您只需要将数据从A传递给B,请选择带有UTF-8编码的std :: string(不要引入新类型,只需使用std :: string)。如果必须使用字符串(extract,concat,sort,...),请选择std :: wstring,并在Windows上编码UCS2 / UTF-16(仅限BMP),在Linux上编辑UCS4 / UTF-32。
好处是固定大小:每个字符的大小为2(或UCS4为4)字节,而带UTF-8的std :: string返回错误的length()结果。
对于转换,您可以检查sizeof(std :: wstring :: value_type)== 2或4以选择UCS2或UCS4。我正在使用ICU库,但可能有简单的包装器库。
建议不要使用std :: string派生,因为basic_string不是为(缺少虚拟成员等)而设计的。如果你真的真的需要你自己的类型,比如std :: basic_string <my_char_type>为此写一个自定义的专门化。
新的C ++ 0x标准将wstring_convert <>和wbuffer_convert <>定义为使用std :: codecvt从窄字符集转换为宽字符集(例如UTF-8到UCS2)。
Visual Studio 2010已经实现了这个,afaik。