3

可能重复:
在 C++ 中拆分字符串

我试图创建一个模仿函数行为的getline()函数,并可以选择使用分隔符将字符串拆分为标记。该函数接受 2 个字符串(第二个通过引用传递)和一个char分隔符类型。它遍历第一个字符串的每个字符,将其复制到第二个字符串,并在到达分隔符时停止循环。true如果第一个字符串在分隔符之后有更多字符,则返回,false否则返回。最后一个字符的位置保存在静态变量中。由于某种原因,程序进入无限循环并且没有执行任何操作:

const int LINE_SIZE = 160;
bool strSplit(string sFirst, string & sLast, char cDelim) {
    static int iCount = 0;
    for(int i = iCount; i < LINE_SIZE; i++) {
        if(sFirst[i] != cDelim)
            sLast[i-iCount] = sFirst[i];
        else {
            iCount = i+1;
            return true;
        }
    }
    return false;
}

该函数的使用方式如下:

while(strSplit(sLine, sToken, '|')) {
    cout << sToken << endl;
}

为什么它会进入无限循环,为什么它不起作用?istringstream如果可能的话,我应该补充一点,我对不使用的解决方案感兴趣。

4

4 回答 4

5

这不完全是您所要求的,但您考虑过std::istringstreamstd::getline

// UNTESTED
std::istringstream iss(sLine);
while(std::getline(iss, sToken, '|')) {
  std::cout << sToken << "\n";
}

编辑

为什么它会进入无限循环,为什么它不起作用?

我们不知道,你没有提供足够的信息。尝试创建一个SSCCE并将其发布。

可以告诉你,下面这行非常可疑:

       sLast[i-iCount] = sFirst[i];

此行将在以下任何情况下导致未定义的行为(可能包括您所看到的):

  • i >= sFirst.size()
  • i-iCount >= sLast.size()
  • i-iCount < 0

在我看来,所有这些条件都可能是真的。例如,如果传入的字符串短于 160 行,或者如果iCount增长到大于第一个分隔符的偏移量,那么您将获得未定义的行为。

于 2012-09-12T16:55:28.197 回答
3

LINE_SIZE可能大于string对象中的字符数,因此代码在字符串存储的末尾运行,几乎任何事情都可能发生。

而不是自己滚动,string::find做你需要的。

std::string::size_type pos = 0;
std::string::size_type new_pos = sFirst.find('|', pos);

调用find查找第一次出现的 '|' 那是在位置'pos'处或之后。如果成功,则返回 '|' 的索引 它发现。如果失败,则返回std::string::npos. 在循环中使用它,每次匹配后,将文本从 [pos, new_pos) 复制到目标字符串中,并更新posnew_pos + 1.

于 2012-09-12T17:09:26.257 回答
1

你确定这是strSplit()不返回的函数还是你的调用者while循环是无限的?

你的调用者循环不应该是这样的:

while(strSplit(sLine, sToken, '|')) {
    cout << sToken << endl;
    cin >> sLine >> endl;
}

- 编辑 -

如果值 ofsLine使得它strSplit()返回 true 则while循环变为无限.. 所以做一些事情来改变sLine循环的每次迭代的值.. 例如放入一个cin..

于 2012-09-12T16:57:29.007 回答
0

看一下这个

std::vector<std::string> spliString(const std::string &str, 
                                    const std::string &separator)
{
    vector<string>      ret;
    string::size_type   strLen = str.length();
    char                *buff;
    char                *pch;

    buff = new char[strLen + 1];
    buff[strLen] = '\0';
    std::copy(str.begin(), str.end(), buff);

    pch = strtok(buff, separator.c_str());
    while(pch != NULL)
    {
        ret.push_back(string(pch));
        pch = strtok(NULL, separator.c_str());
    }

    delete[] buff;

    return ret;
}
于 2012-09-12T17:01:36.363 回答