C++ 如何在c+中从字符串中去除所有非字母数字字符+;?
我正在写一个软件,它需要我处理从libcurl网页上获取的数据。当我得到数据时,由于某种原因,它有额外的换行符。我需要找到一种只允许字母、数字和空格的方法。并删除所有其他内容,包括换行符。有什么简单的方法可以做到这一点吗?谢谢。如果您使用的是C++ 如何在c+中从字符串中去除所有非字母数字字符+;?,c++,string,libcurl,strip,alphanumeric,C++,String,Libcurl,Strip,Alphanumeric,我正在写一个软件,它需要我处理从libcurl网页上获取的数据。当我得到数据时,由于某种原因,它有额外的换行符。我需要找到一种只允许字母、数字和空格的方法。并删除所有其他内容,包括换行符。有什么简单的方法可以做到这一点吗?谢谢。如果您使用的是字符串,您可以循环浏览并删除所有非字母数字字符 #include <cctype> size_t i = 0; size_t len = str.length(); while(i < len){ if (!isalnum(str
字符串,您可以循环浏览并删除所有非字母数字字符
#include <cctype>
size_t i = 0;
size_t len = str.length();
while(i < len){
if (!isalnum(str[i]) || str[i] == ' '){
str.erase(i,1);
len--;
}else
i++;
}
标准算法非常适合您的情况。编写一个函数,如果要删除该字符,则该函数接受char
,并返回true
,如果要保留该字符,则返回false
:
bool my_predicate(char c);
然后使用std::remove_if
算法从字符串中删除不需要的字符:
std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());
根据您的需求,您可能可以使用标准库谓词之一,如std::isalnum
,而不是编写自己的谓词(您说过需要匹配字母数字字符和空格,因此这可能不完全符合您的需要)
如果您想使用标准库<代码> STD::ISALNUM 函数,则需要在C标准库头<代码> >代码>(即您要使用的)和<代码> STD::ISALNUM < /C> > C++标准库头<代码> <代码>之间的一个转换以消除歧义。(除非要执行特定于区域设置的字符串处理,否则该字符串不是您要使用的字符串):
这同样适用于任何序列容器(包括std::string
、std::vector
和std::deque
)。此习惯用法通常称为“擦除/删除”习惯用法。std::remove_if
算法也适用于普通数组。std::remove_if
只对序列进行一次传递,因此它具有线性时间复杂度。您可以这样使用remove-erase算法-
// Removes all punctuation
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
您可以使用isalnum
确定每个字符是否为字母数字,然后使用ptr\u fun
将函数传递到not1
,该函数不会返回值,只剩下您想要的字母数字内容。以下内容适合我
str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());
void删除_空格(字符串数据)
{int i=0,j=0;
而(i只是稍微扩展了James McNellis的代码。他的功能是删除alnum字符而不是非alnum字符
从字符串中删除非alnum字符。(alnum=字母或数字)
- 声明函数(如果传递的字符不是alnum,则isalnum返回0)
- 然后写下这个
s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
那么您的字符串只包含alnum个字符。以前使用的std::isalnum
如果不传递所需的一元参数,就无法使用std::ptr_fun
编译,因此此带有lambda函数的解决方案应封装正确答案:
s.erase(std::remove_if(s.begin(), s.end(),
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
对于给定的字符串s
,下面的代码应该可以正常工作。它利用了
和
库
std::string s("He!!llo Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());
上述解决方案
s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());
非常好,但不幸的是,在Visual Studio(调试模式)中不能使用像“ñ”这样的字符,因为这行代码:
_ASSERTE((unsigned)(c + 1) <= 256)
对不同的方法进行基准测试。
如果你正在寻找一个基准,我做了一个
(115830个周期)115.8ms->使用stringstream
(40434个周期)40.4ms->s.erase(std::remove_if(s.begin(),s.end(),[](charc){return!isalnum(c);}),s.end());
(40389个周期)40.4ms->s.erase(std::remove_if(s.begin(),s.end(),[](charc){return ispunt(c);}),s.end());
(42386个周期)42.4ms->s.erase(如果(s.begin()、s.end()、not1(ptr_fun((int(*)(int))isalnum))、s.end(),则删除_;
(42969个循环)43.0ms->s.erase(如果(s.begin(),s.end(),[](auto-const&c)->bool{return!isalnum(c);}),s.end(),则删除_;
(44829个循环)44.8ms->alnum_from_libc(s)见下文
(24505个周期)24.5ms->困惑?我的方法,见下文
(9717个周期)9.7ms->使用掩码和位运算符
原始长度:8286208,当前长度仅含alnum:5822471
- Stringstream会产生可怕的结果(但我们都知道这一点)
- 已经给出的不同答案给出了相同的运行时
- 以C的方式持续地提供更好的运行时(几乎快两倍!),这绝对值得考虑,而且它与C语言兼容
- 我的按位方法(也是C兼容的)速度快了400%以上
注意:所选答案必须修改,因为它只保留特殊字符
NB2:测试文件是一个(几乎)8192KB的文本文件,包含大约62个alnum和12个特殊字符,随机且均匀地写入
基准源代码
#包括
#包括
#包括
#包括
包括,我基本上避免了分支指令(if)由于掩码。我避免发布与C++标签的位操作,我有很多仇恨。
对于C风格的一个,我迭代字符串,并有两个索引:n
用于我们保留的字符,而I
用于遍历字符串,在这里我们一个接一个地测试它是数字、大写还是小写
添加此功能:
void strip\u special\u chars(char*s){
int n=0;
对于(int i=0;i
并用作:
chars1[s.size()+1]
memcpy(s1,s.c_str(),s.size());
带特殊字符(s1);
您是如何存储数据的?在字符
缓冲区或字符串
中?如果您维护源指针和目标指针,在第二种情况下,消除循环将涉及
bool isNotAlnum(char c) {
return isalnum(c) == 0;
}
s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
s.erase(std::remove_if(s.begin(), s.end(),
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
std::string s("He!!llo Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());
s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());
_ASSERTE((unsigned)(c + 1) <= 256)
inline int my_ispunct( int ch )
{
return std::ispunct(unsigned char(ch));
}
...
s.erase( std::remove_if(s.begin(), s.end(), &my_ispunct), s.end());