2011-06-12 134 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()); 
相關問題