372 votes

Comparaison de chaînes insensible à la casse en C ++

Quelle est la meilleure façon de faire une comparaison de chaîne insensible à la casse dans C ++ sans out transformer une chaîne en majuscules ou minuscules?

Aussi, quelles sont les méthodes que vous présentez, sont-ils Unicode amical? Sont-ils portables?

331voto

Rob Points 22239

Boost inclut un algorithme pratique pour cela:

 #include <boost/algorithm/string.hpp>
// Or, for fewer header dependencies:
//#include <boost/algorithm/string/predicate.hpp>

std::string str1 = "hello, world!";
std::string str2 = "HELLO, WORLD!";

if (boost::iequals(str1, str2))
{
    // Strings are identical
}
 

130voto

Timmmm Points 9909

Le problème avec boost est que vous devez lier avec et dépendre de boost. Pas facile dans certains cas (par exemple Android).

Et en utilisant char_traits, toutes vos comparaisons sont insensibles à la casse, ce qui n'est généralement pas ce que vous voulez.

Cela devrait suffire. Cela devrait être raisonnablement efficace. Ne gère pas unicode ou quoi que ce soit.

 bool iequals(const string& a, const string& b)
{
    unsigned int sz = a.size();
    if (b.size() != sz)
        return false;
    for (unsigned int i = 0; i < sz; ++i)
        if (tolower(a[i]) != tolower(b[i]))
            return false;
    return true;
}
 

123voto

wilhelmtell Points 25504

Profitez de la norme char_traits. Rappelons qu'un std::string est en fait un typedef pour std::basic_string<char>, ou plus explicitement, std::basic_string<char, std::char_traits<char> >. L' char_traits type décrit la façon dont les caractères comparer, comment ils ont copier, comment ils jetèrent etc. Tout ce que vous devez faire est de typedef une nouvelle chaîne sur basic_string,, et de les fournir avec votre propre char_traits qui comparent les cas insensiblement.

struct ci_char_traits : public char_traits<char> {
    static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
    static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
    static bool lt(char c1, char c2) { return toupper(c1) <  toupper(c2); }
    static int compare(const char* s1, const char* s2, size_t n) {
        while( n-- != 0 ) {
            if( toupper(*s1) < toupper(*s2) ) return -1;
            if( toupper(*s1) > toupper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a) {
        while( n-- > 0 && toupper(*s) != toupper(a) ) {
            ++s;
        }
        return s;
    }
};

typedef std::basic_string<char, ci_char_traits> ci_string;

Les détails sont sur le Gourou de La Semaine, au nombre de 29.

64voto

Derek Park Points 25025

Si vous êtes sur un système POSIX, vous pouvez utiliser strcasecmp. Cette fonction ne fait pas partie de la norme C, si, ni est-il disponible sur Windows. Cela permettra d'effectuer une comparaison sensible à la casse sur les 8 bits de caractères, aussi longtemps que l'endroit est POSIX. Si la localisation n'est pas POSIX, les résultats ne sont pas définis (donc il peut faire une version localisée de comparer, ou il ne pourrait pas). Un grand caractère équivalent n'est pas disponible.

Sur Windows, vous pouvez utiliser le _stricmp ou _wcsicmp fonctions pour effectuer la comparaison sensible à la casse. Ces fonctions utilisent les paramètres régionaux en cours de l'information, et la version grand caractère est disponible. Cependant, celles-ci sont évidemment spécifiques à Windows.

Le C et le C++ sont à la fois largement ignorants des enjeux liés à l'internationalisation, donc il n'y a pas de bonne solution à ce problème, sauf à utiliser une bibliothèque tierce. Découvrez IBM unité de soins intensifs (International Components for Unicode) si vous avez besoin d'une bibliothèque robuste pour le C/C++. ICU est pour les systèmes Windows et Unix.

57voto

Coincoin Points 12823

Êtes-vous en parler un muet casse de comparer ou d'un plein normalisé Unicode comparer?

Un idiot de les comparer ne trouverez pas des chaînes de caractères qui peut être le même, mais ne sont pas binaire égale.

Exemple:

U212B (ANGSTROM SIGN)
U0041 (LATIN CAPITAL LETTER A) + U030A (COMBINING RING ABOVE)
U00C5 (LATIN CAPITAL LETTER A WITH RING ABOVE).

Sont tous équivalents, mais ils ont aussi des différentes représentations binaires.

Cela dit, la Normalisation Unicode devrait être obligatoire de le lire surtout si vous comptez sur le soutien de Hangul, Thaï et d'autres langues asiatiques.

Aussi, IBM assez bien breveté le plus optimisé Unicode algorithmes et mis à la disposition du public. Ils permettent également de maintenir une mise en œuvre : IBM soins intensifs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X