在C ++中创建一个字符串拆分函数

时间:2012-09-12 16:52:26

标签: c++ string pass-by-reference static-variables

  

可能重复:
  Splitting a string in 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 个答案:

答案 0 :(得分: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增长到大于第一个分隔符的偏移量,那么您将得到未定义的行为。

答案 1 :(得分: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]中的文本复制到目标字符串中,并将pos更新为new_pos + 1

答案 2 :(得分:1)

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

你的调用者循环不应该像:

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

- 编辑 -

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

答案 3 :(得分: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;
}