使用 CString 实现分词功能

Implementing tokenize function with CString

为了学习,我正在尝试使用 CString 实现我自己的简单 Tokenize 函数。我目前有这个文件:

11111
22222
(ENDWPT)


222222
333333
(ENDWPT)
6060606
ggggggg
hhhhhhh
(ENDWPT)
iiiiiii
jjjjjjj
kkkkkkk
lllllll
mmmmmmm
nnnnnnn

我想用分隔符 (ENDWPT) 对其进行标记。 我编写了以下函数,它试图找到分隔符位置,然后添加分隔符长度并将文本提取到该位置。之后,更新使用的计数器,以便下次调用该函数时它开始从先前的索引中搜索分隔符。该函数如下所示:

bool MyTokenize(CString strText, CString& strOut, int& iCount)
{
    CString strDelimiter = L"(ENDWPT)";
    int iIndex = strText.Find(strDelimiter, iCount);

    if (iIndex != -1)
    {
        iIndex += strDelimiter.GetLength();
        strOut = strText.Mid(iCount, iIndex);
        iCount = iIndex;
        return true;
    }
    return false;
}

并且被这样调用:

int nCount = 0;

while ((MyTokenize(strText, strToken, nCount)) == true)
{
    // Handle tokenized strings here
}

现在,函数以错误的方式拆分字符串,我认为这是因为 Find() 可能返回了错误的索引。我认为它应该返回 12,但它实际上返回 14??。 我 运行 没有想法,如果有人能解决这个问题,我将不胜感激。

如果找到分隔符 (iIndex),则从 (iCount) 开始读取 iIndex - iCount 计数。然后修改iCount

if(iIndex != -1)
{
    strOut = strText.Mid(iCount, iIndex - iCount);
    iCount = iIndex + strDelimiter.GetLength();
    return true;
}

源字符串可能不以分隔符结尾,这需要特殊情况。

您还可以选择更好的名称来匹配 CString::Mid(int nFirst, int nCount) 的用法,以使其更易于理解。 MFC使用camelCase编码风格,在变量前面加上类型标识符,这在C++中是不需要的,我将在本例中避免:

bool MyTokenize(CString &source, CString& token, int& first)
{
    CString delimeter = L"(ENDWPT)";
    int end = source.Find(delimeter, first);

    if(end != -1)
    {
        int count = end - first;
        token = source.Mid(first, count);
        first = end + delimeter.GetLength();
        return true;
    }
    else
    {
        int count = source.GetLength() - first;
        if(count <= 0)
            return false;

        token = source.Mid(first, count);
        first = source.GetLength();
        return true;
    }
}

...

int first = 0;
CString source = ...
CString token;
while(MyTokenize(source, token, first))
{
    // Handle tokenized strings here
}