web-dev-qa-db-fra.com

Comment effacer tous les caractères non alphanumériques d'une chaîne en c ++?

Je suis en train d’écrire un logiciel et il m’oblige à manipuler les données d’une page Web contenant libcurl. Lorsque je reçois les données, il y a des sauts de ligne supplémentaires pour une raison quelconque. Je dois trouver un moyen de ne permettre que les lettres, les chiffres et les espaces. Et supprimez tout le reste, y compris les sauts de ligne. Y at-il un moyen facile de faire cela? Merci.

22
Austin Witherspoon

Ecrivez une fonction qui prend une char et retourne true si vous souhaitez supprimer ce caractère ou false si vous souhaitez la conserver:

bool my_predicate(char c);

Ensuite, utilisez l'algorithme std::remove_if pour supprimer les caractères indésirables de la chaîne:

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

Selon vos besoins, vous pourrez peut-être utiliser l’un des prédicats de la bibliothèque standard, tel que std::isalnum, au lieu d’écrire votre propre prédicat (vous avez dit que vous deviez faire correspondre les caractères alphanumériques et les espaces, alors peut-être que cela ne correspond pas exactement à vos besoins. ).

Si vous souhaitez utiliser la fonction std::isalnum de la bibliothèque standard, vous aurez besoin d'un transtypage pour distinguer la fonction std::isalnum dans l'en-tête C de la bibliothèque standard C <cctype> (qui est celui que vous souhaitez utiliser) et le std::isalnum dans l'en-tête C++ Standard Library <locale> ( qui ne correspond pas à celui que vous souhaitez utiliser, sauf si vous souhaitez effectuer un traitement de chaîne spécifique à l'environnement local):

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

Cela fonctionne aussi bien avec l’un des conteneurs de séquence (y compris std::string, std::vector et std::deque). Cet idiome est communément appelé l'idiome "effacer/supprimer". L'algorithme std::remove_if fonctionnera également avec les tableaux ordinaires. Le std::remove_if ne fait qu'un seul passage sur la séquence, de sorte qu'il a une complexité temporelle linéaire. 

43
James McNellis

Les utilisations précédentes de std::isalnum ne seront pas compilées avec std::ptr_fun sans passer l'argument unary est requis, c'est pourquoi cette solution avec une fonction lambda devrait encapsuler la réponse correcte: 

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

Si vous utilisez erase, vous pouvez toujours parcourir et ne modifier que string tous les caractères non alphanumériques.

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

Quelqu'un de mieux avec le Standard Lib peut probablement le faire sans boucle.

Si vous utilisez uniquement un tampon char, vous pouvez effectuer une boucle et si un caractère n'est pas alphanumérique, décaler tous les caractères après le caractère précédent (pour écraser le caractère incriminé):

#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

L'algorithme remove_copy_if standard serait très approprié pour votre cas.

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;

Résulte en:

"HelloWorld"

Vous utilisez isalnum pour déterminer si chaque caractère est alphanumérique, puis ptr_fun pour transmettre la fonction à not1, ce qui N'A PAS la valeur renvoyée, vous laissant ainsi uniquement le contenu alphanumérique souhaité.

2
TankorSmash

Vous pouvez utiliser l'algorithme remove-erase de cette façon - 

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

Le code ci-dessous devrait fonctionner parfaitement pour la chaîne s. Il utilise les bibliothèques <algorithm> et <locale>.

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

Étendre juste un peu plus le code de James McNellis. Sa fonction est de supprimer des caractères d'alnum au lieu de ceux qui ne le sont pas.

Pour supprimer des caractères non-alnum d'une chaîne. (alnum = alphabétique ou numérique)

  • Déclarer une fonction (isalnum renvoie 0 si le caractère transmis n'est pas alnum)

    bool isNotAlnum(char c) {
        return isalnum(c) == 0;
    }
    
  • Et puis écris ceci

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

alors votre chaîne est uniquement composée de caractères alnum.

1
Ali Eren Çelik

Ce qui suit fonctionne pour moi.

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