11
votes

Comment puis-je vérifier si une chaîne comporte des caractères spéciaux en C ++ efficacement?

J'essaie de trouver s'il y a une meilleure façon de vérifier si la chaîne a des caractères spéciaux. Dans mon cas, autre chose que l'alphanumérique et un '_' est considéré comme un caractère spécial. Actuellement, j'ai une chaîne contenant des caractères spéciaux tels que STD :: String = "! @ # $% ^ &". J'utilise ensuite l'algorithme STD :: Find_First_of () pour vérifier si l'un des caractères spéciaux est présent dans la chaîne.

Je me demandais comment le faire en fonction de la liste de bain. Je souhaite spécifier les caractères minuscules / majuscules, les numéros et un soulignement dans une chaîne (je ne veux pas les énumérer. Y a-t-il une façon de spécifier la gamme ASCII de quelque sorte comme [A-ZA-Z0-9_] ). Comment puis-je atteindre cet objectif? Ensuite, je prévois d'utiliser le std :: Find_First_not_of (). De cette façon, je peux mentionner ce que je veux réellement et vérifier le contraire.


3 commentaires

Stackoverflow.com/q/1120198/82705


@Sai Ganesh: langue différente là-bas (C #)


C ++ n'assume pas ASCII. Il est même compatible avec EBCDIC, dans lequel A-Z n'est pas contiguë.


9 Réponses :


17
votes

Essayez: xxx

ou essayez de booster les expressions régulières: xxx


3 commentaires

Je sais que je peux le faire, mais je me demandais que je pourrais mentionner la gamme, telle que la plage de valeurs [A-Z A-Z 0-9 _] ou ASCII ou quelque chose.


@Praveen: version de boost ajoutée.


Regex va beaucoup plus simple depuis le poste: #include ; /*....*/ Si (! STD :: REGEX_MATCH (STR_VAL, STD :: REGEX ("[A-ZA-Z0-9 \ -_] +")) Jette;



1
votes

Les fonctions (macros) sont soumises aux paramètres de paramètres régionaux, mais vous devriez étudier iSalnum () et des parents de ou .


0 commentaires

0
votes

J'utiliserais simplement l'installation C intégrée ici. Itérate sur chaque caractère de la chaîne et vérifiez s'il est _ ou si isalpha (ch) est vrai. Si oui, alors c'est valide, sinon c'est un caractère spécial.


0 commentaires

3
votes

Il n'y a aucun moyen d'utiliser Standard C ou C ++ pour le faire à l'aide de plages de caractères, vous devez répertorier tous les caractères. Pour C Strings, vous pouvez utiliser strSpn (3) code> et strcspn (3) code> pour trouver le premier caractère d'une chaîne C'est un membre ou n'est pas membre d'un jeu de caractères donné. Par exemple:

// Test if the given string has anything not in A-Za-z0-9_
bool HasSpecialCharacters(const char *str)
{
    return str[strspn(str, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")] != 0;
}


0 commentaires

3
votes

La première chose à considérer est "Est-ce que ceci est seulement"? Si vous répondez est oui, je vous encourage-vous à déterminer vraiment si vous devez ou non laisser ASCII uniquement. Je travaille actuellement pour une entreprise qui a vraiment des maux de tête dans les marchés étrangers, car nous n'avions pas pensé à soutenir Unicode à partir de la gobing.

Cela étant dit, ASCII rend vraiment facile à vérifier pour les numériques non alpha. Jetez un coup d'œil au tableau ASCII.

http://fr.wikipedia.org/wiki/ascii#ascii_printable_characters < / p>

  • Itérale à travers chaque personnage
  • Vérifiez si le personnage est une valeur décimale 48 - 57, 65 - 90, 97 - 122, ou 95 (soussecore)

0 commentaires

0
votes

Si vous le souhaitez, mais ne voulez pas aller à l'ensemble du porc et utilisez REGEXPS, et étant donné que vous êtes testé, c'est pour les caractères ASCII - Créez simplement une fonction pour générer la chaîne pour Find_First_not_of code> ...

#include <iostream>
#include <string>

std::string expand(const char* p)
{
    std::string result;
    while (*p)
        if (p[1] == '-' && p[2])
        {
            for (int c = p[0]; c <= p[2]; ++c)
                result += (char)c;
            p += 3;
        }
        else
            result += *p++;
    return result;
}

int main()
{
    std::cout << expand("A-Za-z0-9_") << '\n';
}


0 commentaires

4
votes

Je pense que je ferais le travail juste un peu différemment, traiter le std :: string code> en tant que collection et en utilisant un algorithme. Utilisation d'un C ++ 0x Lambda, il ressemblerait à quelque chose comme ceci: xxx pré>

au moins lorsque vous traitez avec char code> (pas wchar_t code>), isalnum code> utilisera généralement une table lève-t-il, il sera donc généralement plus rapide que n'importe quoi basé sur Find_first_of code> (qui utilisera normalement un recherche linéaire à la place). Iow, c'est O (n) (n = str.size ()), où quelque chose basé sur wind_first_of code> sera O (n * m), (n = str.size (), m = motif.size ()). p>

Si vous voulez faire le travail avec pure C, vous pouvez utiliser scanef code> avec une conversion de scanset théoriquement non portable, mais supportée par essentiellement Tous les compilateurs récents / populaires: P>

char junk;
if (sscanf(str, "%*[A-Za-z0-9_]%c", &junk))
    /* it has at least one "special" character
else
    /* no special characters */


3 commentaires

Isalnum est optimisé, il ne fait pas une liste de tables, mais elle vérifie si le caractère est dans une plage: le code fonctionne comme ('0' <= '= C && C <=' 9 ') || ('A' <= c && c <= 'z') || ('a' <= c && c <= 'z') où c est le caractère. Il utilise le fait que les caractères (d'un groupe comme des lettres ou des chiffres supérieurs ou inférieurs) sont linéaires après l'autre en ASCII. Ceci est plus efficace que la regex (qui nécessite un analyseur ou un interpréteur) ou Find_First_not_of.


@CMDLP: Il appartient à la mise en œuvre de décider comment la mettre en œuvre, bien sûr. Cela dit, ici (pour un exemple) est de savoir comment il est mis en œuvre dans LIBSTDC ++ pour Linux: Retour _M_TABLE [STATIC_CAST (__ C)] & __M; . (de: GCC / LIBSTDC ++ - V3 / CONFIG / OS / GNU-Linux / CTYPE_INLLINE.H). Et à libcxx, c'est: retour isasciii (c)? (CTYPE :: Classic_Table () [c] & m)! = 0: false; . (libcxx / src / locale.cpp). Donc, alors qu'il peut y avoir des exceptions, il est généralement basé sur la table.


@CMDLP: Si vous en connaissez un lieu où il est basé sur la comparaison avec les gammes, je serais intéressé à savoir ce que c'est - je crois à l'heure actuelle, qui est de bonne chance d'être plus efficace qu'une table Recherche, mais je ne connais aucune mise en œuvre qui le fait réellement.



0
votes

Utiliser

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

    bool my_predicate(char c)
    {
     return !(isalpha(c) || c=='_');
    }


0 commentaires

0
votes

Vous pouvez utiliser quelque chose comme ceci:

#include <ctype>

for(int i=0;i<s.length();i++){
    if( !std::isalpha(s[i]) && !std::isdigit(s[i]) && s[i]!='_')
          return false
}


0 commentaires