it-swarm.com.de

Wie werden alle nicht alphanumerischen Zeichen aus einer Zeichenfolge in C++ entfernt?

Ich schreibe eine Software, und ich muss mit Daten umgehen, die ich mit libcurl von einer Webseite bekomme. Wenn ich die Daten erhalte, enthält das aus irgendeinem Grund zusätzliche Zeilenumbrüche. Ich muss einen Weg finden, nur Buchstaben, Zahlen und Leerzeichen zuzulassen. Und entfernen Sie alles andere, einschließlich Zeilenumbrüche. Gibt es eine einfache Möglichkeit, dies zu tun? Vielen Dank.

22

Schreiben Sie eine Funktion, die eine char verwendet und true zurückgibt, wenn Sie das Zeichen entfernen möchten, oder false, wenn Sie es behalten möchten:

bool my_predicate(char c);

Verwenden Sie dann den std::remove_if-Algorithmus, um die unerwünschten Zeichen aus der Zeichenfolge zu entfernen:

std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

Abhängig von Ihren Anforderungen können Sie möglicherweise eines der Prädikate der Standardbibliothek wie std::isalnum verwenden, anstatt ein eigenes Prädikat zu schreiben (Sie sagten, Sie müssten alphanumerische Zeichen und Leerzeichen angeben, daher ist dies möglicherweise nicht genau das, was Sie benötigen ).

Wenn Sie die std::isalnum-Funktion der Standardbibliothek verwenden möchten, benötigen Sie eine Besetzung, um zwischen der std::isalnum-Funktion im C-Standardbibliothek-Header <cctype> (die Sie verwenden möchten) und dem std::isalnum im C++ Standard Library-Header <locale> ( Dies ist nicht das, was Sie verwenden möchten, es sei denn, Sie möchten eine locale-spezifische Zeichenfolgenverarbeitung durchführen.)

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

Dies funktioniert genauso gut mit jedem Sequenzcontainer (einschließlich std::string, std::vector und std::deque). Diese Redewendung wird im Allgemeinen als "Erase/Remove" -Idom bezeichnet. Der std::remove_if-Algorithmus funktioniert auch mit gewöhnlichen Arrays. Der std::remove_if führt die Sequenz nur einmal durch, daher ist die zeitliche Komplexität linear. 

43
James McNellis

Frühere Verwendungen von std::isalnum können nicht mit std::ptr_fun kompiliert werden, ohne dass das Argument unary erforderlich ist. Daher sollte diese Lösung mit einer Lambda-Funktion die richtige Antwort enthalten: 

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
6
Dado

Sie können immer durchgehen und nur erase alle nicht alphanumerischen Zeichen verwenden, wenn Sie string verwenden.

#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++;
}

Jemand, der mit der Standard Lib besser ist, kann dies wahrscheinlich ohne Schleife tun.

Wenn Sie nur einen char-Puffer verwenden, können Sie durchlaufen und wenn ein Zeichen nicht alphanumerisch ist, verschieben Sie alle Zeichen dahinter um eins (um das fehlerhafte Zeichen zu überschreiben):

#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);
4
Seth Carnegie

Der Algorithmus remove_copy_if standard wäre für Ihren Fall sehr geeignet.

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

Ergebnisse in:

"HelloWorld"

Sie verwenden isalnum, um zu bestimmen, ob jedes Zeichen alphanumerisch ist oder nicht. Mit ptr_fun können Sie die Funktion an not1 übergeben, der NICHT den zurückgegebenen Wert enthält, sodass nur das gewünschte alphanumerische Zeichen übrig bleibt.

2
TankorSmash

Sie können den Remove-Erase-Algorithmus auf diese Weise verwenden - 

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
1
akritaag

Der folgende Code sollte für die angegebene Zeichenfolge s gut funktionieren. Es verwendet <algorithm>- und <locale>-Bibliotheken.

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());
1
Dhruv Kakadiya

Nur den Code von James McNellis etwas mehr erweitern. Seine Funktion ist das Löschen von Alnum-Zeichen anstelle von Nicht-Alnum-Zeichen.

So löschen Sie Nicht-Alnum-Zeichen aus einer Zeichenfolge. (alnum = alphabetisch oder numerisch)

  • Deklarieren einer Funktion (isalnum gibt 0 zurück, wenn übergebenes Zeichen kein Alnum ist)

    bool isNotAlnum(char c) {
        return isalnum(c) == 0;
    }
    
  • Und dann schreibe das

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

dann ist Ihre Zeichenfolge nur mit Alnum-Zeichen.

1
Ali Eren Çelik

Die erwähnte Lösung

s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());

ist sehr schön, funktioniert aber leider nicht mit Zeichen wie 'Ñ' in Visual Studio (Debug-Modus), wegen dieser Zeile:

_ASSERTE((unsigned)(c + 1) <= 256)

in isctype.c

Also würde ich so etwas empfehlen:

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());
0
Andres Hurtis

Folgendes funktioniert für mich.

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
Pabitra Dash
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;
}
0
Imran Saeed