常规编程
现在阅读
Fast splitting of CString objects
0

Fast splitting of CString objects

由 ultracpy2018年1月26日

Introduction

Splitting CString objects is mostly easy. But in some special cases, like handling CSV data, the following function can do a good job: it explains how to handle strings that contain the separator itself in the text.

The solution is to ‘escape’ all separators that occur in the text itself and use a splitting function that is aware of this ‘escape’ (chMagic) character. The following function extends AfxGetSubString with this behaviour and is optimized to be as fast as possible while using CString.

The extracted CString substring is directly manipulated using the GetBufferSetLength member function.

Code

// Get substring, chMagic is a character which 
// makes chSep act as a normal character. 
// Return TRUE on success. 
inline BOOL GetSubString(CString& strSub, LPCTSTR lpszFullString, 
                         int iFullStringLen, int iSubString, TCHAR chSep, 
                         TCHAR chMagic) 
{ 
    int iPos, iPosOrig, iStartPos, iEndPos, iNumMagics; 
    TCHAR* pcSubString; 
    if((lpszFullString == NULL) || 
        (iFullStringLen == 0)) 
        return FALSE; 
    // Find substring begin 
    for(iStartPos = 0; (iStartPos < iFullStringLen) && (iSubString > 0); 
        iStartPos++) 
    { 
        // May be separator ? 
        if(*(lpszFullString + iStartPos) == chSep) 
        { 
            if(((iStartPos > 0) && 
                (*(lpszFullString + iStartPos - 1) != chMagic)) 
                || (iStartPos == 0)) 
            { 
                // Sure it is a separator! 
                iSubString--; 
            } 
        } 
    } 

    // Return empty string when nothing found 
    if(iSubString > 0) 
    { 
        strSub.Empty(); 
        return FALSE; 
    } 

    // Find substring end 
    iNumMagics = 0; 
    for(iEndPos = iStartPos; 
        iEndPos < iFullStringLen; 
        iEndPos++) 
    { 
        // Count magics 
        if(*(lpszFullString + iEndPos) == chMagic) 
        { 
            iNumMagics++; 
        } 
        // May be separator ? 
        if(*(lpszFullString + iEndPos) == chSep) 
        { 
            if(((iEndPos > 0) && (*(lpszFullString + iEndPos - 1) 
                != chMagic)) || (iEndPos == 0)) 
            { 
                // Sure it is the end 
                break; 
            } 
        } 
    } 

    // Copy substring 
    pcSubString = strSub.GetBufferSetLength(
        iEndPos - iStartPos - iNumMagics); 
    iPosOrig = iStartPos; 
    iEndPos -= iStartPos; 
    if(pcSubString != NULL) 
    { 
        for(iPos = 0; iPos < iEndPos; iPos += sizeof(TCHAR)) 
        { 
            if(*(lpszFullString + iPosOrig) != chMagic) 
            { 
                *(pcSubString + iPos) = *(lpszFullString + iPosOrig); 
            } 
            else 
            { 
                iPos -= sizeof(TCHAR); 
                iEndPos -= sizeof(TCHAR); 
            } 
            iPosOrig += sizeof(TCHAR); 
        } 
        *(pcSubString + iPos) = 0; 
        return TRUE; 
    } 
    return FALSE; 
};

Example

CString strSub, strLine("1,2,3\\,1,4,..."); 
int iLen = strLine.GetLength(); 
GetSubString(strSub, strLine, iLen, 0, ',', '\\'); // strSub: 1 
GetSubString(strSub, strLine, iLen, 1, ',', '\\'); // strSub: 2 
GetSubString(strSub, strLine, iLen, 2, ',', '\\'); // strSub: 3,1

出处:https://www.codeproject.com/Articles/3766/Fast-splitting-of-CString-objects

关于作者
ultracpy
评论

    你必须 登录 提交评论