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

j'écris un logiciel, et il me faut gérer les données que je reçois d'une page Web avec libcurl. Quand je reçois les données, pour une raison quelconque, il a des sauts de ligne supplémentaires. Je dois trouver un moyen de n'autoriser que les lettres, les chiffres et les espaces. Et supprimez tout le reste, y compris les sauts de ligne. Est-il un moyen facile de faire cela? Grâce.

21
demandé sur Austin Witherspoon 2011-06-12 07:04:07

10 réponses

Ecrire une fonction qui prend un char et renvoie true si vous souhaitez supprimer ce caractère ou false si vous voulez le garder:

bool my_predicate(char c);

Puis std::remove_if algorithme 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 pouvez être en mesure d'utiliser l'un des prédicats de bibliothèque Standard, comme std::isalnum, au lieu d'écrire votre propre prédicat (vous avez dit que vous aviez besoin de faire correspondre les caractères alphanumériques et les espaces, alors peut-être que cela ne correspond pas exactement à ce dont vous avez besoin).

si vous voulez utiliser la bibliothèque Standard std::isalnum fonction, vous aurez besoin d'un plâtre pour lever l'ambiguïté entre le std::isalnum la fonction de la Bibliothèque C Standard en-tête <cctype> (qui est celui que vous voulez utiliser) et le std::isalnum dans l'en-tête de bibliothèque Standard C++<locale> (qui n'est pas celui que vous voulez utiliser, sauf si vous voulez effectuer un traitement de chaîne spécifique à une locale):

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

Ceci fonctionne aussi bien avec tous les conteneurs séquentiels (y compris std::string,std::vector et std::deque). Cet idiome est communément appelé le "effacer/supprimer" l'idiome. std::remove_if l'algorithme fonctionnera aussi avec des tableaux ordinaires. std::remove_if ne fait qu'un seul passage au-dessus de la séquence, donc il a une complexité temporelle linéaire.

43
répondu James McNellis 2011-06-12 03:27:25

vous pouvez toujours boucler la boucle et juste erase tous les caractères non alphanumériques si vous utilisez string.

#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 Lib Standard peut probablement le faire sans boucle.

si vous utilisez juste un char buffer, vous pouvez passer en boucle et si un caractère n'est pas alphanumérique, décalez tous les caractères après celui-ci vers l'arrière (pour écraser le caractère offensant):

#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);
3
répondu Seth Carnegie 2014-10-21 22:56:24

utilisations antérieures de std::isalnum ne compile pas avec std::ptr_fun sans passer le unaire argument est l'exige, d'où cette solution avec une fonction lambda doit encapsuler la réponse correcte:

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
3
répondu Dado 2017-08-05 12:08:56

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

2
répondu Eugen Constantin Dinca 2011-06-12 03:12:11
#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ésultat:

"HelloWorld"

Vous utilisez isalnum pour déterminer si chaque caractère est alphanumérique, utilisez ptr_fun pour passer à la fonction not1 qui Note la valeur retournée, vous laissant avec seulement la substance alphanumérique que vous voulez.

2
répondu TankorSmash 2016-01-02 16:34:12

Vous pouvez utiliser l'algorithme supprimer-effacer de cette façon -

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
1
répondu akritaag 2014-10-16 17:21:04

j'allonge juste un peu plus le code de James McNellis. Sa fonction est de supprimer les caractères alnum au lieu des non-alnum.

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

  • Déclarer une fonction (isalnum renvoie 0 si elle est adoptée char n'est pas alnum)

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

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

alors votre chaîne est seulement avec des caractères alnum.

1
répondu Ali Eren Çelik 2016-12-28 21:11:14

La suivante 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
répondu Pabitra Dash 2016-06-07 11:10:27
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
répondu Imran Saeed 2016-11-28 11:29:05

le code ci-dessous devrait fonctionner très bien pour une chaîne donnée s. C'est en utilisant <algorithm> et <locale> bibliothèques.

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());
0
répondu Dhruv Kakadiya 2018-09-23 02:15:35