还不如自己重写一个类,或则改用STL中的string,那可是绝对提供了所有的源码。

解决方案 »

  1.   

    在vc98\mfc\include\afx.h中定义;
    在vc98\mfc\src\strex.cpp中实现。
      

  2.   

    你要要就给你吧.还想要什么的源代码? 说出来,有分就行!! #ifdef _AFXDLL
    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;
    }
      

  3.   

    Init;GetData;SafeStrlen在vc98\mfc\include\afx.inl中,如下:_AFX_INLINE void CString::Init()
    { 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); }
      

  4.   

    :)
    上面两位,真有意思啊。
    安装VC的时候,选择安装MFC source
    在VC目录下有MFC类的大部分源代码:
    "C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\"
      

  5.   

    pgfun():
      好,把你的e-mail给我吧,我还有1000多分,下次找你,不过今天不能给你分,你没答对,
    tuggfox(踏歌而行):
      谢谢你,我试一下,就个你分  
      

  6.   

    什么话! 这不是cstring的源码是什么?
      

  7.   

    to pgfun:
      你没看前面的回复,也是我没说清,好吧,给你30,怎么样?
      

  8.   

    lts:
        如果你对MFC的原码感兴趣的话,我可以给你一个工具!要吗?