// 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 }
// 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;
// set string content to single character CString &CString::operator=(char c) //赋值操作符,将字符赋给字符串 { if (m_nSize < 2) // c + " " 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;
//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] = " "; } 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 + " " 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;
// 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;