Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
898 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  comparaison de chaine "case-insensitive" en c++

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

comparaison de chaine "case-insensitive" en c++

n°298865
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 01-02-2003 à 15:25:26  profilanswer
 

Je me demande quel le moyen le plus "propre" pour comparer deux std::string sans prendre en compte la casse des caractères ? strcasecmp c'est bien mais c'est pas du c++ et la portabilité est douteuse. Y'a une feinte avec les facets ou un truc du genre ?
 
Je précise que c'est pas pour comparer des chaine des caractères chinois en UTF8, c'est juste pour des chaines en ascii 7 bit donc rien de méchant

mood
Publicité
Posté le 01-02-2003 à 15:25:26  profilanswer
 

n°298867
gloop
Posté le 01-02-2003 à 15:30:46  profilanswer
 

Captain ad-hoc a écrit :

Je me demande quel le moyen le plus "propre" pour comparer deux std::string sans prendre en compte la casse des caractères ? strcasecmp c'est bien mais c'est pas du c++ et la portabilité est douteuse. Y'a une feinte avec les facets ou un truc du genre ?
 
Je précise que c'est pas pour comparer des chaine des caractères chinois en UTF8, c'est juste pour des chaines en ascii 7 bit donc rien de méchant


tu peux faire une boucle explicite pour comparer et utiliser toupper () sur chaque caractere pour la comparaison. dans la classe basic_string, y a pas de fonction pour la comparaison sans tenir compte de la casse

n°298881
Kristoph
Posté le 01-02-2003 à 15:50:12  profilanswer
 

Utilises ca avec une fonction de comparaison de char adaptée :
 
http://www.sgi.com/tech/stl/lexico [...] mpare.html


Message édité par Kristoph le 01-02-2003 à 15:51:40
n°298886
gloop
Posté le 01-02-2003 à 15:55:05  profilanswer
 

Kristoph a écrit :

Utilises ca avec une fonction de comparaison de char adaptée :
 
http://www.sgi.com/tech/stl/lexico [...] mpare.html


j'l'avais oublié celle la  :)  
mais ce qui est un peu chiant c'est qu'elle renvoie un booléen:

  • true lorsque la 1ere séquence est < à la 2è
  • false qd elles sont égales (logique !  :D )

par contre elle est utilisable sur toutes les séquences

n°298890
Taz
bisounours-codeur
Posté le 01-02-2003 à 15:59:09  profilanswer
 

ouaip, 2 solutions:
- copier les 2chaines a comparer, convertir chaque caractère en minuscule/majuscule avec std::toupper/std::tolower, et comparer avec le std::string::compare ou <, >, etc
 
- réécrire une std::strcmp, avec std::tolower(s1[i]) ?? std::tolower(s2[i]). sans doute la meilleur solution surtout si les chaines sont longues, à condtion de pas coder comme un pied. donc je propose
 
 

Code :
  1. #include <cctype>
  2. #include <string>
  3. int StringCaseCompare(const std::string &s1, const std::string &s2)
  4. {
  5.   int c1, c2;
  6.   const size_t len1(s1.length()), len2(s2.length()), min_len(std::min(len1, len2));
  7.   for(size_t i=0; i<min_len; ++i)
  8.     {
  9.       c1=std::tolower(s1[i]);
  10.       c2=std::tolower(s2[i]);
  11.       if(c1!=c2)
  12. {
  13.   return c1-c2;
  14. }
  15.     }
  16.   return len1-len2;
  17. }


Message édité par Taz le 01-02-2003 à 16:06:56
n°298893
gloop
Posté le 01-02-2003 à 16:02:04  profilanswer
 

Code :
  1. int cmpNoCase (const std::string &s1, const std::string &s2)
  2. {
  3.    std::string::const_iterator i1 = s1.begin ();
  4.    std::string::const_iterator i2 = s2.begin ();
  5.    while (i1 != s1.end () && i2 != s2.end ())
  6.    {
  7.       if (toupper (*i1) != toupper (*i2))
  8.          return (toupper (*i1) < toupper (*i2)) ? -1 : 1;
  9.       ++i1; ++i2;
  10.    }
  11.    return (s1.size () == s2.size ()) ? 0 : (s1.size () < s2.size () ? -1 : 1);
  12. }

n°298896
Taz
bisounours-codeur
Posté le 01-02-2003 à 16:03:07  profilanswer
 

ma version est bien plus performante  :na:
 
edit: arg, j'ai oublié de traiter le cas final

Message cité 1 fois
Message édité par Taz le 01-02-2003 à 16:05:40
n°298897
gloop
Posté le 01-02-2003 à 16:04:21  profilanswer
 

++Taz a écrit :

ma version est bien plus performante  :na:  


mais elle marche mal   :na:

n°298898
Taz
bisounours-codeur
Posté le 01-02-2003 à 16:07:41  profilanswer
 

gloop a écrit :


mais elle marche mal   :na:  

a y est.
 
il me semble que strcmp renvoie une différence de caractère et pas seulement -1, 0, ou 1...  
 
edit: oups, ça dépend de l'implémentation: en fait c'est valeur <0, ==0 ou >0


Message édité par Taz le 01-02-2003 à 16:11:46
n°298902
Taz
bisounours-codeur
Posté le 01-02-2003 à 16:12:55  profilanswer
 

gloop a écrit :


mais elle marche mal   :na:  

cela dit merci à toi de montrer par l'exemple que bien que les string soit des pseudo-containers, elles proposent des itérateurs  :jap:

mood
Publicité
Posté le 01-02-2003 à 16:12:55  profilanswer
 

n°298904
Captain ad​-hoc
miam les bon batonnets de tux
Posté le 01-02-2003 à 16:13:18  profilanswer
 

ok, merci les ptits gars pour vos réponses [:welcom] c'est quand même dommage qu'il n'y ait rien de tout cuit pour ça dans la class basic_string je trouve  :(

n°298911
Taz
bisounours-codeur
Posté le 01-02-2003 à 16:21:16  profilanswer
 

skom ça...faut dire aussi que la comarasion pas sensible à la casse est tres dure à définir (en francais, les majuscules doivent etre accentuées ou avoir une cédille, personne ne le fait, et pourtant), cela dépend beaucoup du contexte local.

n°298927
HelloWorld
Salut tout le monde!
Posté le 01-02-2003 à 16:52:27  profilanswer
 

Ce cas figure dans un bouquin ("mieux programmer en C++" je crois)
Malheureusement je ne l'ai pas sous les yeux et c'est assez loin :(
Je me souvient qu'ils ont créé leur propre fonction compare de char_traits que string utilise et ont créé leur classe identique a string sauf qu'elle utilise cette fonction de comparaison. Y'avait ensuite une discution sur l'utilité d'une telle classe ... arf c'est un peu loin.
Mais voila de quoi te donner un piste :
la fonction de comparaison utilisee est dans char_traits.h

Code :
  1. // class char_traits<char>
  2. static int compare(const char* __s1, const char* __s2, size_t __n)
  3.     { return memcmp(__s1, __s2, __n); }


faut remplacer par memicmp.
 
string est definie ainsi :

Code :
  1. template <class _CharT,
  2.           class _Traits = char_traits<_CharT>,
  3.           class _Alloc = __STL_DEFAULT_ALLOCATOR(_CharT) >
  4. class basic_string;
  5. typedef basic_string<char>    string;


 
faut modifier le char_traits utilisé, peut etre un truc du genre :

Code :
  1. template <class _CharT,
  2.           class _Traits = ichar_traits<_CharT>,
  3.           class _Alloc = __STL_DEFAULT_ALLOCATOR(_CharT) >
  4. class [b]insensitive_string[b];
  5. typedef insensitive_string<char>    istring;


 
enfin c'est une piste, car les templates, je m'y suis jamais plongé.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°298929
gloop
Posté le 01-02-2003 à 16:56:31  profilanswer
 

HelloWorld a écrit :

Ce cas figure dans un bouquin ("mieux programmer en C++" je crois)
Malheureusement je ne l'ai pas sous les yeux et c'est assez loin :(
Je me souvient qu'ils ont créé leur propre fonction compare de char_traits que string utilise et ont créé leur classe identique a string sauf qu'elle utilise cette fonction de comparaison. Y'avait ensuite une discution sur l'utilité d'une telle classe ... arf c'est un peu loin.
Mais voila de quoi te donner un piste :
la fonction de comparaison utilisee est dans char_traits.h

Code :
  1. // class char_traits<char>
  2. static int compare(const char* __s1, const char* __s2, size_t __n)
  3.     { return memcmp(__s1, __s2, __n); }


faut remplacer par memicmp.
 
string est definie ainsi :

Code :
  1. template <class _CharT,
  2.           class _Traits = char_traits<_CharT>,
  3.           class _Alloc = __STL_DEFAULT_ALLOCATOR(_CharT) >
  4. class basic_string;
  5. typedef basic_string<char>    string;


 
faut modifier le char_traits utilisé, peut etre un truc du genre :

Code :
  1. template <class _CharT,
  2.           class _Traits = ichar_traits<_CharT>,
  3.           class _Alloc = __STL_DEFAULT_ALLOCATOR(_CharT) >
  4. class [b]insensitive_string[b];
  5. typedef insensitive_string<char>    istring;


 
enfin c'est une piste, car les templates, je m'y suis jamais plongé.


 
c une bonne idée , mais ca oblige à utiliser 2 types pour les chaines de caractéres. et en + si t'as besoin de comparer un string et istring, c pas le + pratique

n°299276
HelloWorld
Salut tout le monde!
Posté le 02-02-2003 à 01:50:50  profilanswer
 

Je crois que c'etait un des points souleves quant a l'utilite de cette classe : que faire lors de la comparaison d'une string avec une istring.
Et sinon, un simple

Code :
  1. bool IsEqual( std::string s1, std::string s2 )
  2. {
  3.     return ( ::stricmp( s1.c_str(), s2.c_str() ) == 0 ),
  4. }


 
Parce que bon, copier les 2 chaines, les convertir en upper, ca me parrait bourrin quand même.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°299278
HelloWorld
Salut tout le monde!
Posté le 02-02-2003 à 02:04:54  profilanswer
 
n°299303
Taz
bisounours-codeur
Posté le 02-02-2003 à 07:19:52  profilanswer
 

trucicmp connait po  :na:  
 
avec gloop on s'est employé a trouver la solution standard, sinon j'aurais vite dégainé une page de man. bien joué les liens de HW, c'est une bonne idée de tout enrober dans une classe, mais j'aurais pas été jusqu'au point de créer un nouveau type de string, je me serai contenté de fonctions membres statiques pour usage

n°299452
HelloWorld
Salut tout le monde!
Posté le 02-02-2003 à 16:16:55  profilanswer
 

Je savais pas que c'etait pas standard.
On la trouve quand meme a peu pres partout cette fonction. C'est un standard du non-standard ! :)


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°299460
Taz
bisounours-codeur
Posté le 02-02-2003 à 16:36:02  profilanswer
 

PARTOUT mais pas POSIX  :pfff:

n°300805
schbounz
Posté le 04-02-2003 à 12:09:34  profilanswer
 

Coucou,  
 
Je sais qu'au depart on ne compare que des chaines de caracteres 7bits, mais si on s'interresse au probleme des accents, quelle est la meilleure solution.  
 
Deux cas :  
1- on veut ignorer la casse ET les accents,  
2- on veut ignorer la casse mais respecter les accents,  
 
Perso je vois pas d'autre solution qu'une implementation similaire a celle de ++Taz, ou l'on ferait caractere par caractere et, si le caractere n'est pas ascii (<0) on se tape une recherche dans une table associant chaque caractere special a son equivalent majuscule, avec ou sans accent suivant le cas.  
 
Qu'en pensez vous ?  
 

n°1760182
le_num
Posté le 16-07-2008 à 11:48:31  profilanswer
 

Taz a écrit :

ma version est bien plus performante  :na:
 
edit: arg, j'ai oublié de traiter le cas final


 
 
 
Bonjour Taz,
 
Ton code me plait mais je ne vois pas de quel cas final tu parles?
merci de m'apporter une précision.

n°1760412
theshockwa​ve
I work at a firm named Koslow
Posté le 16-07-2008 à 16:41:47  profilanswer
 

le_num a écrit :


 
 
 
Bonjour Taz,
 
Ton code me plait mais je ne vois pas de quel cas final tu parles?
merci de m'apporter une précision.


 
il a déjà edité et corrigé, c'est pour ca que ca te plait [:dawa]

n°1760549
kyntriad
Posté le 16-07-2008 à 20:53:28  profilanswer
 

ya un Gotw à ce propos:
 
http://www.gotw.ca/gotw/029.htm


---------------
You can't start a fire with moonlight
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  comparaison de chaine "case-insensitive" en c++

 

Sujets relatifs
transformer un nombre en chaine de charactères en FORTRANlimiter les espaces ds une chaîne
[Linux-C] Convertion entier vers chaine ??lire une chaine de caractere ?
[ PHP ] les 3 derniers carracteres d une chaine...[Algo/C] Grande chaine de caractères pour test d'un algorithme
Comparaison de tableau en PHPRecuperer une chaine de caractere d'une iframe
Génération d'une chaîne de caractèrerecuperer une page WEB en chaine de caracteres
Plus de sujets relatifs à : comparaison de chaine "case-insensitive" en c++


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR