您的位置:首页 > 编程语言 > C语言/C++

标准C++实现字符串类CString

2012-11-13 11:41 295 查看
// String.cpp: implementation of the CString class.

//

//////////////////////////////////////////////////////////////////////

#include "String.h"

#include <stdio.h>

#include <stdlib.h>

#include <stdarg.h>

#include <string.h>

#include <ctype.h>

#if defined(WIN32)

#include <windows.h>

#elif defined(linux)

#elif defined(_AIX)

#include <extension.h>

#else

#endif

#ifdef _xlC

#include <strings.h>

#endif

#include "macros.h"

#include "String.h"

using namespace clib;

// constructors

// allocate buffers

CString::CString(int iBufferNum)

{

m_pBuffer = new char[iBufferNum * STR_PAGE_SIZE]; //动态申请内存

m_nLength = 0; //长度

m_nSize = iBufferNum * STR_PAGE_SIZE; //字符串大小初始化为iBufferNum个4*1024

m_pDataStart = m_pDataEnd = m_pBuffer; //开始字符串指针全部指向m_pBuffer

}

// new one character

CString::CString(char c, int iBufferNum) //参数为字符c和iBufferNum,构造函数

{

char data[2], len = 2;

data[0] = c; //将c放在字符数组首位

data[1] = 0; //将字符数组data第二位置为0

if (len > iBufferNum * STR_PAGE_SIZE) //如果iBufferNum个4*1024小于3

{

m_pBuffer = new char[len + 1]; //为字符串类的主要字符串m_pBuffer动态申请内存空间

m_nSize = len + 1; //字符串大小为3

}

else

{

m_pBuffer = new char[iBufferNum * STR_PAGE_SIZE]; //字符串申请内存空间

m_nSize = iBufferNum * STR_PAGE_SIZE;

}

// copy data and set total length

CreateFromData(data, len); //根据字符数组data开始创建对象m_pDataStart和m_pDataEnd

}

// copy data from a null terminated string

CString::CString(const char *data, int iBufferNum)

{

long len = strlen(data);

if (len > iBufferNum * STR_PAGE_SIZE) //字符串的大小大于制定数量个4*1024

{

m_pBuffer = new char[len + 1]; // 动态申请内存空间

m_nSize = len + 1;

}

else

{

m_pBuffer = new char[iBufferNum * STR_PAGE_SIZE];

m_nSize = iBufferNum * STR_PAGE_SIZE;

}

// copy data and set total length

CreateFromData(data, len); //根据字符数组data开始创建对象m_pDataStart和m_pDataEnd

}

// copy data from a binary data

CString::CString(const char *data, long len, int iBufferNum) //构造函数的参数为字符串

{

if (len > iBufferNum * STR_PAGE_SIZE) //如果字符串的大小大于制定数量个4*1024

{

m_pBuffer = new char[len + 1]; // 动态申请内存空间

m_nSize = len + 1;

}

else

{

m_pBuffer = new char[iBufferNum * STR_PAGE_SIZE];

m_nSize = iBufferNum * STR_PAGE_SIZE;

}

// copy data and set total length

CreateFromData(data, len); //根据字符数组data开始创建对象m_pDataStart和m_pDataEnd

}

// destructor

CString::~CString(void)

{

SafeDestroy();

}

// destroy allocated memory space and init all pointers

void CString::SafeDestroy(void)

{

SAFEDELETE(m_pBuffer);

// Important for InitPointers()

m_nSize = 0;

Empty();

}

void CString::Empty(void)

{

#ifdef WIN32

ZeroMemory(m_pBuffer, m_nSize);

#else // Linux, AIX

memset(m_pBuffer, 0, m_nSize);

#endif

m_pDataStart = m_pDataEnd = m_pBuffer; //将该字符串的头指针和尾指针全部指向字符串的头部

m_nLength = 0; //字符串长度置为0

}

char *CString::GetData(void) const //获得指向该字符串的头部指针

{

return m_pDataStart;

}

int CString::CreateFromData(const char *data, long len) //根据data和长度len创建对象

{

Empty(); //清空

if (len <= 0)

return TRUE;

if (data == NULL)

return TRUE;

// actually, it's impossible

if (len > m_nSize)

return FALSE;

// copy data and set length

memcpy(m_pDataStart, data, len); //将字符数组复制给m_pDataStart指向内存空间

m_nLength = len;

m_pDataStart[m_nLength] = '\0';

m_pDataEnd = &(m_pDataStart[m_nLength]); //取得尾指针m_pDataEnd

return TRUE;

}

long CString::GetLength(void) const

{

return m_nLength;

}

int CString::IsEmpty(void) const

{

return !m_nLength;

}

int CString::Grow(int iBufferNum)

{

//unsigned char *pNewSpace = NULL;

if (iBufferNum <= 0)

return 0;

AssignNewSpace(m_nSize + iBufferNum * STR_PAGE_SIZE, 1); //分配新的内存空间,变为原来的两倍,移动1倍

return 1;

}

int CString::Append(const char *pSrc, int iLen)

{

int total_len;

char *pNewStart = NULL;

if (iLen <= 0)

return 0;

total_len = m_nLength + iLen; //append后的总的字符串长度

// if some space avaliable, defrag it firstly.

if (m_nSize > total_len) //如果原来总内存空间长度大于append后的字符串长度

{

//如果原来剩余空闲空间小于新添加子字符串的长度,而且

if (m_nSize - (m_pDataEnd - m_pBuffer) < iLen && m_pDataStart - m_pBuffer > 0) //而且m_pDataStart在m_pBuffer的后面

{

Defrag(); //调节原来的字符串

}

}

else //如果原来总内存空间长小于append后的字符串长度,需要开辟新空间

{

// allocate new memory space and copy orignal data

AssignNewSpace(total_len + 1, 1); //分配新的内存空间,变为原来的两倍,移动1倍

}

// get the merge point

pNewStart = m_pDataEnd; //将原来字符串的末尾指针转变成新添加子串的开始指针

if (!pNewStart)

return 0;

// copy data and adjust some pointers

memcpy(pNewStart, pSrc, iLen); //将新添加串pSrc放置在原来串联的末尾

m_nLength = total_len; //字符串的总长度变化

m_pDataStart[m_nLength] = 0; //新的字符串最后以为置为0

m_pDataEnd = &(m_pDataStart[m_nLength]); //让m_pDataEnd指向新的字符串的末尾指针

return 1;

}

void CString::Defrag(void)

{

// Sure! 重新初始化原来字符串头指针m_pDataStart,指向头部

memmove(m_pBuffer, m_pDataStart, m_nLength); //将m_pDataStart复制给m_pBuffer

// adjust those related pointers

m_pDataStart = m_pBuffer; //m_pDataStart指向m_pBuffer

m_pDataStart[m_nLength] = 0;

m_pDataEnd = &(m_pDataStart[m_nLength]); //重新获得原来的字符串尾指针m_pDataEnd

}

// Append another CString to this one

int CString::Append(CString *pNewStr)

{

char *pNewStart = NULL, *pSrc = NULL, *pDest = NULL;

int len = pNewStr->GetLength(); //新添加子串的长度

int total_len;

if (len <= 0)

return 0;

// const char *

pSrc = pNewStr->GetData(); //获得要添加的字符串的头指针

if (!pSrc)

return 0;

total_len = m_nLength + len; //新字符串的总长度 = 原来字符串长度 + 添加字符串长度

// if some space avaliable, defrag it firstly.

if (m_nSize - (m_pDataEnd - m_pBuffer) < len && m_pDataStart - m_pBuffer > 0)

{

Defrag();

}

// allocate new memory space

AssignNewSpace(total_len + 1, 1); // //根据total_len分配新的内存空间

// get the merge point

pNewStart = m_pDataEnd; //将原来字符串的末尾指针转变成新添加子串的开始指针

if (!pNewStart)

return 0;

// copy data and adjust some pointers

memcpy(pNewStart, pSrc, len); //将新添加串pSrc放置在原来串联的末尾

m_nLength = total_len;

m_pDataStart[m_nLength] = 0;

m_pDataEnd = &(m_pDataStart[m_nLength]); //让m_pDataEnd指向新的字符串的末尾指针

return 1;

}

// Adjust start and end pointer of its buffer

// Get one character at give position

char CString::GetAt(int nIndex) const

{

if (nIndex >= m_nLength)

return -1;

if (nIndex < 0)

return -1;

return m_pDataStart[nIndex];

}

// return single character at zero-based index

char CString::operator[](int nIndex) const

{

if (nIndex >= m_nLength)

return -1;

return m_pDataStart[nIndex];

}

// return pointer to const string

CString::operator LPCTSTR() const //将该字符串转变为const char*字符串常量

{

return (const char*)m_pDataStart;

}

// duplicate a string

CString *CString::Duplicate(int iBufferNum) const

{

CString *pCStr = NULL;

pCStr = new CString(m_pDataStart, m_nLength, iBufferNum);

return pCStr;

}

// copy from another CString

const CString& CString::operator=(CString& stringSrc) //赋值操作符

{

long len = stringSrc.GetLength(); //取得stringSrc字符串长度

if (len >= m_nSize) //如果空间大小不够

{

AssignNewSpace(len + 1, 0); // don't copy orignal data //将会申请一块新的内存空间

}

// copy data and adjust pointers

Empty(); //清空

memcpy(m_pDataStart, stringSrc.GetData(), len); //将字符串stringSrc复制给新的m_pDataStart

m_pDataStart[len] = 0;

m_pDataEnd = &(m_pDataStart[len]); //获得新的m_pDataEnd

m_nLength = len;

return *this;

}

// set string content to single character

CString &CString::operator=(char c) //赋值操作符,将字符赋给字符串

{

if (m_nSize < 2) // c + '\0' length //如果内存空间不足

{ // it needs to realloc space, but we use new and delete pair

SafeDestroy();

m_pBuffer = new char[2]; //重新申请内存

m_nSize = 2;

//TODO, I don't check the value of this pointer, unkown result. :)

}

m_pDataStart = m_pBuffer; //获得头指针

m_pDataStart[0] = c;

m_pDataStart[1] = 0;

m_pDataEnd = &(m_pDataStart[1]); //获得尾指针

m_nLength = 1;

return *this;

}

// Set one character at give position

void CString::SetAt(long pos, char ch)

{

if (pos < m_nLength)

m_pDataStart[pos] = ch;

return;

}

// Get the string started from give position

void CString::GetManyChars(char *buf, long pos, long len) const

{

if (buf == NULL)

return;

if (pos >= m_nLength)

return;

if (pos + len > m_nLength)

len = m_nLength - pos;

if (len > 0)

memcpy(buf, m_pDataStart + pos, len); //将 m_pDataStart + pos开始长为len的子串复制给buf

}

// Compare itself with a new string, case-sensitive

int CString::Compare(const char *pNewStr) const

{

if (pNewStr == NULL)

return -1;

return strcmp(m_pDataStart, pNewStr);

}

// Compare itself with a new string, case-ignored

int CString::CompareNoCase(const char *pNewStr) const

{

if (pNewStr == NULL)

return -1;

#ifndef WIN32

return strcasecmp(m_pDataStart, pNewStr);

#else

return stricmp(m_pDataStart, pNewStr);

#endif

}

// find a character start from a give position

int CString::Find(int ch, long pos) const

{

char *p = NULL;

if (ch < 0)

return -1;

if (ch > UCHAR_MAX)

return -1;

if (pos < 0)

return -1;

if (pos >= m_nLength)

return -1;

p = (char*)memchr(m_pDataStart + pos, ch, m_nLength - pos);

if (!p)

return -1;

return p - m_pDataStart;

}

// find a string start from a give position

int CString::Find(const char *str, long pos) const

{

long len;

char *p = NULL;

if (str == NULL)

return -1;

len = strlen(str);

if (len == 0)

return 0;

p = (char *)strstr(m_pDataStart + pos, str);

if (p == NULL)

return -1;

else

return p - m_pDataStart;

}

char *CString::GetBuffer(int nMinBufLength) //获得该字符串头指针,并且说明返回的内存空间最小值

{

Defrag();

if (nMinBufLength > m_nLength)

AssignNewSpace(nMinBufLength, 1);

return m_pDataStart;

}

void CString::ReleaseBuffer(int nNewLength)

{

return;

}

//Extracts the left part of a string.

CString CString::Left(int count) const

{

if (count < 0)

count = 0;

if (count >= m_nLength)

return *this;

CString dest(m_pDataStart, count); //调用构造函数新建一个

return dest;

}

//Extracts the right part of a string.

CString CString::Right(int count) const

{

if (count < 0)

count = 0;

if (count >= m_nLength)

return *this;

CString dest(&(m_pDataStart[m_nLength - count]), count);

return dest;

}

//Converts all the characters in this string to uppercase characters.

void CString::MakeUpper(void)

{

strupr(m_pDataStart);

}

//Converts all the characters in this string to lowercase characters.

void CString::MakeLower(void)

{

strlwr(m_pDataStart);

}

// TODO: check the space left in the two pading of the whole buffer

// trim the left spaces

void CString::TrimLeft(void) // //将字符串右边的空格去掉

{

int start = 0;

while (isspace(m_pDataStart[start]) && start < m_nLength)

start ++;

if (start > 0)

{

m_pDataStart += start;

}

}

// trim the right spaces

void CString::TrimRight(void) //将字符串右边的空格去掉

{

int end = m_nLength - 1;

while (isspace(m_pDataStart[end]) && end >= 0)

end --;

if (end < 0)

{

end = 0;

m_pDataEnd = &(m_pDataStart[end]);

}

else

{

m_pDataEnd = &(m_pDataStart[end]);

}

}

// trim both sides

void CString::Trim(void) // //将字符串的空格去掉

{

TrimLeft();

TrimRight();

}

int CString::Replace(const char *lpszOld, const char *lpszNew)

{

// can't have empty or NULL lpszOld

if (!lpszOld)

return 0;

int nOldLen = strlen(lpszOld); //获得旧字符串的长度

if (nOldLen <= 0)

return 0;

int nNewLen = strlen(lpszNew); //获得新字符串的长度

// loop once to figure out the size of the result string

int nCount = 0;

char *lpszStart = m_pDataStart;

char *lpszEnd = m_pDataEnd;

char *lpszTarget;

while (lpszStart < lpszEnd) //循环处理原有字符串

{

while ((lpszTarget = strstr(lpszStart, lpszOld)) != NULL) //如果在字符串lpszStart中发现子串lpszOld

{

nCount++;
//子串数量+1

lpszStart = lpszTarget + nOldLen; //往后定位字符串lpszStart,从第一个子串后开始

}

lpszStart += strlen(lpszStart) + 1; //往后查找

}

// if any changes were made, make them

if (nCount > 0) //如果有重复的字符串

{

// allocate a new buffer (slow but sure)

int nNewLength = m_nLength + (nNewLen - nOldLen) * nCount; //覆盖后总字符串的大小

AssignNewSpace(nNewLength + 1, 1); //为新的字符串分配内存空间

// then we just do it in-place

lpszStart = m_pDataStart; //重新初始化m_pDataStart,lpszStart,lpszEnd

lpszEnd = m_pDataEnd;

// loop again to actually do the work

while (lpszStart < lpszEnd) //循环处理原来的字符串

{

while ( (lpszTarget = strstr(lpszStart, lpszOld)) != NULL) //如果在字符串lpszStart中发现子串lpszOld

{

int nBalance = lpszEnd - (lpszTarget + nOldLen); //字符串lpszTarget后面的字符数量

memmove(lpszTarget + nNewLen, lpszTarget + nOldLen,

nBalance * sizeof(char)); //移走lpszTarget原来的字符串,并为lpszTarget重新设置为nNewLen大小内存

memcpy(lpszTarget, lpszNew, nNewLen * sizeof(char)); //将新字符串lpszNew覆盖旧的子串lpszTarget

lpszStart = lpszTarget + nNewLen; //寻找目标字符串后移nNewLen

lpszStart[nBalance] = '\0';

}

lpszStart += strlen(lpszStart) + 1; //寻找目标字符串往后走

}

m_nLength = nNewLength;

}

return nCount;

}

// format a string

void CString::Format(char *fmt, ...)

{

char TmpBuffer[STR_PAGE_SIZE]; // TODO, should calculate this size dynamically.

va_list argList;

va_start(argList, fmt);

#ifdef WIN32

_vsnprintf(TmpBuffer, STR_PAGE_SIZE, fmt, argList); // just not overwrite something

#else

vsnprintf(TmpBuffer, STR_PAGE_SIZE, fmt, argList); // just not overwrite something

#endif

va_end(argList);

}

// copy string content from ANSI string (converts to TCHAR)

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

{

int len = strlen(lpsz);

if (m_nSize < len) // c + '\0' length

{ // it needs to realloc space, but we use new and delete pair

SafeDestroy();

m_pBuffer = new char[len + 1];

m_nSize = len + 1;

//TODO, I don't check the value of this pointer, unkown result. :)

}

m_pDataStart = m_pBuffer;

strcpy((char *)m_pDataStart, lpsz);

m_pDataStart[len] = 0;

m_pDataEnd = &(m_pDataStart[len]);

m_nLength = len;

return *this;

}

// concatenate a UNICODE character after converting it to TCHAR

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

{

int len = strlen(lpsz);

if (m_nSize < m_nLength + len + 1)

{

AssignNewSpace(m_nLength + len + 1, 1); // allocate new space and move orignal data

}

Defrag();

memcpy(m_pDataEnd, lpsz, len);

m_pDataEnd += len;

*m_pDataEnd = 0;

return *this;

}

// concatenate a single character

const CString& CString::operator+=(char ch)

{

if (m_nSize < m_nLength + 1 + 1)

{

AssignNewSpace(m_nLength + 1 + 1, 1); // allocate new space and move orignal data

}

Defrag();

memcpy(m_pDataEnd, &ch, 1);

m_pDataEnd += 1;

*m_pDataEnd = 0;

return *this;

}

// concatenate from another CString

const CString& CString::operator+=(CString& string)

{

if (m_nSize < m_nLength + string.GetLength() + 1)

{

AssignNewSpace(m_nLength + string.GetLength() + 1, 1); // allocate new space and move orignal data

}

Defrag();

memcpy(m_pDataEnd, string.GetData(), string.GetLength());

m_pDataEnd += string.GetLength();

*m_pDataEnd = 0;

return *this;

}

void CString::AssignNewSpace(int iNewTotalSize, int iNeedMove)

{

char *pNewSpace = NULL; //新的字符串指针,初始化NULL

if (iNewTotalSize <= m_nSize) //确保新的内存空间大于原来的内存空间

return ;

// allocate new space

pNewSpace = new char [iNewTotalSize]; //pNewSpace动态申请内存空间

if (pNewSpace == NULL)

return ;

if (iNeedMove)

{

memcpy(pNewSpace, m_pDataStart, m_nLength + 1); //将原有字符串复制给新申请内存

}

SAFEDELETE(m_pBuffer); //安全删除原有的字符串m_pBuffer

m_pBuffer = pNewSpace;

m_pDataStart = m_pBuffer;

m_pDataEnd = &(m_pDataStart[m_nLength]); //重置m_pBuffer,m_pDataStart,m_pDataEnd

// adjust new size

m_nSize = iNewTotalSize;

}

//////////////////////////////////////////////////////////////////////////////

// concatenation

// NOTE: "operator+" is done as friend functions for simplicity

// There are three variants:

// CString + CString

// and for ? = TCHAR, LPCTSTR

// CString + ?

// ? + CString

void CString::ConcatCopy(const char *str1, int nSrc1Len, const char *str2, int nSrc2Len)

{

int nNewLen = nSrc1Len + nSrc2Len;

AssignNewSpace(nNewLen + 1, 0);

// append two string

Append(str1, nSrc1Len);

Append(str2, nSrc2Len);

}

// friend methods

// Class + Class

CString operator+(const CString& string1, const CString& string2)

{

CString s;

s.ConcatCopy(string1.GetData(), string1.GetLength(), string2.GetData(), string2.GetLength());

return s;

}

// Class + char

CString operator+(const CString& string, char ch)

{

CString s;

char str[2];

str[0] = ch;

str[1] = 0;

s.ConcatCopy(string.GetData(), string.GetLength(), str, 1);

return s;

}

// char + Class

CString operator+(char ch, const CString& string)

{

CString s;

char str[2];

str[0] = ch;

str[1] = 0;

s.ConcatCopy(string.GetData(), string.GetLength(), str, 1);

return s;

}

// Class + char *

CString operator+(const CString& string, const char *lpsz)

{

CString s;

s.ConcatCopy(string.GetData(), string.GetLength(), lpsz, strlen(lpsz));

return s;

}

// char * + Class

CString operator+(const char *lpsz, const CString& string)

{

CString s;

s.ConcatCopy(string.GetData(), string.GetLength(), lpsz, strlen(lpsz));

return s;

}

// Compare operators

bool operator==(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) == 0);

}

bool operator==(const CString& s1, const char* s2)

{

return (s1.Compare(s2) == 0);

}

bool operator==(const char* s1, const CString& s2)

{

return (s2.Compare(s1) == 0);

}

bool operator!=(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) != 0);

}

bool operator!=(const CString& s1, const char* s2)

{

return (s1.Compare(s2) != 0);

}

bool operator!=(const char* s1, const CString& s2)

{

return (s2.Compare(s1) != 0);

}

bool operator>(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) > 0);

}

bool operator>(const CString& s1, const char* s2)

{

return (s1.Compare(s2) > 0);

}

bool operator>(const char* s1, const CString& s2)

{

return (s2.Compare(s1) < 0);

}

bool operator<(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) < 0);

}

bool operator<(const CString& s1, const char* s2)

{

return (s1.Compare(s2) < 0);

}

bool operator<(const char* s1, const CString& s2)

{

return (s2.Compare(s1) > 0);

}

bool operator>=(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) >= 0);

}

bool operator>=(const CString& s1, const char* s2)

{

return (s1.Compare(s2) >= 0);

}

bool operator>=(const char* s1, const CString& s2)

{

return (s2.Compare(s1) <= 0);

}

bool operator<=(const CString& s1, const CString& s2)

{

return (s1.Compare(s2.GetData()) <= 0);

}

bool operator<=(const CString& s1, const char* s2)

{

return (s1.Compare(s2) <= 0);

}

bool operator<=(const char* s1, const CString& s2)

{

return (s2.Compare(s1) >= 0);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: