用C语言在终端中打印多字节字符
我一直在试验一个自定义字符串对象(struct),它看起来像这样:用C语言在终端中打印多字节字符,c,encoding,utf-8,terminal,C,Encoding,Utf 8,Terminal,我一直在试验一个自定义字符串对象(struct),它看起来像这样: typedef struct { int encoding; int length; character * array; } EncodedString; 其思想是,通过指定编码,我可以生成一些使用该编码正确打印字符串的函数,即ASCII或utf-8或utf-16等(请原谅我对字符编码的无知) 现在,我正在尝试打印一个(普通话)汉字:狗 (0x72d7)。我想也许通过逐字打印,它会正常工作,但显然不行
typedef struct
{
int encoding;
int length;
character * array;
} EncodedString;
其思想是,通过指定编码,我可以生成一些使用该编码正确打印字符串的函数,即ASCII或utf-8或utf-16等(请原谅我对字符编码的无知)
现在,我正在尝试打印一个(普通话)汉字:狗 (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]);
}
}
#包括
typedef无符号字符;
类型定义结构
{
整数编码;
整数长度;
字符*数组;
}编码字符串;
无效打印字符串(EncodedString str);
内部主(空)
{
字符doginmandarin[]={0x72U,0xd7U};
EncodedString mystring={0,doginmandarin的大小,doginmandarin};
printString(mystring);
printf(“\n”);
返回0;
}
void printString(EncodedString str)//数字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字节的映射并不简单,它涉及到一些按位的混乱。这是一种哈夫曼代码,不同的前缀告诉字符将占用多少字节。此外,以下所有字节均以0b10开头,以检测格式错误的UTF-8。这里描述的是:
为了快速找到我的帖子的三个字节,我在python控制台中键入了以下内容:u“\u72d7”。encode('UTF-8')
数字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字节的映射并不简单,它涉及到一些按位的混乱。这是一种哈夫曼代码,不同的前缀告诉字符将占用多少字节。此外,以下所有字节均以0b10开头,以检测格式错误的UTF-8。这里描述的是:
为了快速找到我的文章中的三个字节,我在python控制台中键入了以下内容:u“\u72d7”。encode('UTF-8')
您可能应该研究与宽字符(wchar\u t)和多字节字符串相关的c库函数。linux(或据我所知的windows)上的c库实现与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);
}
您可能应该研究与宽字符(wchar\u t)和多字节字符串有关的c库函数。linux(或据我所知的windows)上的c库实现与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);
}
谢谢相反,使用这三个数字起了作用。因此,第一个,0xe7
告诉处理终端i/o的任何进程,以下两个数字(不确定正确的单词)代表一个代码点?另外,您是如何发现这三个数字的?它们似乎与0x72d7有些不相关。UTF-8是一种复杂的编码。从代码点到UTF-8字节的映射并不简单,它涉及到一些按位的混乱。这是一种哈夫曼代码,不同的前缀告诉字符将占用多少字节。此外,以下所有字节均以0b10开头,以检测格式错误的UTF-8。这里是这样描述的:为了快速找到我文章的三个字节,我在python控制台中键入了:u“\u72d7”。encode('UTF-8')
谢谢!相反,使用这三个数字起了作用。因此,第一个,0xe7
告诉处理终端i/o的任何进程,以下两个数字(不确定正确的单词)代表一个单独的cod