从char *创建UTF-16字符串

时间:2013-03-16 12:49:53

标签: c++ character-encoding char utf-16

所以我有标准的C字符串:

char* name = "Jakub";

我想将其转换为UTF-16。我发现,UTF-16将两倍 - 一个角色需要两个字符。
所以我创建了另一个字符串:

char name_utf_16[10];  //"Jakub" is 5 characters

现在,我相信使用ASCII字符时我只会使用较低的字节,因此对于所有这些字符,74 00就像J一样,依此类推。有了这个信念,我就可以制作这样的代码:

void charToUtf16(char* input, char* output, int length) {
    /*Todo: how to check if output is long enough?*/
    for(int i=0; i<length; i+=2)  //Step over 2 bytes
    {
        //Lets use little-endian - smallest bytes first
        output[i] = input[i];
        output[i+1] = 0;  //We will never have any data for this field
    }
}

但是,通过这个过程,我以"Jkb"结束了。我知道无法正确测试 - 我只是将字符串发送到Minecraft Bukkit Server。这就是断开连接时的说法:

  

13:34:19 [INFO]断开 jkb ?? [/127.0.0.1:53215]:过时的服务器!

注意:我知道Minecraft使用big-endian。上面的代码只是一个例子,事实上,我已经在课堂上实现了我的转换。

3 个答案:

答案 0 :(得分:5)

为什么要在现有的C / C ++函数中创建自己的Unicode转换功能,例如mbstowcs()中包含的<cstdlib>

如果您仍想制作自己的东西,请查看Unicode Consortium的开源代码,可在此处找到:

Convert UTF-16 to UTF-8 under Windows and Linux, in C

答案 1 :(得分:3)

在我回答你的问题之前,请考虑一下:

这个编程领域充满了人类陷阱。理解ASCII,UTF7 / 8和ANSI /'MultiByte字符串(MBCS)之间的差异是很有意义的,所有这些对于说英语的程序员来说都会看起来和感觉完全一样,但如果他们是介绍给欧洲或亚洲用户。

ASCII:字符在32-127范围内。只有一个字节。线索就在名称中,它们对美国人来说很好,但在世界其他地方却不适合。

ANSI / MBCS:这就是'代码页'的原因。字符32-127与ASCII相同,但是可以在128-255范围内使用字符以及其他字符,并且128-255范围中的一些可以用作标记字符继续的标记进入第二,第三或甚至第四个字节。要正确处理字符串,您需要字符串字节和正确的代码页。如果您尝试使用错误的代码页处理字符串,则不会使用正确的字符,并且会误解字符是一个字符,两个字符还是四字节字符。

UTF7 / 8:这些是21位unicode字符点的8位宽格式。在UTF-7和UTF-8中,unicode字符长度可以在1到4个字节之间。 UTF编码优于ANSI / MBCS的优点是代码页不会引起歧义。每个脚本中的每个字形都有一个唯一的unicode代码点,这意味着不可能通过解释具有不同区域设置的其他计算机上的数据来破坏字符集。

所以要开始回答你的问题:

  1. 虽然您假设您的char *仅指向ASCII字符串,这是一个非常危险的选择,但用户可以控制输入的数据,而不是程序员。 Windows程序默认将其存储为MBCS。

  2. 您要做的第二个假设是UTF-16编码的大小是8位编码的两倍。这通常不是一个安全的假设。根据源编码,UTF-16编码可能是两倍大小,可能小于两倍大小,而在极端情况下,实际上可能长度较短。

  3. 那么,什么是安全的解决方案?

    安全选项是在内部以unicode实现您的应用程序。在Windows上,这是一个编译器选项,然后意味着您的Windows控件都使用wchar_t *字符串作为其数据类型。在linux上我不太确定你总能使用自杀图形和操作系统库。您还必须使用wcslen()函数来获取字符串的长度等。当您与外部世界交互时,请准确使用所使用的字符编码。

    要回答您的问题,请将问题更改为,当我收到非UTF-16数据时该怎么办?

    首先,要非常清楚你对它的格式有什么假设吗?其次,接受这样一个事实,即有时转换为UTF-16可能会失败。

    如果你清楚源格式,你可以选择适当的win32或stl转换器来转换格式,然后你应该在使用结果之前查找转换失败的证据。例如Windows上的mbstowcs或MultiByteToWideChar()。但是,安全地使用这两种方法意味着您需要了解上述所有答案。

    所有其他选择都会带来风险。使用mbcs字符串,您将通过使用一个代码页输入数据字符串,并使用不同的代码页进行处理。假设ASCII数据,当你遇到一个非ascii字符时,你的代码就会破坏,你会“责怪”用户的缺点。

答案 2 :(得分:-2)

output[i] = input[i];

这将分配输入的每个其他字节,因为您将i增加2.所以难怪您获得"Jkb"。 你可能想写:

output[i] = input[i / 2];