从字符串中删除一些字符并复制它
deleting some characters from string and copying it
我试图通过这种愚蠢的方法从字符串中删除既不是数字也不是字母的字符,因为我没有得到其他方法(我是一个真正的初学者"just trying ")
我知道这种方法不对,但我的问题是它有什么问题,因为它不起作用,所以错误是什么 :S
string g = "9-=p98u;iu8y76";
string y;
int t = 0;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y[t++] = g[i];
}
else
continue;
}
g = y;
cout << g;
问题是y
的大小是0,是空的。访问它的元素(使用 y[t++]
)因此到达 "after" 字符串——它是缓冲区溢出和未定义的行为。
您需要延长 y
。要以对代码进行最少的更改来做到这一点,您可以这样做:
string g = "9-=p98u;iu8y76";
string y;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y.push_back(g[i]);
}
else
continue;
}
g = y;
cout << g;
当然,还有其他方法可以做到这一点。使用标准算法和 erase-remove 习惯用法会更符合 C++ 的习惯。整个代码可以替换为:
auto shouldBeRemoved = [](char c) { !(isdigit(c) || isalpha(c)) };
g.erase(std::remove_if(g.begin(), g.end(), shouldBeRemoved), g.end());
cout << g;
std::remove_if
通过重新组织范围来工作,以便将所有与谓词匹配的元素(即应该删除的元素)移动到所有要保留的元素之后。成员函数 erase
然后擦除所有移到后面的那些。
这是标准库合理表达的。像
auto digit_or_alpha = [](char c){ return isdigit(c) || isalpha(c); };
std::copy_if(g.begin(), g.end(), std::back_inserter(y), digit_or_alpha );
应该可以。 back_inserter 在 <iterator>
中。 Angew 提供了您的不起作用的原因。
问题在于您尝试扩展字符串的方式 y
。索引只能应用于字符串的域(即不能索引超出字符串的长度)
将y[t++] = g[i]
更改为y += g[i]
此外,我想提一下您不需要 else
分支。当执行到循环作用域结束时,会"automatically"continue
,不需要显式表达。
PS:是经典的C++,不是C++11,长颈鹿船长的回答我会接受
此类任务的一般方法是使用成员函数 erase 以及在 header <algorithm>
中声明的标准算法 std::remove_if
例如
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
s.erase( std::remove_if( s.begin(), s.end(),
[]( char c )
{
return !std::isalnum( ( unsigned char )c );
} ),
s.end() );
std::cout << s << std::endl;
return 0;
}
程序输出为
9-=p98u;iu8y76
9p98uiu8y76
至于你的代码,那么你正在尝试使用下标运算符
y[t++] = g[i];
对于空字符串
string y;
请注意,您可以使用一个函数 std::isalnum
而不是两个函数 std::isalpha
和 std::isdigit
,如我的演示程序所示。
如果您想自己编写循环,那么程序可以像这样
#include <iostream>
#include <string>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
std::string::size_type i = 0;
while ( i < s.length() && std::isalnum( ( unsigned char )s[i] ) ) ++i;
std::string::size_type j = i;
while ( i++ < s.length() )
{
if ( std::isalnum( ( unsigned char )s[i] ) ) s[j++] = s[i];
}
s.erase( j );
std::cout << s << std::endl;
return 0;
}
程序输出同上
9-=p98u;iu8y76
9p98uiu8y76
不需要使用额外的字符串来完成这个操作。
我试图通过这种愚蠢的方法从字符串中删除既不是数字也不是字母的字符,因为我没有得到其他方法(我是一个真正的初学者"just trying ")
我知道这种方法不对,但我的问题是它有什么问题,因为它不起作用,所以错误是什么 :S
string g = "9-=p98u;iu8y76";
string y;
int t = 0;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y[t++] = g[i];
}
else
continue;
}
g = y;
cout << g;
问题是y
的大小是0,是空的。访问它的元素(使用 y[t++]
)因此到达 "after" 字符串——它是缓冲区溢出和未定义的行为。
您需要延长 y
。要以对代码进行最少的更改来做到这一点,您可以这样做:
string g = "9-=p98u;iu8y76";
string y;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y.push_back(g[i]);
}
else
continue;
}
g = y;
cout << g;
当然,还有其他方法可以做到这一点。使用标准算法和 erase-remove 习惯用法会更符合 C++ 的习惯。整个代码可以替换为:
auto shouldBeRemoved = [](char c) { !(isdigit(c) || isalpha(c)) };
g.erase(std::remove_if(g.begin(), g.end(), shouldBeRemoved), g.end());
cout << g;
std::remove_if
通过重新组织范围来工作,以便将所有与谓词匹配的元素(即应该删除的元素)移动到所有要保留的元素之后。成员函数 erase
然后擦除所有移到后面的那些。
这是标准库合理表达的。像
auto digit_or_alpha = [](char c){ return isdigit(c) || isalpha(c); };
std::copy_if(g.begin(), g.end(), std::back_inserter(y), digit_or_alpha );
应该可以。 back_inserter 在 <iterator>
中。 Angew 提供了您的不起作用的原因。
问题在于您尝试扩展字符串的方式 y
。索引只能应用于字符串的域(即不能索引超出字符串的长度)
将y[t++] = g[i]
更改为y += g[i]
此外,我想提一下您不需要 else
分支。当执行到循环作用域结束时,会"automatically"continue
,不需要显式表达。
PS:是经典的C++,不是C++11,长颈鹿船长的回答我会接受
此类任务的一般方法是使用成员函数 erase 以及在 header <algorithm>
std::remove_if
例如
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
s.erase( std::remove_if( s.begin(), s.end(),
[]( char c )
{
return !std::isalnum( ( unsigned char )c );
} ),
s.end() );
std::cout << s << std::endl;
return 0;
}
程序输出为
9-=p98u;iu8y76
9p98uiu8y76
至于你的代码,那么你正在尝试使用下标运算符
y[t++] = g[i];
对于空字符串
string y;
请注意,您可以使用一个函数 std::isalnum
而不是两个函数 std::isalpha
和 std::isdigit
,如我的演示程序所示。
如果您想自己编写循环,那么程序可以像这样
#include <iostream>
#include <string>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
std::string::size_type i = 0;
while ( i < s.length() && std::isalnum( ( unsigned char )s[i] ) ) ++i;
std::string::size_type j = i;
while ( i++ < s.length() )
{
if ( std::isalnum( ( unsigned char )s[i] ) ) s[j++] = s[i];
}
s.erase( j );
std::cout << s << std::endl;
return 0;
}
程序输出同上
9-=p98u;iu8y76
9p98uiu8y76
不需要使用额外的字符串来完成这个操作。