(一) 概述 string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中; CString(typedef CStringT<TCHAR, StrTraitMFC<TCHAR>> CString)为Visual C++中最常用的字符串类,继承自CSimpleStringT类,主要应用在MFC和ATL编程中,主要数据类型有char(应用于ANSI),wchar_t(unicode),TCHAR(ANSI与unicode均可); char*为C编程中最常用的字符串指针,一般以’\0’为结束标志; ### 综合比较 CString, string, char 的使用 #### (一) 概述 - **string** 和 **CString** 都是字符串模板类,其中 **string** 是标准模板库(STL)的一部分,已经被正式纳入 C++ 标准库中。 - **CString** (通过 typedef 定义为 `CStringT<TCHAR, StrTraitMFC<TCHAR>>`) 是 Visual C++ 中最常用的字符串类之一,它继承自 `CSimpleStringT` 类,主要应用在 MFC 和 ATL 编程中。`CString` 支持多种字符类型,如 `char` (用于 ANSI 编码),`wchar_t` (用于 Unicode 编码),以及 `TCHAR` (同时支持 ANSI 和 Unicode)。 - **char\*** 是 C 语言中最常用的字符串指针类型,通常以 `'\0'` 作为字符串的终止标志。 #### (二) 构造 - **string** 支持从多种类型的字符串构造,包括 `CString` 和 `char*`。 - **CString** 可以从基本字符串变量构造,例如 `char*`。 - **char\*** 没有构造函数,只能通过赋值操作进行初始化。 - 示例代码: ```cpp char* psz = "joise"; CString cstr(psz); string str(cstr); ``` #### (三) 运算符重载 ##### operator= - **string** 支持从几乎所有类型的字符串赋值,包括 `CString` 和 `char*`。 - **CString** 支持从基本的字符串变量赋值,例如 `char*`。 - **char\*** 只能通过指针赋值,这通常是一种危险的操作,推荐使用 `strcpy` 或 `memcpy`。 - 示例代码: ```cpp char* psz = NULL; psz = new char[10]; memset(psz, 0, 10); strcpy(psz, "joise"); CString cstr; cstr = psz; string str; str = psz; str = cstr; delete[] psz; ``` ##### operator+ - **string** 和 **CString** 都可以直接与 `char*` 使用 `+` 运算符,但两者之间不能直接使用 `+` 运算符。 - **char\*** 不支持 `+` 运算符,只能使用 `strcat` 将两个指针连接起来。 - 示例代码: ```cpp char* psz = "joise"; CString cstr = psz; cstr = cstr + psz; string str = psz; str = str + str + psz; strcat(psz, psz); strcat(psz, cstr.GetString()); // 合法 // strcat(psz, str); // 非法,需要转换为 const char* ``` ##### operator+= - **string** 支持与所有类型的字符串变量使用 `+=` 运算符。 - **CString** 支持与基本的字符串变量使用 `+=` 运算符。 - **char\*** 不支持 `+=` 运算符,需使用 `strcat`。 ##### operator[] - **CString** 在数组越界时会抛出断言异常。 - **string** 和 **char\*** 在数组越界时结果未定义。 - 示例代码: ```cpp char* psz = "joise"; CString cstr = psz; cout << cstr[8]; // 抛出断言异常 string str = psz; cout << str[8]; // 结果未定义 cout << psz[8]; // 结果未定义 ``` ##### operator==, operator!=, operator>, operator<, operator>=, operator<= - **CString** 和 **string** 不能直接进行比较,但它们都可以与 `char*` 进行比较,并且比较的是值而非地址。 - 示例代码: ```cpp char* psz = "joise"; CString cstr = psz; string str = psz; cout << (psz == cstr.GetString()); // 1 cout << (psz == str); // 1 cout << (str == psz); // 1 cout << (cstr == psz); // 1 ``` #### (四) 常用算法 - **查找作用**: - `CString` 提供了 `Find`, `FindOneOf`, `ReserveFind` 等方法来查找指定的子串或字符。 - `string` 提供了 `find`, `find_first_of`, `rfind` 等方法。 - `char*` 可以使用 C 标准库中的函数如 `strchr`, `strstr`, `strrstr`, `strspn` 等。 - **比较作用**: - `CString` 支持 `Collate`, `Compare` 方法进行字符串比较。 - `string` 支持 `<`, `>`, `<=`, `>=`, `==`, `!=` 等操作符进行比较。 - `char*` 可以使用 `strcmp`, `strncmp`, `strcoll`, `_strncoll` 等函数进行比较。 - 大小写不敏感的比较,`CString` 和 `string` 分别提供了 `_icmp`, `_icoll`, `Collate` 和 `casecmp` 方法,`char*` 可以使用 `_stricmp`, `_strnicmp` 函数。 根据不同的需求和上下文环境,选择合适的字符串处理类非常重要。对于新项目而言,推荐使用 C++ 标准库中的 `string` 类,因为它具有更好的性能、更多的功能以及更好的跨平台兼容性。而对于旧的基于 MFC/ATL 的项目,可能仍然需要使用 `CString`。对于简单的字符串操作,直接使用 `char*` 也可能是一个不错的选择,但要注意安全性和内存管理问题。
