当前位置: 首页 > news >正文

自定义CString类与MFC CString类接口对比

接口对比表格

功能分类

你的 CString 接口

MFC CString 接口(ANSI)

一致性

差异说明

构造函数

CString()
CString(const char*)
CString(char)
CString(const CString&)

CString()
CString(LPCSTR)
CString(TCHAR)
CString(const CString&)

一致

MFC 使用 LPCSTR(const char*),命名和参数逻辑相同。

析构函数

~CString()

~CString()

一致

均需手动释放内存(MFC 内部自动管理 COW 缓冲区)。

长度与判空

int GetLength() const
bool IsEmpty() const
void Empty()

int GetLength() const
BOOL IsEmpty() const
void Empty()

一致

MFC 返回 BOOL(等效 bool),功能相同。

字符访问

char GetAt(int) const
char& operator[]
const char& operator[] const

TCHAR GetAt(int) const
TCHAR& operator[]
const TCHAR& operator[] const

一致

MFC 使用 TCHAR(char in ANSI),越界处理:MFC 断言,你抛出异常。

修改字符

void SetAt(int, char)

void SetAt(int, TCHAR)

一致

参数和逻辑相同。

查找操作

int Find(char) const
int Find(const char*) const
int ReverseFind(char) const
int FindOneOf(const char*) const

int Find(TCHAR) const
int Find(LPCTSTR) const
int ReverseFind(TCHAR) const
int FindOneOf(LPCTSTR) const

一致

MFC 参数为 LPCTSTR(const char*),功能相同。

替换操作

int Replace(char, char)
int Replace(const char*, const char*)

int Replace(TCHAR, TCHAR)
int Replace(LPCTSTR, LPCTSTR)

一致

均返回替换次数,字符串替换需动态扩容。

删除操作

int Remove(char)

int Remove(TCHAR)

一致

均返回删除次数,逻辑相同。

插入操作

int Insert(int, char)
int Insert(int, char*)

int Insert(int, TCHAR)
int Insert(int, LPCTSTR)

一致

参数和返回值(新长度)相同,MFC 支持 CString 插入(通过 LPCTSTR 兼容)。

删除子串

int Delete(int, int = 1)

int Delete(int, int = 1)

一致

默认删除 1 个字符,越界处理逻辑需确保安全。

子串操作

CString Left(int) const
CString Right(int) const
CString Mid(int) const
CString Mid(int, int) const

CString Left(int) const
CString Right(int) const
CString Mid(int) const
CString Mid(int, int) const

一致

均返回子串对象,处理越界时返回空串。

赋值运算符

CString& operator=(char)
CString& operator=(const char*)
CString& operator=(const CString&)

CString& operator=(TCHAR)
CString& operator=(LPCTSTR)
CString& operator=(const CString&)

一致

MFC 无非常量引用赋值,你已删除 operator=(CString&),与 MFC 一致。

追加运算符

CString& operator+=(char)
CString& operator+=(const char*)
CString& operator+=(const CString&)

CString& operator+=(TCHAR)
CString& operator+=(LPCTSTR)
CString& operator+=(const CString&)

一致

功能相同,MFC 通过 LPCTSTR 兼容 CString。

连接运算符

friend CString operator+(...)(多重载)

friend CString operator+(...)(多重载)

一致

均支持字符串连接,返回新对象。

比较运算符

friend bool operator==/!=/>/<>=/<=(...)

friend BOOL operator==/!=/>/<>=/<=(...)

一致

MFC 返回 BOOL,逻辑相同;支持与 const char* 比较。

格式化

void Format(const char*, ...)

void Format(LPCTSTR, ...)

一致

均基于 sprintf,MFC 支持更多格式符(如 %I64d)。

大小写转换

void MakeUpper()
void MakeLower()

void MakeUpper()
void MakeLower()

部分一致

MFC 支持本地化转换(如土耳其语),你仅实现 ASCII 转换。

去除空白字符

void TrimLeft()
void TrimRight()
void Trim()

void TrimLeft()
void TrimRight()
void Trim()

部分一致

MFC 默认识别所有空白字符(如制表符),你的实现依赖 isspace(一致)。

反转字符串

CString& MakeReverse()

CStringT& MakeReverse()

一致

MFC 通过 StringTraits::StringReverse 实现,你通过手动交换字符实现,功能相同。

内存管理接口

char* GetBuffer(int)

LPTSTR GetBuffer(int)
void ReleaseBuffer()

差异

你未提供 ReleaseBuffer(),需手动管理长度;MFC 通过 ReleaseBuffer() 自动更新。

高级功能

无 Tokenize/LoadString/ 路径处理等

支持 Tokenize/LoadString/ExtractFilePath 等

缺失

MFC 提供字符串分词、资源加载、路径解析等高级功能。

安全检查

部分函数抛出异常(如越界)

部分函数内部断言(如 ATLASSERT)

差异

MFC 依赖调试断言,你使用异常处理,均实现基本安全控制。

关键结论

1.基础操作完全一致

构造 / 析构、查找 / 替换、比较 / 连接等核心接口的命名、参数和功能与 MFC 一致,可直接映射。

2.const 修饰完全对齐

所有 const 成员函数、参数均符合 MFC 规范,类型安全无差异。

差异与缺失

  1. 内存管理:缺少 ReleaseBuffer(),需手动处理 GetBuffer() 后的长度更新。
  2. 高级功能:无 Tokenize、资源加载、路径处理等 MFC 特有功能。
  3. 本地化:大小写转换未考虑区域设置,MFC 支持更全面。

适用场景

  1. 一致场景:ANSI 环境下的基础字符串操作,如简单文本处理、非国际化逻辑。
  2. 不一致场景:需要 Unicode、高性能内存管理(COW)、复杂字符串处理(如路径解析)的场景。

cstring.h

#ifndef CSTRING_H
#define CSTRING_H#include <cstdarg>class CString
{
public://默认构造函数CString();//析构函数~CString();//从另一个 CString 复制构造CString(const CString& string1);// 从C风格字符串构造CString(const char *ch);// 从单个字符构造CString(const char ch);// 获取字符串长度int GetLength() const;// 判断字符串是否为空bool IsEmpty() const;// 清空字符串void Empty();// 获取指定位置的字符char GetAt(int iIndex) const;//重载 [] 运算符char& operator[](int iIndex);//重载 [] 运算符const char& operator[](int iIndex) const;//修改指定位置的字符void SetAt(int iIndex, char ch);// 查找字符最后一次出现的位置,失败返回-1int ReverseFind(char ch) const;// 替换所有指定字符,返回替换次数int Replace(char chOld, char chNew);// 替换所有子字符串,返回替换次数int Replace(const char* lpszOld, const char* lpszNew);// 删除所有指定字符,返回删除次数int Remove(char ch);// 在字符串的 nIndex 位置插入字符 ch,返回插入字符后字符串的长度int Insert(int nIndex, char ch);// 在字符串的 nIndex 位置插入字符串 lpsz,返回插入字符串后字符串的长度int Insert(int nIndex, char* lpsz);// 删除字符串中从 nIndex 位置开始的 nCount 个字符(默认删除 1 个字符),返回删除字符后字符串的长度int Delete(int nIndex, int nCount = 1);// 字符赋值运算符重载CString& operator=(char ch);// C风格字符串赋值运算符重载CString& operator=(const char * lpsz);// 常量CString拷贝赋值运算符重载CString& operator=(const CString& string1);// 字符追加运算符重载CString& operator+=(char ch);// C风格字符串追加运算符重载CString& operator+=(const char *str);// CString追加运算符重载CString& operator+=(const CString &Str);// 格式化字符串,功能类似sprintf,返回格式化后的长度void Format(const char* pstrFormat, ...);// 截取左边n个字符的子串CString Left(int nCount) const;// 截取右边n个字符的子串CString Right(int nCount) const;// 从nFirst开始到末尾的子串CString Mid(int nFirst) const;// 从nFirst开始截取nCount个字符的子串CString Mid(int nFirst, int nCount) const;// 获取内部缓冲区指针,用于直接操作内存char* GetBuffer(int nMinBufLength);// 查找int Find(char ch) const;int Find(const char * lpszSub) const;int Find(char ch, int nStart) const;int Find(const char *str,  int uiBegin) const;int Find(CString sSub) const;int FindOneOf(const char* lpszCharSet) const;// 转换为大写void MakeUpper();// 转换为小写void MakeLower();// 去除左侧空白字符void TrimLeft();// 去除右侧空白字符void TrimRight();// 去除两侧空白字符void Trim();//反转CString & MakeReverse();//用于比较的函数int Compare(const char *str)const;int Compare(const CString &Str)const;int CompareNoCase(const char *str)const;int CompareNoCase(const CString &Str)const;// 连接两个CString对象,返回新对象friend CString operator+(const CString& string1, const CString& string2);friend CString operator+(const CString& string1, char ch);friend CString operator+(const CString& string1, const char* ch);friend CString operator+(const char *str, const CString &Str);friend CString operator+(char ch, const CString &Str);// 判断CString与C风格字符串是否相等friend bool operator==(const CString& string1, const char* ch);friend bool operator==(const CString& string1, const CString& string2);friend bool operator==(const char *str, const CString &Str);// 判断两个CString对象是否不相等friend bool operator!=(const CString& string1, const char* ch);friend bool operator!=(const CString& string1, const CString& string2);friend bool operator!=(const char *str, const CString &Str);// 比较两个CString对象大小(大于)friend bool operator> (const CString &Str1, const CString &Str2);friend bool operator> (const CString &Str, const char *str);friend bool operator> (const char *str, const CString &Str);// 比较两个CString对象大小(大于等于)friend bool operator>= (const CString &Str1, const CString &Str2);friend bool operator>=(const CString &Str, const char *str);friend bool operator>=(const char *str, const CString &Str);// 比较两个CString对象大小(小于)friend bool operator< (const CString &Str1, const CString &Str2);friend bool operator< (const CString &Str, const char *str);friend bool operator< (const char *str, const CString &Str);// 比较两个CString对象大小(小于等于)friend bool operator<= (const CString &Str1, const CString &Str2);friend bool operator<=(const CString &Str, const char *str);friend bool operator<=(const char *str, const CString &Str);private:// 字符串缓冲区指针(以'\0'结尾)char* m_pBuf;// 当前字符串长度(不包含终止符)int m_iLen;
};#endif // CSTRING_H

cstring.cpp

#include "CString.h"
#include <cstring>
#include <cstdarg>
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <stdexcept>  // 添加这个头文件以使用 std::out_of_range// 默认构造函数
CString::CString(): m_pBuf(nullptr), m_iLen(0)
{m_pBuf = new char[1];m_pBuf[0] = '\0'; // 初始化空字符串
}// 从C风格字符串构造
CString::CString(const char* lpsz): m_pBuf(nullptr), m_iLen(0)
{if(lpsz){m_iLen = strlen(lpsz);m_pBuf = new char[m_iLen + 1];strcpy(m_pBuf,  lpsz);}else{// 处理空指针输入m_pBuf = new char[1];m_pBuf[0] = '\0';}
}// 从单个字符构造
CString::CString(char ch): m_pBuf(nullptr), m_iLen(1)
{m_pBuf = new char[2];m_pBuf[0] = ch;m_pBuf[1] = '\0';
}// 拷贝构造函数
CString::CString(const CString& src): m_pBuf(nullptr), m_iLen(src.m_iLen)
{if(src.m_pBuf){m_pBuf = new char[m_iLen + 1];strcpy(m_pBuf, src.m_pBuf);}else{// 理论上不会执行,因为m_pBuf在其他构造函数中已初始化m_pBuf = new char[1];m_pBuf[0] = '\0';}
}//析构函数
CString::~CString()
{delete[] m_pBuf;m_pBuf = nullptr;
}// 获取指定索引位置的字符
char CString::GetAt(int iIndex) const
{if(iIndex >= m_iLen || iIndex < 0){// 越界时抛出异常throw std::out_of_range("Index out of range in GetAt");}return m_pBuf[iIndex];
}
//修改指定位置的字符
void CString::SetAt(int iIndex, char ch)
{if(iIndex >= m_iLen || iIndex < 0){// 越界时抛出异常throw std::out_of_range("Index out of range in SetAt");}m_pBuf[iIndex] = ch;
}
// 字符赋值运算符重载
CString& CString::operator=(char ch)
{// 释放原有内存delete[] m_pBuf;// 分配新内存(1个字符+终止符)m_iLen = 1;m_pBuf = new char[2];m_pBuf[0] = ch;m_pBuf[1] = '\0';return *this;
}
// C风格字符串赋值运算符重载
CString& CString::operator =(const char * lpsz)
{// 释放原有内存delete[] m_pBuf;if(lpsz){// 复制新字符串m_iLen = strlen(lpsz);m_pBuf = new char[m_iLen + 1];strcpy(m_pBuf, lpsz);}else{// 处理空指针(赋值为空字符串)m_iLen = 0;m_pBuf = new char[1];m_pBuf[0] = '\0';}return *this;
}
// 常量CString拷贝赋值运算符重载
CString& CString::operator=(const CString& string1)
{if(this != &string1)   // 防止自赋值{// 释放原有内存delete[] m_pBuf;// 复制新字符串m_iLen = string1.m_iLen;if(m_iLen > 0){m_pBuf = new char[m_iLen + 1];strcpy(m_pBuf, string1.m_pBuf);}else{m_pBuf = new char[1];m_pBuf[0] = '\0';}}return *this;
}// 字符追加运算符重载
CString& CString::operator+=(char ch)
{// 计算新长度int newLen = m_iLen + 1;// 分配新内存char* newBuf = new char[newLen + 1];// 复制原有内容if(m_iLen > 0){strcpy(newBuf, m_pBuf);}else{newBuf[0] = '\0'; // 确保空字符串以'\0'开头}// 添加字符newBuf[m_iLen] = ch;newBuf[newLen] = '\0'; // 终止字符串// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen = newLen;return *this;
}
// C风格字符串追加运算符重载
CString& CString::operator+=(const char *str)
{if(str && *str)  // 检查str不为空指针且不为空字符串{int len = strlen(str);int newLen = m_iLen + len;// 分配新内存char* newBuf = new char[newLen + 1];// 复制原有内容if(m_iLen > 0){strcpy(newBuf, m_pBuf);}else{newBuf[0] = '\0';  // 确保空字符串以'\0'开头}// 追加新字符串strcat(newBuf, str);// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen = newLen;}return *this;
}
// CString追加运算符重载
CString& CString::operator+=(const CString &Str)
{if(Str.m_iLen > 0)   // 检查Str不为空字符串{int newLen = m_iLen + Str.m_iLen;// 分配新内存char* newBuf = new char[newLen + 1];// 复制原有内容if(m_iLen > 0){strcpy(newBuf, m_pBuf);}else{newBuf[0] = '\0';  // 确保空字符串以'\0'开头}// 追加新字符串strcat(newBuf, Str.m_pBuf);// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen = newLen;}return *this;
}// 格式化字符串,功能类似sprintf,返回格式化后的长度
void CString::Format(const char* pstrFormat, ...)
{if(!pstrFormat){Empty();return ;}va_list args;va_start(args, pstrFormat);// 第一次调用 vsnprintf 计算所需缓冲区大小int requiredLen = vsnprintf(nullptr, 0, pstrFormat, args);va_end(args);// 错误处理:检查 vsnprintf 的返回值if(requiredLen < 0){// 处理格式化错误(例如格式字符串包含无效格式说明符)Empty();// 可选择抛出异常或设置错误标志throw std::runtime_error("Format error: invalid format string");// 或者返回错误码(需要修改函数返回类型)return ;}// 分配内存char* newBuf =  new char[requiredLen + 1];// 第二次调用 vsnprintf 格式化字符串va_start(args, pstrFormat);int actualWritten = vsnprintf(newBuf, requiredLen + 1, pstrFormat, args);va_end(args);// 再次检查返回值(理论上不会失败,但为了健壮性)if(actualWritten < 0 || actualWritten > requiredLen){delete[] newBuf;Empty();throw std::runtime_error("Format error: unexpected write failure");}// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen = requiredLen;return ;
}// 返回字符串长度(不包含终止符)
int CString::GetLength() const
{return m_iLen;
}
// 截取左边nCount个字符的子串
CString CString::Left(int nCount) const
{CString result;// 处理无效参数if(nCount <= 0){return result;  // 返回空字符串}// 限制截取长度不超过原字符串长度int actualCount = (nCount > m_iLen) ? m_iLen : nCount;// 分配内存并复制子串delete[] result.m_pBuf;result.m_pBuf = new char[actualCount + 1];memcpy(result.m_pBuf, m_pBuf, actualCount);result.m_pBuf[actualCount] = '\0';  // 添加终止符result.m_iLen = actualCount;return result;
}
// 截取右边nCount个字符的子串
CString CString::Right(int nCount) const
{CString result;// 处理无效参数if(nCount <= 0){return result;  // 返回空字符串}// 限制截取长度不超过原字符串长度int actualCount = (nCount > m_iLen) ? m_iLen : nCount;int startPos = m_iLen - actualCount;  // 计算起始位置// 分配内存并复制子串delete[] result.m_pBuf;result.m_pBuf = new char[actualCount + 1];memcpy(result.m_pBuf, m_pBuf + startPos, actualCount);result.m_pBuf[actualCount] = '\0';  // 添加终止符result.m_iLen = actualCount;return result;
}// 从nFirst开始到末尾的子串
CString CString::Mid(int nFirst) const
{CString result;// 处理无效参数(负数或超出长度)if(nFirst < 0 || nFirst >= m_iLen){return result;  // 返回空字符串}// 计算子串长度int subLen = m_iLen - nFirst;// 分配内存并复制子串delete[] result.m_pBuf;result.m_pBuf = new char[subLen + 1];memcpy(result.m_pBuf, m_pBuf + nFirst, subLen);result.m_pBuf[subLen] = '\0';  // 添加终止符result.m_iLen = subLen;return result;
}
// 从nFirst开始截取nCount个字符的子串
CString CString::Mid(int nFirst, int nCount) const
{CString result;// 处理无效参数if(nFirst < 0 || nFirst >= m_iLen || nCount <= 0){return result;  // 返回空字符串}// 计算实际截取长度(避免越界)int actualCount = nCount;if(nFirst + actualCount > m_iLen){actualCount = m_iLen - nFirst;if(actualCount <= 0) return result;   // 起始位置已超出末尾}// 分配内存并复制子串delete[] result.m_pBuf;result.m_pBuf = new char[actualCount + 1];memcpy(result.m_pBuf, m_pBuf + nFirst, actualCount);result.m_pBuf[actualCount] = '\0';  // 添加终止符result.m_iLen = actualCount;return result;
}
// 判断字符串是否为空
bool CString::IsEmpty() const
{return (m_iLen == 0);
}
// 清空字符串内容
void CString::Empty()
{// 释放原有内存delete[] m_pBuf;m_pBuf = nullptr;// 重置为初始状态(空字符串)m_iLen = 0;m_pBuf = new char[1];m_pBuf[0] = '\0';
}
// 获取内部缓冲区指针,用于直接操作内存
char* CString::GetBuffer(int nMinBufLength)
{if(nMinBufLength < 0 || nMinBufLength > m_iLen){return nullptr;}return m_pBuf + nMinBufLength;
}
//查找字符首次出现的位置,失败返回-1
int CString::Find(char ch) const
{for(int i = 0; i < m_iLen; i++){if(m_pBuf[i] == ch){return i;}}return -1;
}
int CString::Find(char ch, int nStart) const
{// 检查起始位置是否合法if(nStart < 0 || nStart >= m_iLen)return -1;// 从nStart位置开始查找字符chfor(int i = nStart; i < m_iLen; i++){if(m_pBuf[i] == ch)return i;  // 找到字符,返回其位置}return -1;  // 未找到字符
}
//查找子字符串首次出现的位置,失败返回-1
int CString::Find(const char* lpszSub) const
{if(!lpszSub || !*lpszSub) return -1;  // 处理空指针或空字符串int subLen = strlen(lpszSub);if(subLen > m_iLen) return -1;  // 子串长度超过原字符串const char* pos = strstr(m_pBuf, lpszSub);if(pos){return pos - m_pBuf; // 计算相对位置}return -1; // 未找到匹配子串
}//查找CString对象首次出现的位置,失败返回-1
int CString::Find(CString sSub) const
{if(sSub.IsEmpty()) return -1;return Find(sSub.GetBuffer(0));
}
//从索引uiBegin开始,返回字符串str第一次出现的位置,省略uiBegin使其为默认的0,未找到返回-1
int CString::Find(const char *str, int uiBegin) const
{if(!str || !*str) return -1;  // 空字符串直接返回-1int lenStr = strlen(str);if(lenStr > m_iLen) return -1;  // 查找的字符串比原字符串长// 处理无效的起始位置if(uiBegin < 0) uiBegin = 0;if(uiBegin > m_iLen - lenStr) return -1;  // 剩余长度不足const char *pStart = m_pBuf + uiBegin;const char *pEnd = m_pBuf + m_iLen - lenStr + 1;// 使用strstr进行高效查找const char *pFound = strstr(pStart, str);if(pFound && pFound < pEnd){return pFound - m_pBuf; // 计算相对位置}return -1; // 未找到匹配的子字符串
}// 连接两个CString对象,返回新对象
CString operator+(const CString& string1, const CString& string2)
{int len1 = string1.GetLength();int len2 = string2.GetLength();char* pchar = new char[len1 + len2 + 1];memset(pchar, '\0', len1 + len2 + 1);// 直接访问m_pBufmemcpy(pchar, string1.m_pBuf, len1);memcpy(pchar + len1, string2.m_pBuf, len2);CString strTemp(pchar);delete[] pchar;return strTemp;
}
// CString连接字符,返回新对象
CString operator+(const CString& string1, char ch)
{int len1 = string1.GetLength();char* pchar = new char[len1 + 2];memset(pchar, '\0', len1 + 2);memcpy(pchar, string1.m_pBuf, len1);pchar[len1] = ch;CString strTemp(pchar);delete[] pchar;return strTemp;
}
// CString连接C风格字符串,返回新对象
CString operator+(const CString& string1, const char* ch)
{if(!ch){return CString("");}int len1 = string1.GetLength();int len2 = strlen(ch);char* buffer = new char[len1 + len2 + 1];memcpy(buffer, string1.m_pBuf, len1);memcpy(buffer + len1, ch, len2);buffer[len1 + len2] = '\0';CString result(buffer);delete[] buffer;return result;
}
// 实现字符串常量与CString相加
CString operator+ (const char *str, const CString &Str)
{if(str == nullptr) return CString(Str);int len = strlen(str);CString result;result.m_iLen = len + Str.m_iLen;result.m_pBuf = new char[result.m_iLen + 1];strcpy(result.m_pBuf, str);strcat(result.m_pBuf, Str.m_pBuf);return result;
}// 实现字符与CString相加
CString operator+ (char ch, const CString &Str)
{CString result;result.m_iLen = 1 + Str.m_iLen;result.m_pBuf = new char[result.m_iLen + 1];result.m_pBuf[0] = ch;strcpy(result.m_pBuf + 1, Str.m_pBuf);result.m_pBuf[result.m_iLen] = '\0';return result;
}
// 判断CString与C风格字符串是否不相等
bool operator!=(const CString& string1, const char* ch)
{// 处理ch为nullptr的情况if(!ch){return !string1.IsEmpty();  // string1非空时返回true}// 使用strcmp比较内容return strcmp(string1.m_pBuf, ch) != 0;
}
// 判断CString与C风格字符串是否相等
bool operator==(const CString& string1, const char* ch)
{// 处理ch为nullptr的情况if(!ch){return string1.IsEmpty();  // string1为空时返回true}// 使用strcmp比较内容return strcmp(string1.m_pBuf, ch) == 0;
}
// 判断两个CString对象是否相等
bool operator==(const CString& string1, const CString& string2)
{if(string1.GetLength() != string2.GetLength()){return false;}return strcmp(string1.m_pBuf, string2.m_pBuf) == 0;
}
bool operator==(const char *str, const CString &Str)
{// 处理str为nullptr的情况if(str == nullptr){return Str.m_iLen == 0; // nullptr只能与空字符串相等}// 比较长度是否一致if(strlen(str) != Str.m_iLen){return false;}// 逐个字符比较内容return strncmp(str, Str.m_pBuf, Str.m_iLen) == 0;
}// 判断两个CString对象是否不相等
bool operator!=(const CString& string1, const CString& string2)
{// 长度不同则直接不相等if(string1.GetLength() != string2.GetLength()){return true;}// 使用strcmp比较内容return strcmp(string1.m_pBuf, string2.m_pBuf) != 0;
}
//将字符串转化为一个大写的字符串
void CString::MakeUpper()
{for(int i = 0; i < m_iLen; i++){if(m_pBuf[i] >= 'a' && m_pBuf[i] <= 'z'){m_pBuf[i] -= 32;  // 转换为大写(ASCII码差值为32)}}
}
//将字符串转化为一个小写的字符串
void CString::MakeLower()
{for(int i = 0; i < m_iLen; i++){if(m_pBuf[i] >= 'A' && m_pBuf[i] <= 'Z'){m_pBuf[i] += 32;  // 转换为小写(ASCII码差值为32)}}
}
void CString::TrimLeft()
{int i = 0;// 查找第一个非空白字符的位置while(m_pBuf[i] != '\0' && isspace(m_pBuf[i]))i++;// 如果存在前导空白字符,则移动字符串if(i > 0){memmove(m_pBuf, m_pBuf + i, m_iLen - i + 1);  // 包含终止符'\0'm_iLen -= i;}
}void CString::TrimRight()
{int i = m_iLen - 1;// 查找最后一个非空白字符的位置while(i >= 0 && isspace(m_pBuf[i]))i--;// 如果存在尾部空白字符,则设置新的字符串长度并添加终止符if(i < m_iLen - 1){m_iLen = i + 1;m_pBuf[m_iLen] = '\0';}
}
//去掉左右两边的空格
void CString::Trim()
{TrimLeft();TrimRight();
}// 比较两个CString对象大小(大于)
bool operator>(const CString &Str1, const CString &Str2)
{return strcmp(Str1.m_pBuf, Str2.m_pBuf) > 0;
}
// 比较两个CString对象大小(小于)
bool operator<(const CString &Str1, const CString &Str2)
{return strcmp(Str1.m_pBuf, Str2.m_pBuf) < 0;
}
// 比较两个CString对象大小(大于等于)
bool operator>=(const CString &Str1, const CString &Str2)
{return strcmp(Str1.m_pBuf, Str2.m_pBuf) >= 0;
}
// 比较两个CString对象大小(小于等于)
bool operator<=(const CString &Str1, const CString &Str2)
{return strcmp(Str1.m_pBuf, Str2.m_pBuf) <= 0;
}
// 下标运算符重载
char& CString::operator[](int iIndex)
{if(iIndex >= m_iLen || iIndex < 0){// 越界时抛出异常throw std::out_of_range("Index out of range in operator[]");}return m_pBuf[iIndex];
}// 常量版本的下标运算符重载
const char& CString::operator[](int iIndex) const
{if(iIndex >= m_iLen || iIndex < 0){// 越界时抛出异常throw std::out_of_range("Index out of range in operator[] const");}return m_pBuf[iIndex];
}
//反转
CString& CString::MakeReverse()
{int left = 0;int right = m_iLen - 1;while(left < right){// 交换左右字符char temp = m_pBuf[left];m_pBuf[left] = m_pBuf[right];m_pBuf[right] = temp;left++;right--;}return *this;  // 返回自身引用,支持链式调用
}
// 查找字符最后一次出现的位置,失败返回-1
int CString::ReverseFind(char ch) const
{for(int i = m_iLen - 1; i >= 0; i--){if(m_pBuf[i] == ch){return i;}}return -1; // 未找到
}// 替换所有指定字符,返回替换次数
int CString::Replace(char chOld, char chNew)
{int count = 0;for(int i = 0; i < m_iLen; i++){if(m_pBuf[i] == chOld){m_pBuf[i] = chNew;count++;}}return count;
}// 替换所有子字符串,返回替换次数
int CString::Replace(const char* lpszOld, const char* lpszNew)
{if(!lpszOld || !*lpszOld){return 0;}if(!lpszNew){throw std::invalid_argument("lpszNew is nullptr");}int lenOld = strlen(lpszOld);int lenNew = strlen(lpszNew);int count = 0;// 计算替换后的新长度int newLen = m_iLen;const char* p = m_pBuf;while((p = strstr(p, lpszOld))){newLen += lenNew - lenOld;p += lenOld;count++;}if(count == 0) return 0;   // 没有找到匹配项// 分配新缓冲区char* newBuf = new char[newLen + 1];char* dest = newBuf;const char* src = m_pBuf;// 执行替换while(*src){if(strncmp(src, lpszOld, lenOld) == 0){memcpy(dest, lpszNew, lenNew);dest += lenNew;src += lenOld;}else{*dest++ = *src++;}}*dest = '\0'; // 终止字符串// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen = newLen;return count;
}// 删除所有指定字符,返回删除次数
int CString::Remove(char ch)
{int count = 0;char* dest = m_pBuf;for(int i = 0; i < m_iLen; i++){if(m_pBuf[i] != ch){*dest++ = m_pBuf[i];}else{count++;}}*dest = '\0'; // 终止字符串m_iLen -= count;return count;
}// 在指定位置插入字符,返回新字符串长度
int CString::Insert(int nIndex, char ch)
{if(nIndex < 0){throw std::out_of_range("Insert position is negative");}if(nIndex > m_iLen){throw std::out_of_range("Insert position is greater than the current length");}// 分配新缓冲区char* newBuf = new char[m_iLen + 2]; // +1 为插入的字符,+1 为终止符// 复制前半部分memcpy(newBuf, m_pBuf, nIndex);// 插入字符newBuf[nIndex] = ch;// 复制后半部分memcpy(newBuf + nIndex + 1, m_pBuf + nIndex, m_iLen - nIndex);// 终止字符串newBuf[m_iLen + 1] = '\0';// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen++;return m_iLen;
}// 在指定位置插入字符串,返回新字符串长度
int CString::Insert(int nIndex, char* lpsz)
{if(!lpsz){throw std::invalid_argument("lpsz is nullptr");}if(nIndex < 0){throw std::out_of_range("Insert position is negative");}if(nIndex > m_iLen){throw std::out_of_range("Insert position is greater than the current length");}int lenInsert = strlen(lpsz);// 分配新缓冲区char* newBuf = new char[m_iLen + lenInsert + 1];// 复制前半部分memcpy(newBuf, m_pBuf, nIndex);// 插入字符串memcpy(newBuf + nIndex, lpsz, lenInsert);// 复制后半部分memcpy(newBuf + nIndex + lenInsert, m_pBuf + nIndex, m_iLen - nIndex);// 终止字符串newBuf[m_iLen + lenInsert] = '\0';// 更新对象状态delete[] m_pBuf;m_pBuf = newBuf;m_iLen += lenInsert;return m_iLen;
}// 删除指定位置开始的nCount个字符,返回剩余字符串长度
int CString::Delete(int nIndex, int nCount)
{if(nIndex < 0 || nIndex >= m_iLen){throw std::out_of_range("Delete position is out of range");}if(nCount <= 0){throw std::invalid_argument("nCount should be greater than 0");}// 确保不越界if(nIndex + nCount > m_iLen){nCount = m_iLen - nIndex;}// 移动后面的字符覆盖删除部分memmove(m_pBuf + nIndex, m_pBuf + nIndex + nCount, m_iLen - (nIndex + nCount) + 1);// 更新长度m_iLen -= nCount;return m_iLen;
}
//在当前字符串中查找 lpszCharSet 中任意一个字符首次出现的位置
int CString::FindOneOf(const char* lpszCharSet) const
{if(!lpszCharSet || !*lpszCharSet)return -1;  // 空字符集for(int i = 0; i < m_iLen; i++){for(const char* p = lpszCharSet; *p; p++){if(m_pBuf[i] == *p){return i; // 找到第一个匹配字符的位置}}}return -1; // 未找到任何匹配字符
}
bool operator!=(const char *str, const CString &Str)
{if(str == nullptr)return Str.m_iLen != 0;return strlen(str) != Str.m_iLen || strncmp(str, Str.m_pBuf, Str.m_iLen) != 0;
}bool operator< (const CString &Str, const char *str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return false; // 非空字符串不小于nullptr}// 使用strcmp比较两个字符串return strcmp(Str.m_pBuf, str) < 0;
}bool operator< (const char *str, const CString &Str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return Str.m_iLen > 0; // nullptr小于任何非空字符串}// 使用strcmp比较两个字符串return strcmp(str, Str.m_pBuf) < 0;
}bool operator> (const CString &Str, const char *str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return Str.m_iLen > 0; // 非空字符串大于nullptr}// 使用strcmp比较两个字符串return strcmp(Str.m_pBuf, str) > 0;
}bool operator<=(const CString &Str, const char *str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return Str.m_iLen == 0; // 仅空字符串<=nullptr}// 使用strcmp比较两个字符串return strcmp(Str.m_pBuf, str) <= 0;
}bool operator<=(const char *str, const CString &Str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return true; // nullptr小于等于任何字符串}// 使用strcmp比较两个字符串return strcmp(str, Str.m_pBuf) <= 0;
}bool operator> (const char *str, const CString &Str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return false; // nullptr不大于任何字符串}// 使用strcmp比较两个字符串return strcmp(str, Str.m_pBuf) > 0;
}// 比较CString对象是否大于等于字符串常量(按字典序)bool operator>=(const CString &Str, const char *str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return true; // 任何字符串都大于等于nullptr}// 使用strcmp比较两个字符串return strcmp(Str.m_pBuf, str) >= 0;
}// 比较字符串常量是否大于等于CString对象(按字典序)bool operator>=(const char *str, const CString &Str)
{// 处理str为nullptr的情况:nullptr视为最小字符串if(str == nullptr){return Str.m_iLen == 0; // nullptr仅大于等于空字符串}// 使用strcmp比较两个字符串return strcmp(str, Str.m_pBuf) >= 0;
}int CString::Compare(const char *str) const
{if(str == nullptr){return m_iLen > 0 ? 1 : 0; // nullptr视为空字符串}return strcmp(m_pBuf, str);
}int CString::Compare(const CString &Str) const
{return strcmp(m_pBuf, Str.m_pBuf);
}int CString::CompareNoCase(const char *str) const
{if(str == nullptr){return m_iLen > 0 ? 1 : 0; // nullptr视为空字符串}return strcasecmp(m_pBuf, str); // Windows: _stricmp, Linux: strcasecmp
}int CString::CompareNoCase(const CString &Str) const
{return strcasecmp(m_pBuf, Str.m_pBuf); // Windows: _stricmp, Linux: strcasecmp
}

测试代码

void testConstructors()
{// 默认构造函数CString s1;assert(s1.GetLength() == 0);assert(s1.IsEmpty());// 从C风格字符串构造CString s2("Hello");assert(s2.GetLength() == 5);assert(strcmp(s2.GetBuffer(0), "Hello") == 0);// 从单个字符构造CString s3('A');assert(s3.GetLength() == 1);assert(s3.GetAt(0) == 'A');// 复制构造函数CString s4(s2);assert(s4.GetLength() == 5);assert(strcmp(s4.GetBuffer(0), "Hello") == 0);
}void testGetLengthAndIsEmpty()
{CString s;assert(s.GetLength() == 0);assert(s.IsEmpty());s = "Test";assert(s.GetLength() == 4);assert(!s.IsEmpty());s.Empty();assert(s.GetLength() == 0);assert(s.IsEmpty());
}void testElementAccess()
{CString s("abc");assert(s.GetAt(0) == 'a');assert(s[1] == 'b');s.SetAt(1, 'X');assert(s[1] == 'X');const CString cs("test");assert(cs[2] == 's');
}void testFindAndReverseFind()
{CString s("Hello World");assert(s.Find('o') == 4);assert(s.Find('o', 5) == 7);assert(s.Find("World") == 6);assert(s.Find("xyz") == -1);assert(s.ReverseFind('l') == 9);assert(s.FindOneOf("aeiou") == 1);assert(s.Find('d',10)==10);
}void testModifyString()
{CString s("Hello");// Replaceassert(s.Replace('l', 'L') == 2);assert(strcmp(s.GetBuffer(0), "HeLLo") == 0);// Removeassert(s.Remove('L') == 2);assert(strcmp(s.GetBuffer(0), "Heo") == 0);// Insertassert(s.Insert(2, 'l') == 4);assert(strcmp(s.GetBuffer(0), "Helo") == 0);assert(s.Insert(3, "lo") == 6);assert(strcmp(s.GetBuffer(0), "Helloo") == 0);// Deleteassert(s.Delete(2, 3) == 3);assert(strcmp(s.GetBuffer(0), "Heo") == 0);
}void testAssignmentOperators()
{CString s;// 字符赋值s = 'A';assert(s.GetLength() == 1);assert(s[0] == 'A');// C风格字符串赋值s = "Test";assert(s.GetLength() == 4);assert(strcmp(s.GetBuffer(0), "Test") == 0);// CString赋值CString s2("Copy");s = s2;assert(s.GetLength() == 4);assert(strcmp(s.GetBuffer(0), "Copy") == 0);
}void testAppendOperators()
{CString s("Hello");// 追加字符s += ' ';assert(strcmp(s.GetBuffer(0), "Hello ") == 0);// 追加C风格字符串s += "World";assert(strcmp(s.GetBuffer(0), "Hello World") == 0);// 追加CStringCString suffix("!");s += suffix;assert(strcmp(s.GetBuffer(0), "Hello World!") == 0);
}void testFormat()
{CString s;s.Format("%d + %d = %d", 2, 3, 5);assert(strcmp(s.GetBuffer(0), "2 + 3 = 5") == 0);float value=1.234;s.Format("%.2f",value);assert(strcmp(s.GetBuffer(0), "1.23") == 0);s.Format("%02x",55);printf("s=%s\n",s.GetBuffer(0));assert(strcmp(s.GetBuffer(0), "37") == 0);
}void testSubstring()
{CString s("HelloWorld");assert(strcmp(s.Left(5).GetBuffer(0), "Hello") == 0);assert(strcmp(s.Right(5).GetBuffer(0), "World") == 0);assert(strcmp(s.Mid(5).GetBuffer(0), "World") == 0);assert(strcmp(s.Mid(1, 3).GetBuffer(0), "ell") == 0);
}void testCaseConversion()
{CString s("Hello");s.MakeUpper();assert(strcmp(s.GetBuffer(0), "HELLO") == 0);s.MakeLower();assert(strcmp(s.GetBuffer(0), "hello") == 0);
}void testTrim()
{CString s("  \tHello World!  \n");CString s2("             ");s2.Trim();assert(s2.IsEmpty());s.TrimLeft();assert(strcmp(s.GetBuffer(0), "Hello World!  \n") == 0);s.TrimRight();assert(strcmp(s.GetBuffer(0), "Hello World!") == 0);s = "  \t Test \t  ";s.Trim();assert(strcmp(s.GetBuffer(0), "Test") == 0);
}void testReverse()
{CString s("abc");s.MakeReverse();assert(strcmp(s.GetBuffer(0), "cba") == 0);
}void testConcatenation()
{CString s1("Hello");CString s2(" World");CString s3 = s1 + s2;assert(strcmp(s3.GetBuffer(0), "Hello World") == 0);CString s4 = s1 + '!';assert(strcmp(s4.GetBuffer(0), "Hello!") == 0);CString s5 = "Hi" + s1;assert(strcmp(s5.GetBuffer(0), "HiHello") == 0);CString s6 = 'A' + s1;assert(strcmp(s6.GetBuffer(0), "AHello") == 0);
}void testComparisonOperators()
{CString s1("abc");CString s2("abc");CString s3("abd");// ==assert(s1 == s2);assert(s1 == "abc");assert("abc" == s1);// !=assert(s1 != s3);assert(s1 != "abd");assert("abd" != s1);// >assert(s3 > s1);assert(s3 > "abc");assert("abd" > s1);// >=assert(s1 >= s2);assert(s3 >= s1);assert(s1 >= "abc");assert("abd" >= s1);// <assert(s1 < s3);assert(s1 < "abd");assert("abc" < s3);// <=assert(s1 <= s2);assert(s1 <= s3);assert(s1 <= "abd");assert("abc" <= s3);
}
void testCompare()
{CString s1("Hello");CString s2("hello");int r1 = s1.Compare("Hello");    // 0assert(r1==0);int r2 = s1.Compare("World");    // <0assert(r2<0);int r3 = s1.CompareNoCase("HELLO"); // 0assert(r3==0);int r4 = s1.Compare(s2);         // <0 (大小写敏感)assert(r4<0);int r5 = s1.CompareNoCase(s2);   // 0 (大小写不敏感)assert(r5==0);
}

相关文章:

  • 奥运数据可视化:探索数据讲述奥运故事
  • w~深度学习~合集3
  • PyTorch 的 F.scaled_dot_product_attention 返回Nan
  • 三格电子上新了——Modbus转IEC104网关
  • C42-作业练习
  • 速通RocketMQ配置
  • MySQL——3、数据类型
  • YOLOv8在单目向下多车辆目标检测中的应用
  • VsCode和AI的前端使用体验:分别使用了Copilot、通义灵码、iflyCode和Trae
  • CentOS系统中升级Python 3.12.2版本
  • 基于对抗性后训练的快速文本到音频生成:stable-audio-open-small 模型论文速读
  • 火语言RPA--EmpireV7下载发布
  • 【大模型面试每日一题】Day 20:大模型出现“幻觉”(Hallucination)的可能原因有哪些?如何从数据或训练层面缓解?
  • nosqlbooster pojie NoSQLBooster for MongoDB
  • 4.2.3 Thymeleaf标准表达式 - 5. 片段表达式
  • SAP ABAP 程序中归档数据读取方式
  • 在服务器上安装AlphaFold2遇到的问题(1)
  • 街景主观感知全流程(自建数据集+两两对比程序+Trueskill计算评分代码+训练模型+大规模预测)11
  • 在服务器上安装AlphaFold2遇到的问题(3)_cat: /usr/include/cudnn_version.h: 没有那个文件或目录
  • 【洗车店专用软件】佳易王洗车店多项目会员管理系统:一卡多用扣次软件系统实操教程 #扣次洗车管理软件
  • 金融月评|尽早增强政策力度、调整施策点
  • 缅甸内观冥想的历史漂流:从心理治疗室到“非语言现场”
  • 光明日报:家长孩子共同“息屏”,也要保证高质量陪伴
  • 腾讯一季度营收增长13%,马化腾:战略性的AI投入将带来长期回报
  • 《歌手2025》公布首发阵容,第一期就要淘汰一人
  • 中国海警舰艇编队5月14日在我钓鱼岛领海巡航