还不如自己重写一个类,或则改用STL中的string,那可是绝对提供了所有的源码。
解决方案 »
- 边界效应问题讨论
- 频域滤波器中 怎样理解截止频率
- 关于CHTMLVIEW::Navigate2的问题。
- 谁知道运行CMSHFlexGrid控件需要注册哪个ocx?
- 菜鸟求助:关于在Cview下面储存视图的问题
- BTW 关注有分
- 完成端口GetQueuedCompletionStatus中第四个参数的疑惑!!!
- 我用ShellExecute(NULL,"open","##",NULL, NULL, SW_SHOWNORMAL)函数调用了netmeeting软件!现在怎样把它嵌入一个已经分割好的窗口中啊
- 数字转化为图片问题
- 后台程序控制鼠标所在窗口(未激活的)的滚轮滚动问题
- How to 画一个“disable”项?
- 请问:怎样从子对话框中直接退出对话框?
在vc98\mfc\src\strex.cpp中实现。
CString::CString()
{
Init();
}
#endifCString::CString(const CString& stringSrc)
{
ASSERT(stringSrc.GetData()->nRefs != 0);
if (stringSrc.GetData()->nRefs >= 0)
{
ASSERT(stringSrc.GetData() != _afxDataNil);
m_pchData = stringSrc.m_pchData;
InterlockedIncrement(&GetData()->nRefs);
}
else
{
Init();
*this = stringSrc.m_pchData;
}
}#ifndef _DEBUG#pragma warning(disable: 4074)
#pragma init_seg(compiler)#define ROUND(x,y) (((x)+(y-1))&~(y-1))
#define ROUND4(x) ROUND(x, 4)
AFX_STATIC CFixedAlloc _afxAlloc64(ROUND4(65*sizeof(TCHAR)+sizeof(CStringData)));
AFX_STATIC CFixedAlloc _afxAlloc128(ROUND4(129*sizeof(TCHAR)+sizeof(CStringData)));
AFX_STATIC CFixedAlloc _afxAlloc256(ROUND4(257*sizeof(TCHAR)+sizeof(CStringData)));
AFX_STATIC CFixedAlloc _afxAlloc512(ROUND4(513*sizeof(TCHAR)+sizeof(CStringData)));#endif //!_DEBUGvoid CString::AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
ASSERT(nLen >= 0);
ASSERT(nLen <= INT_MAX-1); // max size (enough room for 1 extra) if (nLen == 0)
Init();
else
{
CStringData* pData;
#ifndef _DEBUG
if (nLen <= 64)
{
pData = (CStringData*)_afxAlloc64.Alloc();
pData->nAllocLength = 64;
}
else if (nLen <= 128)
{
pData = (CStringData*)_afxAlloc128.Alloc();
pData->nAllocLength = 128;
}
else if (nLen <= 256)
{
pData = (CStringData*)_afxAlloc256.Alloc();
pData->nAllocLength = 256;
}
else if (nLen <= 512)
{
pData = (CStringData*)_afxAlloc512.Alloc();
pData->nAllocLength = 512;
}
else
#endif
{
pData = (CStringData*)
new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];
pData->nAllocLength = nLen;
}
pData->nRefs = 1;
pData->data()[nLen] = '\0';
pData->nDataLength = nLen;
m_pchData = pData->data();
}
}void FASTCALL CString::FreeData(CStringData* pData)
{
#ifndef _DEBUG
int nLen = pData->nAllocLength;
if (nLen == 64)
_afxAlloc64.Free(pData);
else if (nLen == 128)
_afxAlloc128.Free(pData);
else if (nLen == 256)
_afxAlloc256.Free(pData);
else if (nLen == 512)
_afxAlloc512.Free(pData);
else
{
ASSERT(nLen > 512);
delete[] (BYTE*)pData;
}
#else
delete[] (BYTE*)pData;
#endif
}void CString::Release()
{
if (GetData() != _afxDataNil)
{
ASSERT(GetData()->nRefs != 0);
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
FreeData(GetData());
Init();
}
}void PASCAL CString::Release(CStringData* pData)
{
if (pData != _afxDataNil)
{
ASSERT(pData->nRefs != 0);
if (InterlockedDecrement(&pData->nRefs) <= 0)
FreeData(pData);
}
}void CString::Empty()
{
if (GetData()->nDataLength == 0)
return;
if (GetData()->nRefs >= 0)
Release();
else
*this = &afxChNil;
ASSERT(GetData()->nDataLength == 0);
ASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
}void CString::CopyBeforeWrite()
{
if (GetData()->nRefs > 1)
{
CStringData* pData = GetData();
Release();
AllocBuffer(pData->nDataLength);
memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(TCHAR));
}
ASSERT(GetData()->nRefs <= 1);
}void CString::AllocBeforeWrite(int nLen)
{
if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
{
Release();
AllocBuffer(nLen);
}
ASSERT(GetData()->nRefs <= 1);
}CString::~CString()
// free any attached data
{
if (GetData() != _afxDataNil)
{
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
FreeData(GetData());
}
}//////////////////////////////////////////////////////////////////////////////
// Helpers for the rest of the implementationvoid CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
int nExtraLen) const
{
// will clone the data attached to this string
// allocating 'nExtraLen' characters
// Places results in uninitialized string 'dest'
// Will copy the part or all of original data to start of new string int nNewLen = nCopyLen + nExtraLen;
if (nNewLen == 0)
{
dest.Init();
}
else
{
dest.AllocBuffer(nNewLen);
memcpy(dest.m_pchData, m_pchData+nCopyIndex, nCopyLen*sizeof(TCHAR));
}
}//////////////////////////////////////////////////////////////////////////////
// More sophisticated constructionCString::CString(LPCTSTR lpsz)
{
Init();
if (lpsz != NULL && HIWORD(lpsz) == NULL)
{
UINT nID = LOWORD((DWORD)lpsz);
if (!LoadString(nID))
TRACE1("Warning: implicit LoadString(%u) failed\n", nID);
}
else
{
int nLen = SafeStrlen(lpsz);
if (nLen != 0)
{
AllocBuffer(nLen);
memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
}
}
}/////////////////////////////////////////////////////////////////////////////
// Special conversion constructors#ifdef _UNICODE
CString::CString(LPCSTR lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
if (nSrcLen != 0)
{
AllocBuffer(nSrcLen);
_mbstowcsz(m_pchData, lpsz, nSrcLen+1);
ReleaseBuffer();
}
}
#else //_UNICODE
CString::CString(LPCWSTR lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if (nSrcLen != 0)
{
AllocBuffer(nSrcLen*2);
_wcstombsz(m_pchData, lpsz, (nSrcLen*2)+1);
ReleaseBuffer();
}
}
#endif //!_UNICODE//////////////////////////////////////////////////////////////////////////////
// Diagnostic support#ifdef _DEBUG
CDumpContext& AFXAPI operator<<(CDumpContext& dc, const CString& string)
{
dc << string.m_pchData;
return dc;
}
#endif //_DEBUG//////////////////////////////////////////////////////////////////////////////
// Assignment operators
// All assign a new value to the string
// (a) first see if the buffer is big enough
// (b) if enough room, copy on top of old buffer, set size and type
// (c) otherwise free old string data, and create a new one
//
// All routines return the new string (but as a 'const CString&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//void CString::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
AllocBeforeWrite(nSrcLen);
memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}const CString& CString::operator=(const CString& stringSrc)
{
if (m_pchData != stringSrc.m_pchData)
{
if ((GetData()->nRefs < 0 && GetData() != _afxDataNil) ||
stringSrc.GetData()->nRefs < 0)
{
// actual copy necessary since one of the strings is locked
AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
}
else
{
// can just copy references around
Release();
ASSERT(stringSrc.GetData() != _afxDataNil);
m_pchData = stringSrc.m_pchData;
InterlockedIncrement(&GetData()->nRefs);
}
}
return *this;
}const CString& CString::operator=(LPCTSTR lpsz)
{
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}/////////////////////////////////////////////////////////////////////////////
// Special conversion assignment#ifdef _UNICODE
const CString& CString::operator=(LPCSTR lpsz)
{
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
AllocBeforeWrite(nSrcLen);
_mbstowcsz(m_pchData, lpsz, nSrcLen+1);
ReleaseBuffer();
return *this;
}
#else //!_UNICODE
const CString& CString::operator=(LPCWSTR lpsz)
{
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
AllocBeforeWrite(nSrcLen*2);
_wcstombsz(m_pchData, lpsz, (nSrcLen*2)+1);
ReleaseBuffer();
return *this;
}
#endif //!_UNICODE//////////////////////////////////////////////////////////////////////////////
// concatenation// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// CString + CString
// and for ? = TCHAR, LPCTSTR
// CString + ?
// ? + CStringvoid CString::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
int nSrc2Len, LPCTSTR lpszSrc2Data)
{
// -- master concatenation routine
// Concatenate two sources
// -- assume that 'this' is a new CString object int nNewLen = nSrc1Len + nSrc2Len;
if (nNewLen != 0)
{
AllocBuffer(nNewLen);
memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
}
}CString AFXAPI operator+(const CString& string1, const CString& string2)
{
CString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
string2.GetData()->nDataLength, string2.m_pchData);
return s;
}CString AFXAPI operator+(const CString& string, LPCTSTR lpsz)
{
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
CString s;
s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
CString::SafeStrlen(lpsz), lpsz);
return s;
}CString AFXAPI operator+(LPCTSTR lpsz, const CString& string)
{
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
CString s;
s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
string.m_pchData);
return s;
}//////////////////////////////////////////////////////////////////////////////
// concatenate in placevoid CString::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
{
// -- the main routine for += operators // concatenating an empty string is a no-op!
if (nSrcLen == 0)
return; // if the buffer is too small, or we have a width mis-match, just
// allocate a new buffer (slow but sure)
if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
{
// we have to grow the buffer, use the ConcatCopy routine
CStringData* pOldData = GetData();
ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
ASSERT(pOldData != NULL);
CString::Release(pOldData);
}
else
{
// fast concatenation when buffer big enough
memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
GetData()->nDataLength += nSrcLen;
ASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
m_pchData[GetData()->nDataLength] = '\0';
}
}const CString& CString::operator+=(LPCTSTR lpsz)
{
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
ConcatInPlace(SafeStrlen(lpsz), lpsz);
return *this;
}const CString& CString::operator+=(TCHAR ch)
{
ConcatInPlace(1, &ch);
return *this;
}const CString& CString::operator+=(const CString& string)
{
ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
return *this;
}///////////////////////////////////////////////////////////////////////////////
// Advanced direct buffer accessLPTSTR CString::GetBuffer(int nMinBufLength)
{
ASSERT(nMinBufLength >= 0); if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
{
#ifdef _DEBUG
// give a warning in case locked string becomes unlocked
if (GetData() != _afxDataNil && GetData()->nRefs < 0)
TRACE0("Warning: GetBuffer on locked CString creates unlocked CString!\n");
#endif
// we have to grow the buffer
CStringData* pOldData = GetData();
int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
if (nMinBufLength < nOldLen)
nMinBufLength = nOldLen;
AllocBuffer(nMinBufLength);
memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
GetData()->nDataLength = nOldLen;
CString::Release(pOldData);
}
ASSERT(GetData()->nRefs <= 1); // return a pointer to the character storage for this string
ASSERT(m_pchData != NULL);
return m_pchData;
}void CString::ReleaseBuffer(int nNewLength)
{
CopyBeforeWrite(); // just in case GetBuffer was not called if (nNewLength == -1)
nNewLength = lstrlen(m_pchData); // zero terminated ASSERT(nNewLength <= GetData()->nAllocLength);
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
}LPTSTR CString::GetBufferSetLength(int nNewLength)
{
ASSERT(nNewLength >= 0); GetBuffer(nNewLength);
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
return m_pchData;
}void CString::FreeExtra()
{
ASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
if (GetData()->nDataLength != GetData()->nAllocLength)
{
CStringData* pOldData = GetData();
AllocBuffer(GetData()->nDataLength);
memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(TCHAR));
ASSERT(m_pchData[GetData()->nDataLength] == '\0');
CString::Release(pOldData);
}
ASSERT(GetData() != NULL);
}LPTSTR CString::LockBuffer()
{
LPTSTR lpsz = GetBuffer(0);
GetData()->nRefs = -1;
return lpsz;
}void CString::UnlockBuffer()
{
ASSERT(GetData()->nRefs == -1);
if (GetData() != _afxDataNil)
GetData()->nRefs = 1;
}///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)int CString::Find(TCHAR ch) const
{
return Find(ch, 0);
}int CString::Find(TCHAR ch, int nStart) const
{
int nLength = GetData()->nDataLength;
if (nStart >= nLength)
return -1; // find first single character
LPTSTR lpsz = _tcschr(m_pchData + nStart, (_TUCHAR)ch); // return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}int CString::FindOneOf(LPCTSTR lpszCharSet) const
{
ASSERT(AfxIsValidString(lpszCharSet));
LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}void CString::MakeUpper()
{
CopyBeforeWrite();
_tcsupr(m_pchData);
}void CString::MakeLower()
{
CopyBeforeWrite();
_tcslwr(m_pchData);
}void CString::MakeReverse()
{
CopyBeforeWrite();
_tcsrev(m_pchData);
}void CString::SetAt(int nIndex, TCHAR ch)
{
ASSERT(nIndex >= 0);
ASSERT(nIndex < GetData()->nDataLength); CopyBeforeWrite();
m_pchData[nIndex] = ch;
}#ifndef _UNICODE
void CString::AnsiToOem()
{
CopyBeforeWrite();
::AnsiToOem(m_pchData, m_pchData);
}
void CString::OemToAnsi()
{
CopyBeforeWrite();
::OemToAnsi(m_pchData, m_pchData);
}
#endif///////////////////////////////////////////////////////////////////////////////
// CString conversion helpers (these use the current system locale)int AFX_CDECL _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
{
if (count == 0 && mbstr != NULL)
return 0; int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
mbstr, count, NULL, NULL);
ASSERT(mbstr == NULL || result <= (int)count);
if (result > 0)
mbstr[result-1] = 0;
return result;
}int AFX_CDECL _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
{
if (count == 0 && wcstr != NULL)
return 0; int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
wcstr, count);
ASSERT(wcstr == NULL || result <= (int)count);
if (result > 0)
wcstr[result-1] = 0;
return result;
}LPWSTR AFXAPI AfxA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
{
if (lpa == NULL)
return NULL;
ASSERT(lpw != NULL);
// verify that no illegal character present
// since lpw was allocated based on the size of lpa
// don't worry about the number of chars
lpw[0] = '\0';
VERIFY(MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars));
return lpw;
}LPSTR AFXAPI AfxW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
{
if (lpw == NULL)
return NULL;
ASSERT(lpa != NULL);
// verify that no illegal character present
// since lpa was allocated based on the size of lpw
// don't worry about the number of chars
lpa[0] = '\0';
VERIFY(WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL));
return lpa;
}
{ m_pchData = afxEmptyString.m_pchData; }_AFX_INLINE CStringData* CString::GetData() const
{ ASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }_AFX_INLINE int PASCAL CString::SafeStrlen(LPCTSTR lpsz)
{ return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
上面两位,真有意思啊。
安装VC的时候,选择安装MFC source
在VC目录下有MFC类的大部分源代码:
"C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\"
好,把你的e-mail给我吧,我还有1000多分,下次找你,不过今天不能给你分,你没答对,
tuggfox(踏歌而行):
谢谢你,我试一下,就个你分
你没看前面的回复,也是我没说清,好吧,给你30,怎么样?
如果你对MFC的原码感兴趣的话,我可以给你一个工具!要吗?