我一直在试验一个自定义字符串对象(struct),如下所示:
typedef struct
{
int encoding;
int length;
character * array;
} EncodedString;
我的想法是,通过指定编码,我可以制作一些使用该编码正确打印字符串的函数,即ASCII或utf-8或utf-16等。(请原谅我的字符编码无知。)< / p>
现在,我正打算打印出一个(普通话)汉字:狗(0x72d7)。我想也许是通过逐个字符打印它,它会正常工作,但显然不是。它打印只是“r?” (分别为0x72和0xd7)。那么如何修改这个程序以便它打印出角色?
#include <stdio.h>
typedef unsigned char character;
typedef struct
{
int encoding;
int length;
character * array;
} EncodedString;
void printString(EncodedString str);
int main(void)
{
character doginmandarin[] = {0x72U, 0xd7U};
EncodedString mystring = {0, sizeof doginmandarin, doginmandarin};
printString(mystring);
printf("\n");
return 0;
}
void printString(EncodedString str) // <--- where I try to print the character
{
int i;
for(i = 0; i < str.length; i++)
{
printf("%c", str.array[i]);
}
}
理想情况下,我更喜欢包含字符的数组只包含无符号字符,这意味着将构成字符狗的两个字节分开。虽然它现在没有任何用途,但我们的想法是使用encoding
结构的EncodedString
字段来确定每个字符的字节数。
如何用最少量的黑客来实现?
答案 0 :(得分:3)
您应该查看与宽字符(wchar_t)和多字节字符串有关的c库函数。 Linux上的c-library实现(或者据我所知的windows)与unicode兼容。 (如果你需要在你的微控制器板上使用它,你可能会运气不好)。大多数处理utf-8编码和unicode的东西都已存在,所以你不需要自己动手。 这是一个如何处理一个角色的例子:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
int main ()
{
/*
* use an utf-8 compatible locale.
*/
setlocale (LC_ALL, "en_US.utf8");
const wchar_t dog = 0x72d7;
/*
* wchar_t strings can contain any character. Create one
* string containing only the dog.
*/
wchar_t in[2] = { dog, 0 };
char out[100];
/*
* convert to a multibyte string, returns the number of chars.
*/
size_t len = wcstombs (out, in, sizeof out);
printf ("the character '%lc' is %zd bytes (string: '%s')\n", dog, len, out);
}
输出:
$ ./a.out
the character '狗' is 3 bytes (string: '狗')
答案 1 :(得分:1)
数字Ox72d7
是您要打印的字符的Unicode代码点(摘要编号)。当在内存中用两个字节0x72, 0xd7
表示时,它就成为该字符的UCS-2代码,它也恰好是它的UTF-16编码。但是您的终端可能期望UTF-8编码字符。代码点Ox72d7
的正确UTF-8编码为0xe7, 0x8b, 0x97
。
您可以修复代码以使用UTF-8编码字符,但这种编码对于内存表示非常不切实际,因为它会为不同的字符生成不同数量的字节。这使得简单的字符串操作比如使第n个字符非常复杂。相反,经常使用固定长度的表示。例如,UCS-2每个字符总是使用两个字节。然后,在打印字符串之前,尽可能晚地完成到外部表示编码的转换。
编辑(来自评论)
UTF-8是一种棘手的编码。从代码点到UTF-8字节的映射并不简单,涉及一些按位的mumbo-jumbo。它是一种霍夫曼代码,不同的前缀表示字符占用的字节数。此外,所有后续字节都以0b10开头,以便检测格式错误的UTF-8。这里描述了:http://en.wikipedia.org/wiki/UTF-8#Description
为了快速找到我的帖子的三个字节,我只需在python控制台中输入:u"\u72d7".encode('UTF-8')