使用 string erase() 和 string length() 从字符串中删除某些字符
Using string erase() and string length() to delete certain chars from a string
我在下面编写了一个函数来遍历字符串 a 删除所有空格 ' '
和 '-'
s。但是,它会跳过字符串的某些元素并在末尾留下 '-'
,因此逻辑一定是不正确的。谁能发现我哪里出错了?
#include <iostream>
#include <string>
using namespace std;
string FormatString(string S) {
size_t original_size = S.length();
cout << "Length at start is " << S.length() << "\n";
/*Count spaces and dashes*/
for(size_t i = 0; i < S.length(); i++) {
cout << "Current letter is " << S[i] << "\n";
if((S[i] == ' ') || (S[i] == '-')) {
cout << "Deleting current letter " << S[i] << "\n";
S.erase (i,1);
cout << "Length is now " << S.length() << "\n";
}
}
std::cout << S << '\n';
return S;
}
int main() {
std::string testString("AA BB-4499--5");
std::string result = FormatString(testString);
cout << result << endl; // prints !!!Hello World!!!
return 0;
}
输出为:
Length at start is 13
Current letter is A
Current letter is A
Current letter is
Deleting current letter
Length is now 12
Current letter is B
Current letter is -
Deleting current letter -
Length is now 11
Current letter is 4
Current letter is 9
Current letter is 9
Current letter is -
Deleting current letter -
Length is now 10
Current letter is 5
AABB4499-5
AABB4499-5
这个函数的问题是,当一个字符被擦除时,索引仍然会增加。所以一些相邻的字符将仍然在字符串中。
最好使用基于标准算法 std::remove
或 std::remove_if
.
的 so-called 习语 erase-remove
这是一个演示程序
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
std::string FormatString( const std::string &s, const std::string &erased = " -" )
{
const char *data = erased.data();
std::string t( s );
t.erase( std::remove_if( t.begin(), t.end(), [=]( char c ) { return std::strchr( data, c ); } ),
t.end() );
return t;
}
int main()
{
std::string testString( "AA BB-4499--5" );
std::cout << FormatString( testString ) << std::endl;
return 0;
}
它的输出是
AABB44995
这是因为您在擦除后增加了位置。
当你擦除时,你将所有其他字符向下移动一个。如果您随后还增加了您在字符串中的位置,您实际上会跳过一个字符。
如果我们从这里开始:
"AA BB-4499--5"
删除几个字符后剩下这个
"AABB4499--5"
^ // i is 9.
您现在删除光标上方的字符。
"AABB4499-5"
^ // i is 9.
现在开始循环的下一次迭代。
"AABB4499-5"
^ // i is 10.
您注意到您跳过了一个字符。
这个算法更好的实现是:
for(size_t i = 0; i < S.length();) { // Notice no increment here
if((S[i] == ' ') || (S[i] == '-')) {
S.erase (i,1);
}
else {
++i;
}
}
我们可以用迭代器对此进行改进:
for(auto loop = std::begin(S); loop != std::end(S);) {
if (*loop == ' ' || *loop == '-') {
loop = S.erase(loop);
}
else {
++loop;
}
}
现在我们正在使用迭代器,我们可以在标准算法中循环
auto newEnd = std::remove_if(std::begin(S), std::end(S),
[](char c){return c == ' ' || c == '-';});
std::erase(newEnd, std::end(S));
我在下面编写了一个函数来遍历字符串 a 删除所有空格 ' '
和 '-'
s。但是,它会跳过字符串的某些元素并在末尾留下 '-'
,因此逻辑一定是不正确的。谁能发现我哪里出错了?
#include <iostream>
#include <string>
using namespace std;
string FormatString(string S) {
size_t original_size = S.length();
cout << "Length at start is " << S.length() << "\n";
/*Count spaces and dashes*/
for(size_t i = 0; i < S.length(); i++) {
cout << "Current letter is " << S[i] << "\n";
if((S[i] == ' ') || (S[i] == '-')) {
cout << "Deleting current letter " << S[i] << "\n";
S.erase (i,1);
cout << "Length is now " << S.length() << "\n";
}
}
std::cout << S << '\n';
return S;
}
int main() {
std::string testString("AA BB-4499--5");
std::string result = FormatString(testString);
cout << result << endl; // prints !!!Hello World!!!
return 0;
}
输出为:
Length at start is 13
Current letter is A
Current letter is A
Current letter is
Deleting current letter
Length is now 12
Current letter is B
Current letter is -
Deleting current letter -
Length is now 11
Current letter is 4
Current letter is 9
Current letter is 9
Current letter is -
Deleting current letter -
Length is now 10
Current letter is 5
AABB4499-5
AABB4499-5
这个函数的问题是,当一个字符被擦除时,索引仍然会增加。所以一些相邻的字符将仍然在字符串中。
最好使用基于标准算法 std::remove
或 std::remove_if
.
这是一个演示程序
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
std::string FormatString( const std::string &s, const std::string &erased = " -" )
{
const char *data = erased.data();
std::string t( s );
t.erase( std::remove_if( t.begin(), t.end(), [=]( char c ) { return std::strchr( data, c ); } ),
t.end() );
return t;
}
int main()
{
std::string testString( "AA BB-4499--5" );
std::cout << FormatString( testString ) << std::endl;
return 0;
}
它的输出是
AABB44995
这是因为您在擦除后增加了位置。
当你擦除时,你将所有其他字符向下移动一个。如果您随后还增加了您在字符串中的位置,您实际上会跳过一个字符。
如果我们从这里开始:
"AA BB-4499--5"
删除几个字符后剩下这个
"AABB4499--5"
^ // i is 9.
您现在删除光标上方的字符。
"AABB4499-5"
^ // i is 9.
现在开始循环的下一次迭代。
"AABB4499-5"
^ // i is 10.
您注意到您跳过了一个字符。
这个算法更好的实现是:
for(size_t i = 0; i < S.length();) { // Notice no increment here
if((S[i] == ' ') || (S[i] == '-')) {
S.erase (i,1);
}
else {
++i;
}
}
我们可以用迭代器对此进行改进:
for(auto loop = std::begin(S); loop != std::end(S);) {
if (*loop == ' ' || *loop == '-') {
loop = S.erase(loop);
}
else {
++loop;
}
}
现在我们正在使用迭代器,我们可以在标准算法中循环
auto newEnd = std::remove_if(std::begin(S), std::end(S),
[](char c){return c == ' ' || c == '-';});
std::erase(newEnd, std::end(S));