关于C++编程中字符与字符串的处理

来源:互联网 发布:sql select as 别名 编辑:程序博客网 时间:2024/05/17 23:54

一、

Unicode标准:

每个Unicode字符都是使用UTF-16编码,UTF-16将每个字符编码为2个字节,UTF-16在节省空间和简化编码之间提供了一个良好的折衷。

ANSI标准:

使用UTF-8编码,一个字符使用一个字节,占8位。c语言的char类型用来表示一个8位的ANSI字符。

 

二、  

WIndows系统与Unicode标准:

自Windows NT起,Windows所有版本都采用Unicode标准,所有核心函数都采用Unicode字符串,如果调用一个函数传入的参数是ANSI字符串,那么函数会先将其转换冲Unicode字符串,再传给操作系统,如果希望函数返回ANSI字符串,那么操作系统会先将Unicode字符串转换成ANSI字符串,这些转换都在幕后进行的,因此系统会产生时间和内存上的消耗。

 

三、

Microsoft的C/C++编译器与Unicode字符:

现在Microsoft的C/C++编译器定义了一个内建的数据类型wchar_t,它表示一个16位的Unicode(UTF-16)字符,在默认情况下,VS建立一个新项目时,是使用Unicode标准字符的。

声明Unicode字符或字符串的方法:wchar_t c = L'A';  在前面加个L表示通知编译器该字符(串)应当编译为Unicode字符。输出要用std::wcout。

 

四、

源代码如何保持一致性:

windows开发团队与c语言稍有区别,他们在Windows头文件WinNT.h中定义了以下数据类型:

typedef char CHAR ;  

typedef wchar_t WCHAR;

 

//指针

typedef  CHAR *PCHAR;

typedef  CHAR *PSTR;  

typedef  CONST CHAR *PCSTR;  

 

typedef WCHAR PWCHAR;

typedef WCHAR PWSTR;

typedef  CONST WCHAR *PCWSTR;  

 

在源代码中,具体使用哪种字符类型不重要,重要的是保持一致性,增加代码的可维护性, WinNT.h中定义了以下类型和宏:

#ifdef UNICODE

typedef WCHAR TCHAR ,*PTCHAR, PTSTR;

typedef CONST WCHAR  *PCTSTR;

 

#else

 

typedef WCHAR TCHAR ,*PTCHAR, PTSTR;

typedef CONST WCHAR  *PCTSTR;

所以无论采用哪种字符标准,使用TCHAR都是编译通过   TCHAR szBuffer[100] = _T("hello world!"); 故TCHAR称为通用类型。

此外对一些API函数也做了一些保持一致性的修改,如下:

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

 

#else

#define CreateWindowEx CreateWindowExA

 

#endif

 

 

五、

C运行库中的Unicode函数和ANSI函数:

对于计算字符串长度的函数,C运行库中,strlen是返回ANSI字符串的长度,与之对于的是wcslen,返回的是Unicode字符串的长度。

TChar.h文件中,定义了以下宏:

#ifdef UNICODE

#define _tcslen  wcslen

#else

#define _tcslen strlen

#endif

所以在代码中不用管是否采用Unicode标准,可以直接调用_tcslen函数。

 

但是,任何修改字符串的函数都存在一个安全隐患,如果目标字符串的缓冲区不够大,无法容下所生成的字符串,将会导致内存中的数据被破坏,例如strcpy和wcscpy,所以最好是用wcscat这样指定缓冲区长度的字符串处理函数。相反的,像stlen和wcslen等不会修改传入字符串的函数则是安全的。

目前微软提供了一些新版本的字符串安全处理函数(tchar.h文件里),即在函数名后面加_s ,例如_tcscpy_s,_tcscat_s,memcpy_s,memmove_s。它们的首要任务就是验证传给它们的参数值。例如指针不为NULL,整数在有范围内,缓冲区是否能容纳结果大小等。

这里我介绍一个宏_countof, 一些函数通常需要我传入某个参数的缓冲区的字符数,而非字节数,所以我们就应该传入_countof(szBuffer)而不是sizeof(szBuffer) 。在手动分配一块内存的时候,要记住内存是以字节累分配的,这意味着我们必须调用malloc(nChars * sizeof(TCHAR))。

VC中有一个计算数组元素个数的MACRO

代码如下:

#if !defined(_countof)
#if !defined(__cplusplus)
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#else
extern "C++"
{
template <typename _CountofType, size_t _SizeOfArray>
char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];
#define _countof(_Array) sizeof(*__countof_helper(_Array))
}
#endif
#endif

C++版本的实现充分地利用了函数模板的参数自动推导机制,但我始终没聊到函数指针也可以模板化,

 

六、宽字符与窄字符转换

size_t mbstowcs(wchar_t *wcstr, const char *mbstr, size_t count)//由一个窄字符转换到一个宽字符

size_t wcstombs(char *mbstr, const wchar_t *wcstr, size_t count)//由一个宽字符转换到一个窄字符

原创粉丝点击