关于UNICODE版本的开发

  1. 代码转换方案

    1. 概述

在VC6.0中,相应的有一些宏来代替ANSI的函数、宏或数据类型,这些宏在ANSI编译条件中处理字符串为单字节,而在UNICODE中处理字符串为双字节,请在编写程序中请使用这些宏。

  1. 数据类型

表-1.1中黑体字部分为替代数据类型的宏。

Generic-Text Data Type Mappings

Generic-Text Data Type Name

SBCS (_UNICODE, _MBCS Not Defined)

_MBCS Defined

_UNICODE Defined

_TCHAR

Char

char

wchar_t

_TINT

Int

int

wint_t

_TSCHAR

signed char

signed char

wchar_t

_TUCHAR

unsigned char

unsigned char

wchar_t

_TXCHAR

Char

unsigned char

wchar_t

_T or _TEXT

No effect (removed by preprocessor)

No effect (removed by preprocessor)

L (converts following character or string to its Unicode counterpart)

表-1.1

  1. 函数

表-1.2中黑体字部分为替代函数的宏

Generic-Text Routine Mappings

Generic-Text
Routine Name

SBCS (_UNICODE &
MBCS Not Defined)

_MBCS Defined

_UNICODE Defined

_fgettc

fgetc

fgetc

fgetwc

_fgettchar

fgetchar

fgetchar

_fgetwchar

_fgetts

fgets

fgets

fgetws

_fputtc

fputc

fputc

fputwc

_fputtchar

fputchar

fputchar

_fputwchar

_fputts

fputs

fputs

fputws

_ftprintf

fprintf

fprintf

fwprintf

_ftscanf

fscanf

fscanf

fwscanf

_gettc

getc

getc

getwc

_gettchar

getchar

getchar

getwchar

_getts

gets

gets

getws

_istalnum

isalnum

_ismbcalnum

iswalnum

_istalpha

isalpha

_ismbcalpha

iswalpha

_istascii

__isascii

__isascii

iswascii

_istcntrl

iscntrl

iscntrl

iswcntrl

_istdigit

isdigit

_ismbcdigit

iswdigit

_istgraph

isgraph

_ismbcgraph

iswgraph

_istlead

Always returns false

_ismbblead

Always returns false

_istleadbyte

Always returns false

isleadbyte

Always returns false

_istlegal

Always returns true

_ismbclegal

Always returns true

_istlower

islower

_ismbclower

iswlower

_istprint

isprint

_ismbcprint

iswprint

_istpunct

ispunct

_ismbcpunct

iswpunct

_istspace

isspace

_ismbcspace

iswspace

_istupper

isupper

_ismbcupper

iswupper

_istxdigit

isxdigit

isxdigit

iswxdigit

_itot

_itoa

_itoa

_itow

_ltot

_ltoa

_ltoa

_ltow

_puttc

putc

putc

putwc

_puttchar

putchar

putchar

putwchar

_putts

puts

puts

putws

_tmain

main

main

wmain

_sntprintf

_snprintf

_snprintf

_snwprintf

_stprintf

sprintf

sprintf

swprintf

_stscanf

sscanf

sscanf

swscanf

_taccess

_access

_access

_waccess

_tasctime

asctime

asctime

_wasctime

_tccpy

Maps to macro or inline function

_mbccpy

Maps to macro or inline function

_tchdir

_chdir

_chdir

_wchdir

_tclen

Maps to macro or inline function

_mbclen

Maps to macro or inline function

_tchmod

_chmod

_chmod

_wchmod

_tcreat

_creat

_creat

_wcreat

_tcscat

strcat

_mbscat

wcscat

_tcschr

strchr

_mbschr

wcschr

_tcsclen

strlen

_mbslen

wcslen

_tcscmp

strcmp

_mbscmp

wcscmp

_tcscoll

strcoll

_mbscoll

wcscoll

_tcscpy

strcpy

_mbscpy

wcscpy

_tcscspn

strcspn

_mbscspn

wcscspn

_tcsdec

_strdec

_mbsdec

_wcsdec

_tcsdup

_strdup

_mbsdup

_wcsdup

_tcsftime

strftime

strftime

wcsftime

_tcsicmp

_stricmp

_mbsicmp

_wcsicmp

_tcsicoll

_stricoll

_stricoll

_wcsicoll

_tcsinc

_strinc

_mbsinc

_wcsinc

_tcslen

strlen

strlen

wcslen

_tcslwr

_strlwr

_mbslwr

_wcslwr

_tcsnbcnt

_strncnt

_mbsnbcnt

_wcnscnt

_tcsncat

strncat

_mbsnbcat

wcsncat

_tcsnccat

strncat

_mbsncat

wcsncat

_tcsncmp

strncmp

_mbsnbcmp

wcsncmp

_tcsnccmp

strncmp

_mbsncmp

wcsncmp

_tcsnccnt

_strncnt

_mbsnccnt

_wcsncnt

_tcsnccpy

strncpy

_mbsncpy

wcsncpy

_tcsncicmp

_strnicmp

_mbsnicmp

_wcsnicmp

_tcsncpy

strncpy

_mbsnbcpy

wcsncpy

_tcsncset

_strnset

_mbsnset

_wcsnset

_tcsnextc

_strnextc

_mbsnextc

_wcsnextc

_tcsnicmp

_strnicmp

_mbsnicmp

_wcsnicmp

_tcsnicoll

_strnicoll

_strnicoll

_wcsnicoll

_tcsninc

_strninc

_mbsninc

_wcsninc

_tcsnccnt

_strncnt

_mbsnccnt

_wcsncnt

_tcsnset

_strnset

_mbsnbset

_wcsnset

_tcspbrk

strpbrk

_mbspbrk

wcspbrk

_tcsspnp

_strspnp

_mbsspnp

_wcsspnp

_tcsrchr

strrchr

_mbsrchr

wcsrchr

_tcsrev

_strrev

_mbsrev

_wcsrev

_tcsset

_strset

_mbsset

_wcsset

_tcsspn

strspn

_mbsspn

wcsspn

_tcsstr

strstr

_mbsstr

wcsstr

_tcstod

strtod

strtod

wcstod

_tcstok

strtok

_mbstok

wcstok

_tcstol

strtol

strtol

wcstol

_tcstoul

strtoul

strtoul

wcstoul

_tcsupr

_strupr

_mbsupr

_wcsupr

_tcsxfrm

strxfrm

strxfrm

wcsxfrm

_tctime

ctime

ctime

_wctime

_texecl

_execl

_execl

_wexecl

_texecle

_execle

_execle

_wexecle

_texeclp

_execlp

_execlp

_wexeclp

_texeclpe

_execlpe

_execlpe

_wexeclpe

_texecv

_execv

_execv

_wexecv

_texecve

_execve

_execve

_wexecve

_texecvp

_execvp

_execvp

_wexecvp

_texecvpe

_execvpe

_execvpe

_wexecvpe

_tfdopen

_fdopen

_fdopen

_wfdopen

_tfindfirst

_findfirst

_findfirst

_wfindfirst

_tfindnext

_findnext

_findnext

_wfindnext

_tfopen

fopen

fopen

_wfopen

_tfreopen

freopen

freopen

_wfreopen

_tfsopen

_fsopen

_fsopen

_wfsopen

_tfullpath

_fullpath

_fullpath

_wfullpath

_tgetcwd

_getcwd

_getcwd

_wgetcwd

_tgetenv

getenv

getenv

_wgetenv

_tmain

main

main

wmain

_tmakepath

_makepath

_makepath

_wmakepath

_tmkdir

_mkdir

_mkdir

_wmkdir

_tmktemp

_mktemp

_mktemp

_wmktemp

_tperror

perror

perror

_wperror

_topen

_open

_open

_wopen

_totlower

tolower

_mbctolower

towlower

_totupper

toupper

_mbctoupper

towupper

_tpopen

_popen

_popen

_wpopen

_tprintf

printf

printf

wprintf

_tremove

remove

remove

_wremove

_trename

rename

rename

_wrename

_trmdir

_rmdir

_rmdir

_wrmdir

_tsearchenv

_searchenv

_searchenv

_wsearchenv

_tscanf

scanf

scanf

wscanf

_tsetlocale

setlocale

setlocale

_wsetlocale

_tsopen

_sopen

_sopen

_wsopen

_tspawnl

_spawnl

_spawnl

_wspawnl

_tspawnle

_spawnle

_spawnle

_wspawnle

_tspawnlp

_spawnlp

_spawnlp

_wspawnlp

_tspawnlpe

_spawnlpe

_spawnlpe

_wspawnlpe

_tspawnv

_spawnv

_spawnv

_wspawnv

_tspawnve

_spawnve

_spawnve

_wspawnve

_tspawnvp

_spawnvp

_spawnvp

_tspawnvp

_tspawnvpe

_spawnvpe

_spawnvpe

_tspawnvpe

_tsplitpath

_splitpath

_splitpath

_wsplitpath

_tstat

_stat

_stat

_wstat

_tstrdate

_strdate

_strdate

_wstrdate

_tstrtime

_strtime

_strtime

_wstrtime

_tsystem

system

system

_wsystem

_ttempnam

_tempnam

_tempnam

_wtempnam

_ttmpnam

tmpnam

tmpnam

_wtmpnam

_ttoi

atoi

atoi

_wtoi

_ttol

atol

atol

_wtol

_tutime

_utime

_utime

_wutime

_tWinMain

WinMain

WinMain

wWinMain

_ultot

_ultoa

_ultoa

_ultow

_ungettc

ungetc

ungetc

ungetwc

_vftprintf

vfprintf

vfprintf

vfwprintf

_vsntprintf

_vsnprintf

_vsnprintf

_vsnwprintf

_vstprintf

vsprintf

vsprintf

vswprintf

_vtprintf

vprintf

vprintf

vwprintf

表1.2

表1.4中黑体字部分为替代宏的宏

Generic-Text Marco Mappings

Generic-Text –
Object Name

SBCS (_UNICODE,
_MBCS Not Defined)

_MBCS Defined

_UNICODE
Defined

LPCTSTR

LPCSTR(CONST CHAR*) 

LPCSTR(CONST CHAR*)

CONST WCHAR*(const unsigned short*)

LPTSTR

LPSTR(CHAR*) 

LPSTR(CHAR*) 

WCHAR*(unsigned short*) 

表1.3

  1. 常量和全局变量

表1.4中黑体字部分为替代常量和全局变量的宏

Generic-Text Constant and Global Variable Mappings

Generic-Text –
Object Name

SBCS (_UNICODE,
_MBCS Not Defined)

_MBCS Defined

_UNICODE
Defined

_TEOF

EOF

EOF

WEOF

_tenviron

_environ

_environ

_wenviron

_tfinddata_t

_finddata_t

_finddata_t

_wfinddata_t

表-1.4

  1. 不能转换的函数

atof替换方案

创建函数atof

#ifdef _UNICODE

double my_atof( LPCTSTR string )

{

assert( string!= NULL );

//double f3;

//_stscanf(string, _T("%lf"), &f3) ;//double

float f;

_stscanf(string, _T("%f"), &f) ;//float

return f;

}

#else

double my_atof( LPCTSTR string )

{

assert( string != NULL );

return atof(string);

}

#endif

fcvt替换方案

创建函数my_fcvt,如下:(注:FLT_EPSILON在float.h中)

#ifdef _UNICODE

LPCTSTR my_fcvt( double value, int count, int *dec, int *sign )

{

    static TCHAR szValue[32];

    

    if ( value < FLT_EPSILON && value > -FLT_EPSILON )

    {

        *dec = 0;

        *sign = 0;

        _stprintf(szValue, _T("%0*d"), count, 0);

        return (LPTSTR)&szValue;

    }

 

    if( value > FLT_EPSILON )

        *sign = 0;

    else

    {

        *sign = 1;

        value = -value;

    }

    *dec = 0;

    

    int nSize = _stprintf(szValue, _T("%.*f"), count, value);

    if( nSize > 0 )

    {

        //remove "."

        LPTSTR pstrSource = szValue;

        LPTSTR pstrDest = szValue;

        LPTSTR pstrEnd = szValue + nSize;

        LPTSTR pstrPoint = szValue;

        

        while (pstrSource < pstrEnd)

        {

            if (*pstrSource != '.')

            {

                *pstrDest = *pstrSource;

                pstrDest = _tcsinc(pstrDest);

            }

            else

            {

                pstrPoint = pstrDest;

            }

            pstrSource = _tcsinc(pstrSource);

        }

        *pstrDest = '\0';

        

        //trim "0"

        pstrDest = szValue;

        while (*pstrDest != '\0')

        {

            if (_tcschr(_T("0"), *pstrDest) == NULL)

                break;

            pstrDest = _tcsinc(pstrDest);

        }

        if (pstrDest != szValue)

        {

            int nDataLength = _tcslen(szValue) - (pstrDest - szValue);

            memmove(szValue, pstrDest, (nDataLength+1)*sizeof(TCHAR));

        }

        *dec = pstrPoint - pstrDest;

    }

    return (LPCTSTR)&szValue;

}

#else

inline LPCTSTR my_fcvt( double value, int count, int *dec, int *sign )

{

    return _fcvt( value, count, dec, sign );

}

#endif

  1. UNICODE文本文件的读写

对于UNICODE的文本文件,实际上就是双字节的二进制文件,该文件包含两个字节的文件头,内容是byte-order mark (BOM)值是0xfffe或0xfeff,表示字节的顺序,在这里使用的是0xfffe。

下面是一个写、读文件的例程:

#ifdef UNICODE

    FILE* fp;

    fp = _tfopen(_T("c:\\1.txt"), _T("w+b"));

    if( fp != NULL )

    {

        LPCTSTR buf = _T("abc\r\n");

        const BYTE head[] = {0xff, 0xfe};//BOM(byte-order mark)

        fwrite(head, sizeof(BYTE), sizeof(head)/sizeof(BYTE), fp);

        fwrite(buf, sizeof(TCHAR), _tcslen(buf), fp);

        fclose(fp);

    }

#endif

 

    fp = _tfopen(_T("c:\\1.txt"), _T("r+t"));

 

#ifdef UNICODE

    if( fp != NULL )

    {

        TCHAR text[512];

        memset(text, 0, sizeof(text));

        fread(text, sizeof(TCHAR), sizeof(text)-1, fp);

        int ret;

        IsTextUnicode(text, _tcslen(text), &ret);

        LPTSTR pBuf = text;

        if( ret & IS_TEXT_UNICODE_SIGNATURE )

        {

            pBuf ++;//文本的内容

        }

        fclose(fp);

    }

#endif

  1. 工程转换方案

如果VC6.0工程选择的是中文,在菜单Projects->Setting的C/C++属性页中,把Preprocessor definitinons: _MBCS改为_UNICODE,如果是英文的工程则直接加入_UNICODE。

如果工程是EXE文件,则须在Link属性页中,选择Category为Output,把Entry-point symbol:设置为wWinMainCRTStartup,如果工程不是EXE文件,则不需要改变。

最后点击OK即可。

  1. 附:ANSI、DBCS 和 Unicode 的定义

Unicode 是一种用两个字节表示一个字符的字符集。另外一些程序,如 Windows 95 API,使用 ANSI (American National Standards Institute) 或 DBCS 存储和操作字符串。

  1. ANSI

ANSI 是个人计算机使用得最普遍的字符集。由于 ANSI 标准使用单一字节表示每个字符,因此最多只能有 256 个字符和标点符号代码。虽然对英语来说已经足够了,但不能完全支持其它语言。

  1. DBCS

发行在亚洲大部分地区的 Microsoft Windows 系统使用 DBCS。它支持很多不同的东亚语言字母,如汉语、日语和朝鲜语。DBCS 使用数字 0–128 表示 ASCII 字符集。其它大于 128 的数字作为前导字节字符,它并不是真正的字符,只是简单的表明下一个字符属于非拉丁字符集。在 DBCS 中,ASCII 字符的长度是一个字节,而日语、朝鲜语和其它东亚字符的长度是 2 个字节。

  1. Unicode

Unicode 是用两个字节表示每个字符的字符编码方案。国际标准组织 (ISO) 几乎为每种语言的每个字符和符号在 0 到 65,535 (2 – 1) 范围内定义了一个数字(再加上为将来发展保留的一些空余空间)。在所有 32 位版本的 Windows 中,部件对象模型 (COM) 都使用 Unicode,它是 OLE 和 ActiveX 技术的基础。Windows NT 全部支持 Unicode。虽然 Unicode 和 DBCS 都是双字节字符,但它们的编码方案完全不同。

05-07 13:28