Project Properties -> General-> Character set,里面显示了是不是unicode. Unicode处理String的方式不一样,一定要注意!!


 




使你的C/C++代码支持Unicode的第一步

  • 定义宏 _UNICODE, 如果定义了宏 _MBCS 则取消它的定义(undefine)。
  • 在字符串前添加 L 标记或者用 _T宏修饰字符串。
  • 使用 Wide 或者 TCHAR 版本的字符串处理函数。
  • 确定API中的字符串长度是按字节计数还是按字符个数计数。因为基于字符的显示和打印(与此不同的是,GUI是基于像素的)使用 列数,而不是字节数或者字符个数。
  • 在字符串指针相关的计算中使用GetNext格式,因为一个字符可能包含多于一个Unicode字符单元。
  • 注意缓冲区的大小以及防止缓冲区溢出。
    改变编码方式可能需要增大缓冲区或者限制字符串的最大长度。假设单个字符的大小从1个字节变为4个字节,并且字 符串本来20个字符占用20字节,那么你需要将字符串缓冲区扩大为80字节或者将字符串长度限制为5个字符(字符串缓冲区仍为20字节)。注意缓冲区的扩 大可能被限制到一个最大值(比如65KB)。减少字符串长度到一个固定值可能破坏现有的程序,限制字符串长度到固定值可能是危险的。比如,限制到20字 节,将字符串转化为大写形式就可能导致字符串变长并且超过限制。
  • 将接受或者返回单字符参数的函数替换为使用字符串的版本。 (在一些语言中) 对于单个字符的操作可能导致返回多个代码点。例如,upper('ß')将 返回"SS"。
  • 使用 wmain 代替 main。环境变量也由_environ变 为_wenviron 。
    wmain(int argc, wchar_t *argv[], wchar_t *envp[])
  • MFC Unicode 程序使用  wWinMain 作为程序入口点(VC++ 6.0)。 
    project->settings->Link,选择output选项卡
    在Entry point symbol一行加上 wWinMainCRTStartup 。
  • 字体的因素,分清使用的字体用于渲染各种语言的字符还是用于脚本中。


文件 I/O, 数据库, 传输协议等因素

  • 考虑是否需要读写文件、数据库中的 UTF-8 或者 UTF-16 字符,以及是否进行数据交换。
  • 考虑 UTF-16 格式文件中的字节序。 
    读写网络传输的数据总是使用 Big-Endian ,如果你没有产生 BOM 也使用 Big-Endian。
    文件的字节序依赖于文件格式以及/或者源/目标机器的体系结构。
    读取 UTF-16 或者 UTF-32编码的文件时,考虑是否需要将字符按字节逆序。 
    对于 streams 和传输协议也需要做上述的考虑。
  • 传输协议和用于数据交换的文件要使用正确的编码方式。例如 HTTP,HTML,XML 必须设置为 UTF-8 或者 UTF-16。
  • 考虑Unicode字节序标记( BOM ,Byte Order Marker) 以及是否需要将它同数据一同写入。读取数据时记得去掉BOM。
  • 考虑遗留数据和文件的编码惯例,考虑导入和导出以及传输协议。
  • 考虑复制文本到剪贴板
    使用 CF_TEXT 格式并且写入本地编码的文本(ANSI格式)
    使用 CF_UNICODETEXT 格式并写入Unicode文本
  • 数据库程序需要考虑数据类型 (NCHAR, NVARCHAR) 和模式(schema)的变更,触发器,存储过程和查询,数据的增长,索引以及性能等因素。
    注意:Unicode模式的改变对于不同厂商的数据库产生不同的影响。如果需要数据库具有较好的可移植性,就要考虑到每种数据库的特性和行为。 
    (我知道针对这个问题说得不够多,以后有机会再补充吧)


流式 I/O

如果你使用Microsoft C++编译器,你可能遇到与流式 I/O相关的3类问题:

  1. 不支持Unicode文件名。
    解决方式是使用 FILE * _wfopen 函数,之后使用FILE句柄初始化流式 I/O。 std::ifstream stm(_wfopen(pFilename, L"r"));
  2. 在 读/写 的时候,流式 I/O 会把数据 从本地代码页(ANSI格式)转换到Unicode格式/从Unicode格式转换到ANSI格式,而非UTF-8 或者 UTF-16。但是可以修改表示流的类使之支持读写 UTF-8 格式字符。你可以自己实现一个读写时把数据在 Unicode 和 UTF-8 之间转换的I/O stream类。 codecvt >
  3. 如果要用流式 I/O读写 UTF-16 字符,应该用二进制模式打开并且在二进制模式下输入输出。可以用如下方法设置 I/O 为二进制模式: _setmode( _fileno( stdin ), _O_BINARY );

    也可以参考 Microsoft 运行时库参考: "Unicode Stream I/O in Text and Binary Modes".

注意:针对cout/wcout, cin/wcin等并没有相应的 TCHAR 版本。如果你需要在ANSI/Unicode两种模式下编译 代码,你可能需要自己定义一个名字类似"tout"的宏。


国际化,Unicode高级技术,平台和其它因素

  • 考虑使用基于地区的办法和更进一步的国际化。


Unicode字节序标记(BOM) 值



常量和全局变量

ANSI版本

宽字符版本

宏定义版本(TCHAR)

EOF

WEOF

_TEOF

_environ

_wenviron

_tenviron

_pgmptr

_wpgmptr

_tpgmptr



数据类型

ANSI版本

宽字符版本

宏定义版本(TCHAR)

char

wchar_t

_TCHAR

_finddata_t

_wfinddata_t

_tfinddata_t

__finddata64_t

__wfinddata64_t

_tfinddata64_t

_finddatai64_t

_wfinddatai64_t

_tfinddatai64_t

int

wint_t

_TINT

signed char

wchar_t

_TSCHAR

unsigned char

wchar_t

_TUCHAR

char

wchar_t

_TXCHAR

 

L

_T 或者 _TEXT

LPSTR

(char *)

LPWSTR

(wchar_t *)

LPTSTR

(_TCHAR *)

LPCSTR

(const char *)

LPCWSTR

(const wchar_t *)

LPCTSTR

(const _TCHAR *)

LPOLESTR

(For OLE)

LPWSTR

LPTSTR



Platform SDK字符串处理API

有很多Windows API函数会根据宏 UNICODE 是 否被定义而编译成不同形式。那些需要同时操作ANSI字符和宽字符的模块需要了解这一点。否则,应该使用宏定义版本的名字,这样的话就只需要定义宏 UNICODE 并且重新编译程序。

下列列表并没有列举所有的有ANSI和宽字符两个版本的API,只列举了与字符和字符串处理相关的一些。如果需要查看与代码页和地区相 关 的API请查看WinNLS.h头文件。

ANSI版本

宽字符版本

宏定义版本(TCHAR)

CharLowerA

CharLowerW

CharLower

CharLowerBuffA

CharLowerBuffW

CharLowerBuff

CharNextA

CharNextW

CharNext

CharNextExA

CharNextExW

CharNextEx

CharPrevA

CharPrevW

CharPrev

CharPrevExA

CharPrevExW

CharPrevEx

CharToOemA

CharToOemW

CharToOem

CharToOemBuffA

CharToOemBuffW

CharToOemBuff

CharUpperA

CharUpperW

CharUpper

CharUpperBuffA

CharUpperBuffW

CharUpperBuff

CompareStringA

CompareStringW

CompareString

FoldStringA

FoldStringW

FoldString

GetStringTypeA

GetStringTypeW

GetStringType

GetStringTypeExA

GetStringTypeExW

GetStringTypeEx

IsCharAlphaA

IsCharAlphaW

IsCharAlpha

IsCharAlphaNumericA

IsCharAlphaNumericW

IsCharAlphaNumeric

IsCharLowerA

IsCharLowerW

IsCharLower

IsCharUpperA

IsCharUpperW

IsCharUpper

LoadStringA

LoadStringW

LoadString

lstrcatA

lstrcatW

lstrcat

lstrcmpA

lstrcmpW

lstrcmp

lstrcmpiA

lstrcmpiW

lstrcmpi

lstrcpyA

lstrcpyW

lstrcpy

lstrcpynA

lstrcpynW

lstrcpyn

lstrlenA

lstrlenW

lstrlen

OemToCharA

OemToCharW

OemToChar

OemToCharBuffA

OemToCharBuffW

OemToCharBuff

wsprintfA

wsprintfW

wsprintf

wvsprintfA

wvsprintfW

wvsprintf



CRT字符串处理API

函数按照ANSI版本的ASCII字母顺序排序,方便转换到相应的Unicode版本。

ANSI版本

宽字符版本

宏定义版本(TCHAR)

_access

_waccess

_taccess

_atoi64

_wtoi64

_tstoi64

_atoi64

_wtoi64

_ttoi64

_cgets

_cgetws

cgetts

_chdir

_wchdir

_tchdir

_chmod

_wchmod

_tchmod

_cprintf

_cwprintf

_tcprintf

_cputs

_cputws

_cputts

_creat

_wcreat

_tcreat

_cscanf

_cwscanf

_tcscanf

_ctime64

_wctime64

_tctime64

_execl

_wexecl

_texecl

_execle

_wexecle

_texecle

_execlp

_wexeclp

_texeclp

_execlpe

_wexeclpe

_texeclpe

_execv

_wexecv

_texecv

_execve

_wexecve

_texecve

_execvp

_wexecvp

_texecvp

_execvpe

_wexecvpe

_texecvpe

_fdopen

_wfdopen

_tfdopen

_fgetchar

_fgetwchar

_fgettchar

_findfirst

_wfindfirst

_tfindfirst

_findnext64

_wfindnext64

_tfindnext64

_findnext

_wfindnext

_tfindnext

_findnexti64

_wfindnexti64

_tfindnexti64

_fputchar

_fputwchar

_fputtchar

_fsopen

_wfsopen

_tfsopen

_fullpath

_wfullpath

_tfullpath

_getch

_getwch

_gettch

_getche

_getwche

_gettche

_getcwd

_wgetcwd

_tgetcwd

_getdcwd

_wgetdcwd

_tgetdcwd

_ltoa

_ltow

_ltot

_makepath

_wmakepath

_tmakepath

_mkdir

_wmkdir

_tmkdir

_mktemp

_wmktemp

_tmktemp

_open

_wopen

_topen

_popen

_wpopen

_tpopen

_putch

_putwch

_puttch

_putenv

_wputenv

_tputenv

_rmdir

_wrmdir

_trmdir

_scprintf

_scwprintf

_sctprintf

_searchenv

_wsearchenv

_tsearchenv

_snprintf

_snwprintf

_sntprintf

_snscanf

_snwscanf

_sntscanf

_sopen

_wsopen

_tsopen

_spawnl

_wspawnl

_tspawnl

_spawnle

_wspawnle

_tspawnle

_spawnlp

_wspawnlp

_tspawnlp

_spawnlpe

_wspawnlpe

_tspawnlpe

_spawnv

_wspawnv

_tspawnv

_spawnve

_wspawnve

_tspawnve

_spawnvp

_wspawnvp

_tspawnvp

_spawnvpe

_wspawnvpe

_tspawnvpe

_splitpath

_wsplitpath

_tsplitpath

_stat64

_wstat64

_tstat64

_stat

_wstat

_tstat

_stati64

_wstati64

_tstati64

_strdate

_wstrdate

_tstrdate

_strdec

_wcsdec

_tcsdec

_strdup

_wcsdup

_tcsdup

_stricmp

_wcsicmp

_tcsicmp

_stricoll

_wcsicoll

_tcsicoll

_strinc

_wcsinc

_tcsinc

_strlwr

_wcslwr

_tcslwr

_strncnt

_wcsncnt

_tcsnbcnt

_strncnt

_wcsncnt

_tcsnccnt

_strncnt

_wcsncnt

_tcsnccnt

_strncoll

_wcsncoll

_tcsnccoll

_strnextc

_wcsnextc

_tcsnextc

_strnicmp

_wcsnicmp

_tcsncicmp

_strnicmp

_wcsnicmp

_tcsnicmp

_strnicoll

_wcsnicoll

_tcsncicoll

_strnicoll

_wcsnicoll

_tcsnicoll

_strninc

_wcsninc

_tcsninc

_strnset

_wcsnset

_tcsncset

_strnset

_wcsnset

_tcsnset

_strrev

_wcsrev

_tcsrev

_strset

_wcsset

_tcsset

_strspnp

_wcsspnp

_tcsspnp

_strtime

_wstrtime

_tstrtime

_strtoi64

_wcstoi64

_tcstoi64

_strtoui64

_wcstoui64

_tcstoui64

_strupr

_wcsupr

_tcsupr

_tempnam

_wtempnam

_ttempnam

_ui64toa

_ui64tow

_ui64tot

_ultoa

_ultow

_ultot

_ungetch

_ungetwch

_ungettch

_unlink

_wunlink

_tunlink

_utime64

_wutime64

_tutime64

_utime

_wutime

_tutime

_vscprintf

_vscwprintf

_vsctprintf

_vsnprintf

_vsnwprintf

_vsntprintf

asctime

_wasctime

_tasctime

atof

_wtof

_tstof

atoi

_wtoi

_tstoi

atoi

_wtoi

_ttoi

atol

_wtol

_tstol

atol

_wtol

_ttol

字符比较

映射为宏或者inline 函数

_tccmp

字符拷贝

映射为宏或者inline 函数

_tccpy

字符长度

映射为宏或者inline 函数

_tclen

ctime

_wctime

_tctime

fgetc

fgetwc

_fgettc

fgets

fgetws

_fgetts

fopen

_wfopen

_tfopen

fprintf

fwprintf

_ftprintf

fputc

fputwc

_fputtc

fputs

fputws

_fputts

freopen

_wfreopen

_tfreopen

fscanf

fwscanf

_ftscanf

getc

getwc

_gettc

getchar

getwchar

_gettchar

getenv

_wgetenv

_tgetenv

gets

getws

_getts

isalnum

iswalnum

_istalnum

isalpha

iswalpha

_istalpha

isascii

iswascii

_istascii

iscntrl

iswcntrl

_istcntrl

isdigit

iswdigit

_istdigit

isgraph

iswgraph

_istgraph

islead (总是返回FALSE)

(总是返回FALSE)

_istlead

isleadbyte (总是返回FALSE)

isleadbyte (总是返回FALSE)

_istleadbyte

islegal (总是返回TRUE)

(总是返回TRUE)

_istlegal

islower

iswlower

_istlower

isprint

iswprint

_istprint

ispunct

iswpunct

_istpunct

isspace

iswspace

_istspace

isupper

iswupper

_istupper

isxdigit

iswxdigit

_istxdigit

main

wmain

_tmain

perror

_wperror

_tperror

printf

wprintf

_tprintf

putc

putwc

_puttc

putchar

putwchar

_puttchar

puts

_putws

_putts

remove

_wremove

_tremove

rename

_wrename

_trename

scanf

wscanf

_tscanf

setlocale

_wsetlocale

_tsetlocale

sprintf

swprintf

_stprintf

sscanf

swscanf

_stscanf

strcat

wcscat

_tcscat

strchr

wcschr

_tcschr

strcmp

wcscmp

_tcscmp

strcoll

wcscoll

_tcscoll

strcpy

wcscpy

_tcscpy

strcspn

wcscspn

_tcscspn

strerror

_wcserror

_tcserror

strftime

wcsftime

_tcsftime

strlen

wcslen

_tcsclen

strlen

wcslen

_tcslen

strncat

wcsncat

_tcsncat

strncat

wcsncat

_tcsnccat

strncmp

wcsncmp

_tcsnccmp

strncmp

wcsncmp

_tcsncmp

strncpy

wcsncpy

_tcsnccpy

strncpy

wcsncpy

_tcsncpy

strpbrk

wcspbrk

_tcspbrk

strrchr

wcsrchr

_tcsrchr

strspn

wcsspn

_tcsspn

strstr

wcsstr

_tcsstr

strtod

wcstod

_tcstod

strtok

wcstok

_tcstok

strtol

wcstol

_tcstol

strtoul

wcstoul

_tcstoul

strxfrm

wcsxfrm

_tcsxfrm

system

_wsystem

_tsystem

tmpnam

_wtmpnam

_ttmpnam

tolower

towlower

_totlower

toupper

towupper

_totupper

ungetc

ungetwc

_ungettc

vfprintf

vfwprintf

_vftprintf

vprintf

vwprintf

_vtprintf

vsprintf

vswprintf

_vstprintf

WinMain

wWinMain

_tWinMain