我正在尝试在Windows中实现文本支持,并打算稍后迁移到Linux平台。以统一的方式支持国际语言是理想的,但考虑到这两个平台,这似乎并不容易实现。我花了相当多的时间阅读UNICODE、UTF-8(和其他编码),widechars等,以下是我到目前为止所了解的:
作为标准,UNICODE描述了可Map的字符集以及它们出现的顺序,我将其称为“什么”:UNICODE指定将提供的 * 内容 *。
UTF-8(和其他编码)指定 * 如何 *:每个字符将如何以二进制格式表示。
现在,在windows上,他们最初选择了UCS-2编码,但这无法满足要求,所以他们使用UTF-16,必要时也可以使用多字符编码。
下面是delemma:
- Windows内部只支持UTF-16,所以如果你想支持国际字符,你必须转换成他们的widechar版本,以使用相应的操作系统调用。似乎没有任何支持调用像CreateFileA()这样的多字节UTF-8字符串,并让它看起来正确。这是正确的吗?
1.在C语言中,有一些支持多字节的函数(_mbscat,_mbscpy,etc),但是在windows上,这些函数的字符类型被定义为unsigned char*。(即没有_mbstol来将多字节串转换为长的,例如)您被迫使用运行时函数的某些char* 版本,这会导致编译器的问题,因为那些函数之间有符号/无符号类型的差异。有人甚至使用那些吗?你只是做了一大堆的铸造,以绕过错误?
1.在C中,std::string有迭代器,但是这些迭代器是基于char_type的,而不是基于码点的。因此,如果我在std::string::迭代器上执行,我得到的是下一个char_type,而不是下一个码点。类似地,如果你调用std::string::operator[],你得到的是一个char_type的引用,它很可能不是一个完整的码点。那么,如何按码点迭代std::string呢?(C有_mbsinc()函数)
4条答案
按热度按时间r6l8ljro1#
只执行UTF-8
每个平台都有很多支持UTF-8的库,也有一些是多个。正如你已经注意到的,Win32中的UTF-16 API是有限的和不一致的,所以最好保持所有的东西都是UTF-8,并在最后一刻转换为UTF-16。也有一些方便的UTF-8 Package 窗口API。
此外,在应用程序级文档中,UTF-8正越来越多地被接受为标准。每个文本处理应用程序要么接受UTF-8,要么最坏的情况是将其显示为“带有一些小字符的ASCII”,而只有少数应用程序支持UTF-16文档,而那些不支持的应用程序则将其显示为“大量的空白!”
vsikbqxv2#
1.正确。您将为Windows API调用将UTF-8转换为UTF-16。
1.大多数情况下,你会使用常规的字符串函数来处理UTF-8--
strlen
,strcpy
(ick),snprintf
,strtol
。它们可以很好地处理UTF-8字符。要么使用char *
来处理UTF-8,要么你必须强制转换所有的字符。请注意,下划线版本(如
_mbstowcs
)不是标准的,它们通常不使用下划线命名,如mbstowcs
。operator[]
的例子,我的建议是远离它。同样,迭代字符串的用法也少得惊人:参见:C++ iterate or split UTF-8 string into array of symbols?
krcsximq3#
是的,这是正确的。
*A
函数变体根据当前活动的代码页解释字符串参数(在美国和西欧的大多数计算机上是Windows-1252,但通常可以是其他代码页)并将其转换为UTF-16。有一个UTF-8代码页,但是,AFAIK没有一种方法可以通过编程方式设置活动代码页(有GetACP
可以获取活动代码页,但没有对应的SetACP
)。1.在C语言中,有一些支持多字节的函数(_mbscat,_mbscpy,etc),但是在windows上,这些函数的字符类型被定义为unsigned char *。(即没有_mbstol来将多字节串转换为长的,例如)您被迫使用运行时函数的某些char * 版本,这会导致编译器的问题,因为那些函数之间有符号/无符号类型的差异。有人甚至使用那些吗?你只是做了一大堆的铸造,以绕过错误?
根据我的经验,
mbs*
家族的函数几乎从未使用过,除了mbstowcs
、mbsrtowcs
和mbsinit
,这些函数都不是标准C。1.在C中,std::string有迭代器,但是这些迭代器是基于char_type的,而不是基于码点的。因此,如果我在std::string::迭代器上执行,我得到的是下一个char_type,而不是下一个码点。类似地,如果你调用std::string::operator [],你得到的是一个char_type的引用,它很可能不是一个完整的码点。那么,如何按码点迭代std::string呢?(C有_mbsinc()函数)
我认为
mbrtowc(3)
是解码多字节字符串的单个码位的最佳选择。总的来说,我认为跨平台Unicode兼容性的最佳策略是在内部使用单字节字符来完成UTF-8中的所有操作。当你需要调用Windows API函数时,将其转换为UTF-16,并始终调用
*W
变体。大多数非Windows平台已经使用UTF-8,因此使用它们很容易。zmeyuzjn4#
在Windows中,可以调用
WideCharToMultiByte
和MultiByteToWideChar
在UTF-8字符串和UTF-16字符串之间进行转换(Windows中为wstring)。由于Windows API不使用UTF-8,因此无论何时调用任何支持Unicode的Windows API函数,都必须将string转换为wstring(Windows版本的Unicode在UTF-16中)。当你从Windows获得输出时,你必须将UTF-16转换回UTF-8。Linux内部使用UTF-8,所以你不需要这样的转换。为了让你的代码移植到Linux,坚持使用UTF-8,并提供如下转换:要迭代utf8字符串,需要两个基本函数:一个用于计算utf8字符的字节数,另一个用于确定该字节是否为utf8字符序列的前导字节。以下代码提供了一种非常有效的测试方法:
使用这些函数,在utf8字符串上实现自己的迭代器应该不难,一个是用于前向迭代器,另一个是用于后向迭代器。