2011-01-04 6 views
4

Dans l'une de nos classe, monsieur a dit que le modèle permet de personnaliser le comportement de la classe, puis il a donné un exemple de classe de chaînes, avec quelques lignes de code. dans, nous pouvons le faire pour traiter 'a' et 'z' pareil, 'b' et 'y' pareil, 'c' et 'x' pareil et ainsi de suite. Similaire 'A' et 'Z' même, etc.implémenter une classe de chaînes avec un comportement personnalisé

"abc" == "zyx" est vrai;
"Abc" == "zyx" est faux;
« Abc == « Zyx » est vrai.

etc

Je pensais à mettre en œuvre cette classe de chaîne, mais je ne suis pas en mesure de le faire Comment pouvons-nous mettre en œuvre cette classe de chaîne à l'aide des modèles

?
+1

Je suis nouveau à C++ aussi bien, mais je pense que cela a quelque chose à voir avec traits de caractère. – dreamlax

Répondre

3

C'est très compliqué. Tout ce que vous devez écrire vos propres traits classe, en particulier, vous devez le déduire de char_traits<> modèle de classe et redéfinir eq() et COMPARE() fonction (Remarque: seule la redéfinition eq() ne fonctionnerait pas Même s'il n'y a aucun changement dans la redéfinition de compare(), vous devez l'écrire dans votre classe dérivée en tant que telle!). Disons cette classe de traits sequence_traits et appelez votre chaîne personnalisée sequence. Après tout, la chaîne est une séquence de caractères!

Note: Ce que je comprends de votre message que vous voulez alphabets[i] == alphabets[25-i] à traiter comme même, ce qui signifie, première lettre et la dernière lettre même, la deuxième lettre et deuxième dernière lettre même, et ainsi de suite!

struct sequence_traits : char_traits<char> 
{ 
    //'a' and 'z' are equal 
    //'b' and 'y' are equal 
    //'c' and 'x' are equal, and so on. 
    //that implies, 'a' + 'z' == 'b' + 'y' == 'c' + 'x' == 'd' + 'w == so on 
    //same for upper cases! 
    static bool eq(const char& left, const char& right) 
    { 
     return (left == right) || (left + right == 'a' + 'z') || (left + right == 'A' + 'Z') ; 
    } 
    static int compare(const char *first1, const char *first2, size_t count) 
    { 
     for (; 0 < count; --count, ++first1, ++first2) 
      if (!eq(*first1, *first2)) 
       return (lt(*first1, *first2) ? -1 : +1); 
     return (0); 
    } 
}; 

Et vous pouvez le faire typedef pour une utilisation facile:

typedef basic_string<char, sequence_traits> sequence; 

Vous avez terminé. Vous pouvez utiliser sequence maintenant.:-)

Exemple de travail: http://www.ideone.com/ByBRV


Lire cet article pour savoir comment cela fonctionne en détail: http://www.gotw.ca/gotw/029.htm

+0

Je ne suis pas sûr de C++, mais en C, les identifiants qui commencent par un trait de soulignement et une lettre majuscule (par exemple '_Left' et' _Right') sont réservés et leur utilisation entraîne un comportement indéfini. – dreamlax

+0

@dreamlax: qui a dit ça? – Nawaz

+2

@Nawaz: Dans la norme C++, §17.4.3.1.2 définit les identifiants réservés concernant les traits de soulignement, et §17.4.3.1 le paragraphe 3 définit le comportement de l'utilisation des identifiants réservés. – dreamlax

2

Vous voudrez regarder le type char_traits Voici un exemple d'un type de classe de traits que vous pouvez utiliser avec basic_string pour obtenir un type de chaîne de travail Si vous définissez votre propre classe de traits, vous pouvez Construire une chaîne personnalisée comme ceci:

class CustomTraits { ... }; 
typedef basic_string<char, CustomTraits> CustomString; 

Et maintenant les traits définis par CustomTraits seront utilisés pour déterminer le fonctionnement de la chaîne.

A titre d'exemple le long des lignes de ce que vous disiez, vous pourriez faire quelque chose comme ceci:

class CustomTraits: public char_traits<char> { 
public: 
    /* Redefine equality to compare 'a' and 'z' equal. */ 
    static bool eq(char one, char two) { 
     return one == two || (one == 'a' && two == 'z' || one == 'z' && two == 'a'); 
    } 
}; 
typedef basic_string<char, CustomTraits> StringWithAAndZEqual; 

Maintenant, vous pouvez utiliser le nouveau type et la classe traitera « a » et « z » identiquement.

+0

@templatetyepdef: Je pense que ce n'est PAS ce qu'il veut. ceci ne traite que 'a' et 'x' de manière équivalente, mais pas toutes les autres paires, comme 'b' et 'y', 'c' et 'x'. Je pense que ce qu'il veut est 'alphabets [i] == alphabets [25-i]' devrait être traité comme identique, ce qui signifie, première lettre et dernière lettre même, deuxième lettre et deuxième dernière lettre même, et ainsi de suite! – Nawaz

+1

cela ne fonctionne pas. cela fonctionne pour les paires 'a' et 'z', pas 'b' et 'y' etc. –

+1

Mes excuses - j'ai mal lu la question. C'était surtout une preuve de concept, cependant; il y a aussi quelques autres choses manquantes (telles que lt, compare, etc.) – templatetypedef

2

Vous voulez créer votre char_traits personnalisé et instancier std::basic_string avec cela.

+0

Pouvez-vous encore comparer deux chaînes std :: basic_string si elles ont des char_traits différents avec l'opérateur '=='? – dreamlax

+1

Pas naïvement. Si 'my_string' est une instance de votre chaîne personnalisée, alors vous devrez faire quelque chose comme' my_string == a_std_string.c_str() '. Il en va de même pour l'utilisation de votre chaîne avec des flux: vous devrez probablement utiliser 'std :: basic_string <> :: c_str()'. – wilhelmtell

Questions connexes