Click here to Skip to main content
15,881,803 members
Articles / Desktop Programming / MFC
Article

Fast splitting of CString objects

Rate me:
Please Sign up or sign in to vote.
2.67/5 (18 votes)
23 Sep 2005GPL3 105K   14   15
Splitting CString objects is mostly easy, but can be tricky. I developed this function for using it with CSV files.

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

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Web Developer
Switzerland Switzerland
Working as software developer in communication and automotive industry.
To contact me: softwaredeveloper [at ]dieselschrauber.de
Visit my Website to view my current work.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Member 1071292224-Nov-14 4:14
Member 1071292224-Nov-14 4:14 
it doesn't work
GeneralRe: My vote of 1 Pin
rkaufman3-Mar-15 7:31
rkaufman3-Mar-15 7:31 
GeneralCode Pin
carlmalden14-Aug-07 4:54
carlmalden14-Aug-07 4:54 
GeneralBugs found Pin
russelo6-May-03 17:47
russelo6-May-03 17:47 
GeneralThis is no bug Pin
rkaufman7-May-03 4:02
rkaufman7-May-03 4:02 
GeneralAnother option Pin
Bill Oliver29-Apr-03 3:43
Bill Oliver29-Apr-03 3:43 
Generaltry this instead.. Pin
Bill Gates Antimatter Particle11-Mar-03 21:56
Bill Gates Antimatter Particle11-Mar-03 21:56 
GeneralRe: try this instead.. Pin
rkaufman12-Mar-03 4:55
rkaufman12-Mar-03 4:55 
QuestionWhat's about AfxExtractSubString? Pin
Holger Persch11-Mar-03 19:47
Holger Persch11-Mar-03 19:47 
AnswerRe: What's about AfxExtractSubString? Pin
rkaufman12-Mar-03 4:57
rkaufman12-Mar-03 4:57 
GeneralRe: What's about AfxExtractSubString? Pin
Member 12506657-Oct-04 10:11
Member 12506657-Oct-04 10:11 
GeneralRe: What's about AfxExtractSubString? Pin
Member 12506657-Oct-04 10:11
Member 12506657-Oct-04 10:11 
GeneralRe: Observations Pin
rkaufman12-Mar-03 5:11
rkaufman12-Mar-03 5:11 
Generaldefine fast... Pin
Anonymous11-Mar-03 5:45
Anonymous11-Mar-03 5:45 
GeneralRe: define fast... Pin
rkaufman12-Mar-03 5:00
rkaufman12-Mar-03 5:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.