2009-03-14 5 views
0

J'ai essayé d'obtenir un modèle qui convertit les caractères d'une chaîne en majuscules.Utilisation d'un modèle

Je dois faire cela plusieurs fois tout au long de mon programme.

Alors, je vais utiliser un modèle.

template <string theString> 
string strUpper(string theString) 
{ 
    int myLength = theString.length(); 
    for(int sIndex=0; sIndex < myLength; sIndex++) 
    { 
     if (97 <= theString[sIndex] && theString[sIndex] <= 122) 
     { 
     theString[sIndex] -= 32; 
     } 
    } 
    return theString; 
} 

maintenant seulement si le modèle a fonctionné! Des suggestions? L'identifiant 'string' devrait être un drapeau immédiat.

+1

Pourquoi cela est-il nécessaire/voulez-vous que ce soit un modèle? –

+0

Comment les chaînes sont-elles codées? – BigSandwich

+1

Daniel L a raison - il suffit de supprimer la ligne supérieure (en faisant de strUpper() une fonction non-template régulière) et tout fonctionnera comme vous le souhaitez. –

Répondre

7

Vous parlez apparemment de C++ (pas encore de tags, donc je pense que c'est du C++ ici). Eh bien, vous semblez vouloir dire

Comme arguments à mon modèle, j'accepte tout type modèles une chaîne

Malheureusement, actuellement ce n'est pas encore possible. Il nécessite la fonctionnalité concept qui sera dans la prochaine version C++. Here est une vidéo à leur sujet.

Ce que vous pouvez faire est d'accepter basic_string<CharT, TraitsT> si vous voulez le garder générique, par exemple si vous voulez accepter des chaînes larges caractères aswell comme des chaînes étroites de caractère

template <typename CharT, typename TraitsT> 
std::basic_string<CharT, TraitsT> strUpper(basic_string<CharT, TraitsT> theString) { 
    typedef basic_string<CharT, TraitsT> StringT; 
    for(typename StringT::iterator it = theString.begin(); 
     it != theString.end(); 
     ++it) 
    { 
     *it = std::toupper(*it, std::locale()); 
    } 
    return theString; 
} 

Il n'acceptera d'autres ou classes de cordes personnalisées ce qui arrive à être chaînes aussi. Si vous voulez que le garder totalement libre de ce qu'il accepte et ce qui ne

template <typename StringT> 
StringT strUpper(StringT theString) { 
    for(typename StringT::iterator it = theString.begin(); 
     it != theString.end(); 
     ++it) 
    { 
     *it = std::toupper(*it, std::locale()); 
    } 
    return theString; 
} 

Vous devez dire aux utilisateurs de cette bibliothèque quelles fonctions et le type qu'ils doivent exposer pour cela à travailler. Le compilateur ne connaîtra pas ce contrat. Au lieu de cela, il lancera juste des messages d'erreur quand il s'agit d'appeler la fonction avec un type qui n'est pas une chaîne. Souvent, vous trouverez des pages de messages d'erreur et il est difficile d'obtenir la vraie raison de ce qui ne va pas. La fonctionnalité proposée Concepts pour la prochaine version de la norme corrige bien.

Si vous avez pas l'intention d'écrire une fonction générique, vous pouvez simplement aller de l'avant et d'écrire une fonction normale comme celui-ci

std::string strUpper(std::string theString) { 
    for(std::string::iterator it = theString.begin(); 
     it != theString.end(); 
     ++it) 
    { 
     *it = std::toupper(*it, std::locale()); 
    } 
    return theString; 
} 

Si vous avez pas l'intention d'inventer cette fonction pour apprendre en premier lieu, mais parce que vous n'avez pas trouvé un autre algorithme déjà écrit, regardez dans la bibliothèque boost string algorithm. Ensuite, vous pouvez écrire

boost::algorithm::to_upper(mystring); 
+0

Passe std :: string par const ref. –

+0

je vais devoir le copier quand même. il est préférable de le prendre en valeur car cela sera plus transparent pour l'appelant et peut être mieux optimisé. –

+0

Si je pouvais optimiser tout ce que je pouvais penser, alors il faut créer l'objet locale localement et toujours le réutiliser. En ce moment, je crée toujours un nouveau temporaire. mais je pense que ce sont des questions de mise en œuvre. le gars va le mettre sur la pile dans son programme. –