凌的博客

您现在的位置是: 首页 > 学无止境 > C# > 

C#

ANSI 与 Unicode

2019-10-06 C# 1203

Unicode     :宽字节字符集  



     1. 如何取得一个既包含单字节字符又包含双字节字符的字符串的字符个数? 

    可以调用Microsoft     Visual     C++的运行期库包含函数_mbslen来操作多字节(既包括单字节也包括双字节)字符串。 

    调用strlen函数,无法真正了解字符串中究竟有多少字符,它只能告诉你到达结尾的0之前有多少个字节。 



     2. 如何对DBCS(双字节字符集)字符串进行操作? 

    函数 描述 

    PTSTR     CharNext     (     LPCTSTR     ); 返回字符串中下一个字符的地址 

    PTSTR     CharPrev     (     LPCTSTR,     LPCTSTR     ); 返回字符串中上一个字符的地址 

    BOOL     IsDBCSLeadByte(     BYTE     ); 如果该字节是DBCS字符的第一个字节,则返回非0值  



     3. 为什么要使用Unicode? 

    (1) 可以很容易地在不同语言之间进行数据交换。 

    (2) 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。 

    (3) 提高应用程序的运行效率。 

    Windows     2000是使用Unicode从头进行开发的,如果调用任何一个Windows函数并给它传递一个ANSI字符串,那么系统首先要将字符串转换成Unicode,然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序,就能够使你的应用程序更加有效地运行。 

    Windows     CE     本身就是使用Unicode的一种操作系统,完全不支持ANSI     Windows函数 

    Windows     98     只支持ANSI,只能为ANSI开发应用程序。 

    Microsoft公司将COM从16位Windows转换成Win32时,公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。  



     4. 如何编写Unicode源代码? 

    Microsoft公司为Unicode设计了WindowsAPI,这样,可以尽量减少代码的影响。实际上,可以编写单个源代码文件,以便使用或者不使用Unicode来对它进行编译。只需要定义两个宏(UNICODE和_UNICODE),就可以修改然后重新编译该源文件。 

    _UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件。当编译源代码模块时,通常必须同时定义这两个宏。  



     5. Windows定义的Unicode数据类型有哪些? 

    数据类型 说明 

    WCHAR Unicode字符 

    PWSTR 指向Unicode字符串的指针 

    PCWSTR 指向一个恒定的Unicode字符串的指针 

    对应的ANSI数据类型为CHAR,LPSTR和LPCSTR。 

    ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR。


  

     6. 如何对Unicode进行操作? 

    字符集 特性 实例 

    ANSI 操作函数以str开头 strcpy 

    Unicode 操作函数以wcs开头 wcscpy 

    MBCS 操作函数以_mbs开头 _mbscpy 

    ANSI/Unicode 操作函数以_tcs开头 _tcscpy(C运行期库) 

    ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数) 

    所有新的和未过时的函数在Windows2000中都同时拥有ANSI和Unicode两个版本。ANSI版本函数结尾以A表示;Unicode版本函数结尾以W表示。Windows会如下定义: 

    #ifdef       UNICODE 

    #define       CreateWindowEx       CreateWindowExW 

    #else 

    #define       CreateWindowEx       CreateWindowExA 

    #endif         //     !UNICODE  



     7. 如何表示Unicode字符串常量? 

    字符集 实例 

    ANSI “string” 

    Unicode L“string” 

    ANSI/Unicode T(“string”)或_TEXT(“string”)if(     szError[0]     ==     _TEXT(‘J’)     ){     } 



     8. 为什么应当尽量使用操作系统函数? 

    这将有助于稍稍提高应用程序的运行性能,因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程Explorer.exe所使用。由于这些函数使用得很多,因此,在应用程序运行时,它们可能已经被装入RAM。 

    如:StrCat,StrChr,StrCmp和StrCpy等。 



     9. 如何编写符合ANSI和Unicode的应用程序? 

    (1) 将文本串视为字符数组,而不是chars数组或字节数组。 

    (2) 将通用数据类型(如TCHAR和PTSTR)用于文本字符和字符串。 

    (3) 将显式数据类型(如BYTE和PBYTE)用于字节、字节指针和数据缓存。 

    (4) 将TEXT宏用于原义字符和字符串。 

    (5) 执行全局性替换(例如用PTSTR替换PSTR)。 

    (6) 修改字符串运算问题。例如函数通常希望在字符中传递一个缓存的大小,而不是字节。这意味着不应该传递sizeof(szBuffer),而应该传递(sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要为字符串分配一个内存块,并且拥有该字符串中的字符数目,那么请记住要按字节来分配内存。这就是说,应该调用malloc(nCharacters     *sizeof(TCHAR)),而不是调用malloc(nCharacters)。 



     10. 如何对字符串进行有选择的比较? 

    通过调用CompareString来实现。 

    标志 含义 

    NORM_IGNORECASE 忽略字母的大小写 

    NORM_IGNOREKANATYPE 不区分平假名与片假名字符 

    NORM_IGNORENONSPACE 忽略无间隔字符 

    NORM_IGNORESYMBOLS 忽略符号 

    NORM_IGNOREWIDTH 不区分单字节字符与作为双字节字符的同一个字符 

    SORT_STRINGSORT 将标点符号作为普通符号来处理 



     11. 如何判断一个文本文件是ANSI还是Unicode? 

    判断如果文本文件的开头两个字节是0xFF和0xFE,那么就是Unicode,否则是ANSI。


  

     12. 如何判断一段字符串是ANSI还是Unicode? 

    用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法,以便猜测缓存的内容。由于这不是一种确切的科学方法,因此     IsTextUnicode有可能返回不正确的结果。


  

     13. 如何在Unicode与ANSI之间转换字符串? 

    Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串;函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。

--------------------------------------


Wince unicode


Windows CE是一种Unicode环境。他支持ASCII函数以实现文本的转换,但其原有的文本格式是Unicode。

将ASCII应用程序转换为Unicode程序的一些通用指导方针如下:



①包含Tchar.h文件。该文件包含所有必要的转换。


②使用Win32字符串函数(例如lstrlen)而不是C运行时态(run-time)库的函数。


③声明中使用TCHAR、LPTSTR和其他类型。这样代码将易于编译为ASCII或Unicode格式。


④使用TEXT宏和_T宏进行字符串映射(例如TEXT("Your Text"))。


⑤牢记一个字符在长度上不再是一个字节,而字符串以两个零而不是一个零结尾。


⑥当增加一个数组指针或字符计数时,使用sizeof(TCHAR)以确保能够对ASCII或Unicode都有效。


⑦使用TCHAR当编译不同版本(SBCS/MBCS和)时自动定义成WCHAR或CHAR,wchar_t或char。_tcscpy代替strcpy()和wcscpy()。

L"this is a string 这是字符串" ,没有L仅仅是传统的字符串。


转自:http://blog.csdn.net/slj0609/archive/2008/09/11/2911478.aspx


-------------------------------------------------------------------------------


宽字符处理函数函数与普通函数对照表


字符分类:  

宽字符函数       普通C函数    描述

iswalnum()     isalnum() 测试字符是否为数字或字母

iswalpha()     isalpha() 测试字符是否是字母

iswcntrl()     iscntrl() 测试字符是否是控制符

iswdigit()     isdigit() 测试字符是否为数字

iswgraph()     isgraph() 测试字符是否是可见字符

iswlower()     islower() 测试字符是否是小写字符

iswprint()     isprint() 测试字符是否是可打印字符

iswpunct()     ispunct() 测试字符是否是标点符号

iswspace()     isspace() 测试字符是否是空白符号

iswupper()     isupper() 测试字符是否是大写字符

iswxdigit()     isxdigit()测试字符是否是十六进制的数字



大小写转换:   

宽字符函数        普通C函数   描述

towlower()     tolower() 把字符转换为小写

towupper()     toupper() 把字符转换为大写



字符比较:

宽字符函数        普通C函数   描述

wcscoll()     strcoll() 比较字符串



日期和时间转换:

宽字符函数        描述

strftime()     根据指定的字符串格式和locale设置格式化日期和时间

wcsftime()     根据指定的字符串格式和locale设置格式化日期和时间, 并返回宽字符串

strptime()     根据指定格式把字符串转换为时间值, 是strftime的反过程



打印和扫描字符串:

宽字符函数                   描述

fprintf()/fwprintf()     使用vararg参量的格式化输出

fscanf()/fwscanf()         格式化读入

printf()             使用vararg参量的格式化输出到标准输出

scanf()             从标准输入的格式化读入

sprintf()/swprintf()     根据vararg参量表格式化成字符串

sscanf()             以字符串作格式化读入

vfprintf()/vfwprintf()     使用stdarg参量表格式化输出到文件

vprintf()             使用stdarg参量表格式化输出到标准输出

vsprintf()/vswprintf()     格式化stdarg参量表并写到字符串



数字转换:

宽字符函数      普通C函数   描述

wcstod()     strtod() 把宽字符的初始部分转换为双精度浮点数

wcstol()     strtol() 把宽字符的初始部分转换为长整数

wcstoul()     strtoul() 把宽字符的初始部分转换为无符号长整数



多字节字符和宽字符转换及操作:

宽字符函数         描述

mblen()         根据locale的设置确定字符的字节数

mbstowcs()         把多字节字符串转换为宽字符串

mbtowc()/btowc()    把多字节字符转换为宽字符

wcstombs()         把宽字符串转换为多字节字符串

wctomb()/wctob()     把宽字符转换为多字节字符



输入和输出:

宽字符函数      普通C函数     描述

fgetwc()     fgetc()     从流中读入一个字符并转换为宽字符

fgetws()     fgets()     从流中读入一个字符串并转换为宽字符串

fputwc()     fputc()     把宽字符转换为多字节字符并且输出到标准输出

fputws()     fputs()     把宽字符串转换为多字节字符并且输出到标准输出串

getwc()     getc()     从标准输入中读取字符, 并且转换为宽字符

getwchar()     getchar()     从标准输入中读取字符, 并且转换为宽字符

None         gets()     使用fgetws()

putwc()     putc()     把宽字符转换成多字节字符并且写到标准输出

putwchar()     putchar()     把宽字符转换成多字节字符并且写到标准输出

None         puts()     使用fputws()

ungetwc()     ungetc()     把一个宽字符放回到输入流中



字符串操作:

宽字符函数          普通C函数      描述

wcscat()         strcat()     把一个字符串接到另一个字符串的尾部

wcsncat()         strncat()     类似于wcscat(), 而且指定粘接字符串的粘接长度.

wcschr()         strchr()     查找子字符串的第一个位置

wcsrchr()         strrchr()     从尾部开始查找子字符串出现的第一个位置

wcspbrk()         strpbrk()     从一字符字符串中查找另一字符串中任何一个字符第一次出现的位置

wcswcs()/wcsstr()     strchr()     在一字符串中查找另一字符串第一次出现的位置

wcscspn()         strcspn()     返回不包含第二个字符串的的初始数目

wcsspn()         strspn()     返回包含第二个字符串的初始数目

wcscpy()         strcpy()     拷贝字符串

wcsncpy()         strncpy()     类似于wcscpy(), 同时指定拷贝的数目

wcscmp()         strcmp()     比较两个宽字符串

wcsncmp()         strncmp()     类似于wcscmp(), 还要指定比较字符字符串的数目

wcslen()         strlen()     获得宽字符串的数目

wcstok()         strtok()     根据标示符把宽字符串分解成一系列字符串

wcswidth()         None         获得宽字符串的宽度

wcwidth()         None         获得宽字符的宽度



另外还有对应于memory操作的 wmemcpy(), wmemchr(), wmemcmp(), wmemmove(), wmemset().


------------------------------------------------------------------------------


Windows环境下Unicode编程总结


UNICODE环境设置

在安装Visual Studio时,在选择VC++时需要加入unicode选项,保证相关的库文件可以拷贝到system32下。


UNICODE编译设置:

C/C++, Preprocessor difinitions 去除_MBCS,加_UNICODE,UNICODE

在ProjectSetting/link/output 中设置Entry为wWinMainCRTStartup

反之为MBCS(ANSI)编译。


文章评论

0条评论