Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在c+中从字符串中去除所有非字母数字字符+;?_C++_String_Libcurl_Strip_Alphanumeric - Fatal编程技术网

C++ 如何在c+中从字符串中去除所有非字母数字字符+;?

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

我正在写一个软件,它需要我处理从libcurl网页上获取的数据。当我得到数据时,由于某种原因,它有额外的换行符。我需要找到一种只允许字母、数字和空格的方法。并删除所有其他内容,包括换行符。有什么简单的方法可以做到这一点吗?谢谢。

如果您使用的是
字符串,您可以循环浏览并删除所有非字母数字字符

#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());