C++ can';t使用迭代器遍历字符串:但是我的带有索引的版本确实有效
我正在写一个小程序,将所有出现的正整数转换成二进制整数。那么我该怎么写呢 我有一个函数numbersToBinary,它接受一个字符串并对其进行修改,使其包含二进制形式的数字,而不是十进制形式的数字C++ can';t使用迭代器遍历字符串:但是我的带有索引的版本确实有效,c++,string,stl,iterator,C++,String,Stl,Iterator,我正在写一个小程序,将所有出现的正整数转换成二进制整数。那么我该怎么写呢 我有一个函数numbersToBinary,它接受一个字符串并对其进行修改,使其包含二进制形式的数字,而不是十进制形式的数字 void numbersToBinary(string &src) { for (string::iterator iter = src.begin(); iter != src.end(); iter++) { if (isdigit(*iter))
void numbersToBinary(string &src)
{
for (string::iterator iter = src.begin(); iter != src.end(); iter++)
{
if (isdigit(*iter))
{
string::iterator numberStart = iter++; //numberStart = iter;
while ((iter != src.end()) && (isdigit(*iter)))
{
iter++;
}
string ins = decimalToBinary(string(numberStart, iter));
src.replace(numberStart, iter, ins);
}
}
}
问题在于,当使用以数字结尾的字符串调用replace方法时,该函数会捕获异常
下面是一个:代码,您也可以在这里看到:。单元测试可用
MWE:
但事实证明,条件(iter!=src.end())从来都不是假的,即使是在字符串末尾:
Breakpoint 2, numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:58
58 newString.append(ins);
(gdb) print ins
$40 = "1101"
(gdb) s
51 for (string::iterator iter = src.begin(); iter != src.end(); iter++) {
(gdb) print iter
$41 = 0 '\000'
(gdb) s
__gnu_cxx::__normal_iterator<char*, std::string>::operator++ (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:757
757 { return __normal_iterator(_M_current++); }
(gdb) s
__gnu_cxx::__normal_iterator<char*, std::string>::__normal_iterator (this=0x7fffffffd780, __i=@0x7fffffffd788: 0x6a1a10 "") at /usr/include/c++/4.9.1/bits/stl_iterator.h:729
729 : _M_current(__i) { }
(gdb) s
__gnu_cxx::operator!=<char*, std::string> (__lhs=16 '\020', __rhs=0 '\000') at /usr/include/c++/4.9.1/bits/stl_iterator.h:832
832 { return __lhs.base() != __rhs.base(); }
(gdb) s
__gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794
794 { return _M_current; }
(gdb) s
__gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd810) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794
794 { return _M_current; }
(gdb) s
numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:52
52 if (isdigit(*iter)) {
(gdb) print iter
$42 = 16 '\020'
(gdb) print src.end()
$43 = 0 '\000'
在for循环结束之前,它可以工作!这是什么?调用
replace
后,原始字符串值不再存在。因此,它的某些部分的迭代器不再有效。当您再次循环时,iter
是一个迭代器,用于对不再存在的值的一部分进行迭代器,因此将其与另一个值的结尾进行比较是毫无意义的。调用replace
后,需要将新字符串中的iter
设置为正确的新值,然后再将其与end
进行比较,以了解更新的(和…更新的)代码
编辑:难以置信,如果我加上这个
if (iter == src.end()) break;
if (iter == src.end()) break;
在for循环结束之前,它可以工作!这是什么
这并不令人难以置信。这就是for循环的工作原理。您需要了解何时执行for循环的增量步骤,以及何时计算条件步骤
在(重新)输入循环体之前,完成条件评估。在循环体完成后,在返回到循环顶部进行下一个条件求值之前,完成增量步骤
简而言之,如果内部数字循环运行到src.end()。记住,for循环增量是在每次迭代完成之后,但在下一个条件测试之前完成的
所以,
void numbersToBinary(string &src)
{
string newString;
string::iterator iter = src.begin();
while (iter != src.end())
{
if (isdigit(*iter))
{
string::iterator numberStart = iter++; //numberStart = iter;
while ((iter != src.end()) && (isdigit(*iter))) {
++iter;
}
string ins = decimalToBinary(string(numberStart, iter));
newString.append(ins);
}
else
{
newString.push_back(*iter++);
}
}
src = newString;
}
是您尝试的几种方法之一。如果iter
已经到达src.end()
,您也可以在循环的末尾插入一个硬中断(尽管在那里检查似乎有些多余,因为我们已经知道它被设置为src.end()
:数字循环)调用std::string::replace
可以使迭代器无效。您应该创建一个新的结果
字符串并返回它。问题是字符串中可能有多个整数。我该怎么处理呢?在调用replace
之后,我当然需要继续循环。您最好使用[]
操作符(数组索引)…事情会变得不那么麻烦谢谢您,这很有意义。
if (iter == src.end()) break;
if (iter == src.end()) break;
void numbersToBinary(string &src)
{
string newString;
string::iterator iter = src.begin();
while (iter != src.end())
{
if (isdigit(*iter))
{
string::iterator numberStart = iter++; //numberStart = iter;
while ((iter != src.end()) && (isdigit(*iter))) {
++iter;
}
string ins = decimalToBinary(string(numberStart, iter));
newString.append(ins);
}
else
{
newString.push_back(*iter++);
}
}
src = newString;
}