Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C编程:如何为Unicode编程?_C_Unicode_Utf 8_Character Encoding_Locale - Fatal编程技术网

C编程:如何为Unicode编程?

C编程:如何为Unicode编程?,c,unicode,utf-8,character-encoding,locale,C,Unicode,Utf 8,Character Encoding,Locale,进行严格的Unicode编程需要哪些先决条件 这是否意味着我的代码不应该在任何地方使用char类型,并且需要使用能够处理wint和wchar\t的函数 在这种情况下,多字节字符序列扮演什么角色 要执行严格的Unicode编程: 仅使用支持Unicode的字符串API(不是strlen,strcpy,…而是它们的宽字符串对应项wstrlen,wsstrcpy,…) 在处理文本块时,使用允许存储Unicode字符(utf-7、utf-8、utf-16、ucs-2等)而不会丢失的编码 检查操作系统默

进行严格的Unicode编程需要哪些先决条件

这是否意味着我的代码不应该在任何地方使用
char
类型,并且需要使用能够处理
wint
wchar\t
的函数


在这种情况下,多字节字符序列扮演什么角色

要执行严格的Unicode编程:

  • 仅使用支持Unicode的字符串API(不是
    strlen
    strcpy
    ,…而是它们的宽字符串对应项
    wstrlen
    wsstrcpy
    ,…)
  • 在处理文本块时,使用允许存储Unicode字符(utf-7、utf-8、utf-16、ucs-2等)而不会丢失的编码
  • 检查操作系统默认字符集是否与Unicode兼容(例如:utf-8)
  • 使用Unicode兼容的字体(例如arial_Unicode)
多字节字符序列是一种早于UTF-16编码(通常与
wchar\u t
一起使用)的编码,在我看来,它只是一种Windows编码


我从未听说过wint\t

请注意,这不是关于“严格的unicode编程”本身,而是一些实践经验

我们公司所做的是围绕IBM的ICU库创建一个包装库。包装器库有一个UTF-8接口,并在需要调用ICU时转换为UTF-16。在我们的例子中,我们并不太担心性能问题。当性能成为问题时,我们还提供UTF-16接口(使用我们自己的数据类型)

应用程序可以保持原样(使用char),尽管在某些情况下它们需要知道某些问题。例如,我们使用一个包装器代替strncpy(),它可以避免切断UTF-8序列。在我们的情况下,这是足够的,但也可以考虑合并字符的检查。我们也有包装器来计算代码点的数量,图形的数量,等等

当与其他系统接口时,我们有时需要自定义字符组合,因此您可能需要一些灵活性(取决于您的应用程序)


我们不使用wchar\t。使用ICU可以避免在可移植性方面出现意外问题(当然不是其他意外问题:-)。

据我所知,wchar\u t依赖于实现(从这里可以看出)。而且它不是unicode

您基本上希望将内存中的字符串处理为
wchar\u t
数组,而不是char。当您执行任何类型的I/O(如读取/写入文件)时,您可以使用UTF-8(这可能是最常见的编码)进行编码/解码,这非常简单,可以实现。只需谷歌搜索RFC。所以在内存中,没有任何内容应该是多字节的。一个
wchar\u t
表示一个字符。然而,在进行序列化时,需要将某些字符编码为UTF-8,其中一些字符由多个字节表示

您还必须为宽字符串编写新版本的strcmp,但这不是一个大问题。最大的问题是与只接受字符数组的库/现有代码的互操作

当涉及到
sizeof(wchar\u t)
(如果你想做得好,你需要4个字节)时,如果需要,你可以使用
typedef
/
hacks将其重新定义为更大的大小。

C99或更早版本 C标准(C99)提供了宽字符和多字节字符,但由于无法保证这些宽字符可以容纳什么,因此它们的值有些有限。对于给定的实现,它们提供了有用的支持,但如果您的代码必须能够在实现之间移动,则无法保证它们会有用

因此,Hans van Eck建议的方法(即围绕ICU-International Components for Unicode-library编写包装器)是合理的,IMO

UTF-8编码有许多优点,其中一个优点是,如果不弄乱数据(例如,通过截断数据),那么它可以被不完全了解UTF-8编码复杂性的函数复制。这绝对不是
wchar\u t
的情况

完整的Unicode是一种21位格式。也就是说,Unicode保留从U+0000到U+10FFFF的代码点

UTF-8、UTF-16和UTF-32格式(其中UTF代表Unicode转换格式-请参阅)的一个有用之处是,您可以在三种表示形式之间进行转换,而不会丢失信息。每个人都可以代表其他人可以代表的任何东西。UTF-8和UTF-16都是多字节格式

众所周知,UTF-8是一种多字节格式,其结构严谨,可以可靠地找到字符串中字符的开头,从字符串中的任何一点开始。单字节字符的高位设置为零。多字节字符的第一个字符以位模式110、1110或11110中的一个开始(对于2字节、3字节或4字节字符),后续字节始终以10开始。连续字符始终在0x80范围内。。0xBF。有一些规则规定UTF-8字符必须以尽可能最小的格式表示。这些规则的一个结果是,字节0xC0和0xC1(也是0xF5..0xFF)不能出现在有效的UTF-8数据中

 U+0000 ..   U+007F  1 byte   0xxx xxxx
 U+0080 ..   U+07FF  2 bytes  110x xxxx   10xx xxxx
 U+0800 ..   U+FFFF  3 bytes  1110 xxxx   10xx xxxx   10xx xxxx
U+10000 .. U+10FFFF  4 bytes  1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx
最初,人们希望Unicode是一个16位的代码集,所有东西都能放入16位的代码空间。不幸的是,现实世界更加复杂,必须扩展到当前的21位编码

因此,UTF-16是“基本多语言平面”的单单位(16位字)代码集,表示Unicode代码点为U+0000的字符。。U+FFFF,但对超出此范围的字符使用两个单位(32位)。所以,使用UTF-16编码的代码必须能够处理可变宽度编码,就像UTF-8必须处理的一样。双重密码-
char16_t
char32_t
typedef char UTF8; // for code units of UTF-8 strings
typedef unsigned char BYTE; // for binary data
#include <windows.h>

typedef unsigned char utf8_t;
typedef unsigned short utf16_t;
typedef unsigned long utf32_t;

int main ( int argc, char *argv[] )
{
  int msgBoxId;
  utf16_t lpText[] = { 0x03B1, 0x0009, 0x03B2, 0x0009, 0x03B3, 0x0009, 0x03B4, 0x0000 };
  utf16_t lpCaption[] = L"Greek Characters";
  unsigned int uType = MB_OK;
  msgBoxId = MessageBoxW( NULL, lpText, lpCaption, uType );
  return 0;
}