我试图创建一个模仿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
的解决方案感兴趣。
答案 0 :(得分:5)
这不是您要求的,但您是否考虑过std::istringstream
和std::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;
}