2011-06-12 135 views
21

我正在编写一个软件,它需要我处理从libcurl网页获得的数据。当我得到数据时,出于某种原因,它有额外的换行符。我需要找出一种只允许字母,数字和空格的方法。并删除其他所有内容,包括换行符。有没有简单的方法来做到这一点?谢谢。如何从C++中的字符串中去除所有非字母数字字符?

+0

你是如何存储数据?在'char'缓冲区或'string'中? – 2011-06-12 03:06:40

回答

3

如果您使用的是string,则可以始终循环使用所有非字母数字字符,并且只能使用erase

#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缓冲区,可以遍历,如果一个字符不是字母,却将所有的字符后,它向后一(覆盖有问题的字符):

#include <cctype> 

size_t buflen = something; 
for (size_t i = 0; i < buflen; ++i) 
    if (!isalnum(buf[i]) || buf[i] != ' ') 
     memcpy(buf[i], buf[i + 1], --buflen - i); 
+1

消除循环将涉及[erase-remove idiom](http://en.wikipedia.org/wiki/Erase-remove_idiom) – 2011-06-12 03:12:54

+0

在第二种情况下,如果您维护源指针和目标指针,则可以避免执行memcpy每次需要删除一个角色时,剩下的缓冲区的剩余空间。 (char * s = buf,* d = buf; * s; ++ s){if(!isalnum(* s)|| * s!='')* d ++ = * s; } * d = 0; – Ferruccio 2011-06-12 11:52:36

2

的标准算法将非常适合您的情况。

42

编写一个函数,需要一个char,如果你想,如果你想保留它删除该字符或false返回true

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标准库头<cctype>std::isalnum功能之间的歧义(这是您要使用的一个),并在C++标准的std::isalnum库头<locale>(除非你想执行特定语言环境的字符串处理这是不是您要使用的一个):

s.erase(std::remove_if(s.begin(), s.end(), (int(*)(int))std::isalnum), s.end()); 

这同样适用与任何序列容器(包括std::stringstd::vectorstd::deque )。这个成语通常被称为“擦除/删除”成语。 std::remove_if算法也适用于普通的数组。 std::remove_if只对序列进行一次通过,因此它具有线性时间复杂度。

+6

做到这一点,不是我的。 – 2011-06-12 03:13:56

+2

@詹姆斯:这是删除字母数字字符,而不是特殊字符。难道我做错了什么 ? – bjskishore123 2013-07-04 11:22:48

+2

它将删除字母数字字符而不是特殊字符,因为只要遇到字母数字字符,该字符就会从字符串中删除,因此'(int(*)(int))std :: isalnum'将返回'true'。 – 2013-12-28 22:35:16

1

您可以使用Remove-擦除算法这样 -

// Removes all punctuation  
s.erase(std::remove_if(s.begin(), s.end(), &ispunct), s.end()); 
2
#include <cctype> 
#include <string> 
#include <functional> 

std::string s = "Hello World!"; 
s.erase(std::remove_if(s.begin(), s.end(), 
    std::not1(std::ptr_fun(std::isalnum)), s.end()), s.end()); 
std::cout << s << std::endl; 

结果:

"HelloWorld" 

您使用isalnum来确定每个字符是否是字母数字,然后使用ptr_fun将函数传递给not1,这不是返回的值,只给出您想要的字母数字内容。

0

以下适用于我。

str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end()); 
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end()); 
0
void remove_spaces(string data) 
{ int i=0,j=0; 
    while(i<data.length()) 
    { 
     if (isalpha(data[i])) 
     { 
     data[i]=data[i]; 
     i++; 
     } 
     else 
      { 
      data.erase(i,1);} 
    } 
    cout<<data; 
} 
1

只是延长詹姆斯McNellis代码多一点点。他的功能是删除alnum字符而不是非alnum字符。

删除字符串中的非阿尔汉字符。 (alnum =字母或数字)

  • 声明一个函数(字符isalnum返回0,如果通过炭不alnum)

    bool isNotAlnum(char c) { 
        return isalnum(c) == 0; 
    } 
    
  • ,然后写该

    s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end()); 
    

那么你的字符串只与alnum字符。

1

上的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()); 
相关问题