我正在尝试从字符串中截断开头的零,所以我使用了序列擦除功能
string& erase (size_t pos = 0, size_t len = npos);
这是我的实现:
string str="000010557";
for(char c:str){
cout<<c<<" "<<str<<" "<<"\n";// for debug purpose
if(c=='0')
str.erase(0,1);
else
break;
}
cout<<str;
我得到的输出字符串是0010557
而不是10557
,并且调试语句打印出来:
0 000010557
0 00010557
1 0010557
[我阅读erase和this的文档后认为可能存在一些迭代器无效,但是实现接受的答案中推荐的代码段也给出了相同的输出,请帮助我了解问题出在哪里。
我对使用stl库函数不熟悉,所以请原谅我的任何疏忽,谢谢。
您的for
循环正在递增从中提取c
的位置,即使您删除前导零也是如此。因此,在循环运行两次之后,您已经删除了前导零的first和third,则c
值将是第一个1
。
这里是尝试跟踪代码中发生的事情:
Start of first loop:
"000010557"
^
c is '0', so erase is called, making the string:
"00010557"
At the end of this first loop, the position is incremented, so...
Start of second loop:
"00010557"
^ (Note that we've skipped a zero!)
c is '0', so erase is called, making the string:
"0010557"
End of loop, position increment, and we skip another zero, so...
Start of third loop:
"0010557"
^
c is not '0', so we break out of the loop.
相反,您应该使用while
循环,测试only第一个字符:
int main()
{
string str = "000010557";
char c;
while ((c = str.at(0)) == '0') {
cout << c << " " << str << " " << "\n";// for debug purpose
str.erase(0, 1);
}
cout << str;
}
输出:
0 000010557
0 00010557
0 0010557
0 010557
10557
当然,您的“调试”行只需要c
变量,因此,没有它,您就可以拥有:
int main()
{
string str = "000010557";
while (str.at(0) == '0') str.erase(0, 1);
cout << str;
}
即使您可以使用此代码,也不是一个好的解决方案。从字符串的开头删除单个字符意味着将所有后续字符向下移动一个位置,并且代码会针对每个前导零执行此操作。相反,请计算前导零并立即将其全部删除:
std::string::size_type non_zero_pos = 0;
while (non_zero_pos < str.size() && str[non_zero_pos] == '0')
++non_zero_pos;
str.erase(0, non_zero_pos);
这样,(昂贵的)擦除操作仅执行一次。
或使用迭代器:
auto non_zero_it = std::find_first_not_of(std::begin(str), std::end(str), "0");
str.erase(std::begin(str), non_zero_it);
编辑:固定搜索非0的迭代器。