IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

std::replace probléme de template


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 389
    Par défaut std::replace probléme de template
    Bonjour a tous,

    j'ai quelque problème avec la fonctions replace de la STL (algorithm.h).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    map<string,TrVariable>::iterator pos;
    for(pos=mMapOfVariable.begin();pos!=mMapOfVariable.end();++pos)
    {
    	string key=pos->first;
    	TrVariable var=pos->second;
    	string varContent=var.valueToString();
    	replace (formula.begin(), formula.end(), key,varContent);
    }
    Donc ici, je parcour une std::map et je cherche a remplacer des occurrences dans une std::string formula.

    Comme vous pouvez le voir key et varContent sont tout deux des string.
    Malheureusement, lors de la compilation j'obtiens des erreurs de ce type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    c:\Program Files\Visual Basic Express\VC\include\algorithm(898) : error C2784: 'bool std::operator ==(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'char'
            c:\Program Files\Visual Basic Express\VC\include\xtree(1453) : see declaration of 'std::operator =='
            c:\Program Files\Visual Basic Express\VC\include\algorithm(907) : see reference to function template instantiation 'void std::_Replace<char*,_Ty>(_FwdIt,_FwdIt,const _Ty &,const _Ty &)' being compiled
            with
            [
                _Ty=std::string,
                _FwdIt=char *
            ]
            .\TrJsParser.cpp(34) : see reference to function template instantiation 'void std::replace<std::_String_iterator<_Elem,_Traits,_Alloc>,std::string>(_FwdIt,_FwdIt,const _Ty &,const _Ty &)' being compiled
            with
            [
                _Elem=char,
                _Traits=std::char_traits<char>,
                _Alloc=std::allocator<char>,
                _FwdIt=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>>,
                _Ty=std::string
            ]
    Il me dit qu'il n'arrive pas a déterminé le template.....
    Donc avez vous une idée de la source du problème ?

    Je vous remercie d'avance pour vos lumières

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Bonjour,

    Les algorithmes de l'entête <algotithm> travaille sur des "ranges", ie des parties de conteneur. Ils manipulent ces parties comme des ensembles d'élément d'un certain type, celui contenu par le conteneur. L'agorithme replace remplace dans le range l'ensemble des éléments qui ont une valeur donnée par une autre valeur.

    Dans ton cas tu l'appliques sur un std::string, qui est bien un conteneur, mais un conteneur de char. Cet algorithme va donc rechercher tout les caractères équalent à une valeur et les remplacer par une autre. Ce n'est pas ce que tu veux.

    Il y a un algorithme replace en fonction membre de std::string, mais il remplace une sous-chaine dont on connait la position. En couplant avec l'algorithme std::search tu dois pouvoir faire ce que tu veux (et un boucle aussi). C'est une première solution, mais elle me semble sous-optimale.

    Si tu peux te permettre des bibliothèques externes :


    Si tu veux le recoder, une piste qui me semble viable est std::generate avec un foncteur bien choisi. Cependant il me semble que ce genre d'algorithme est sujet à des optimisations plus ou moins importantes. Je ne connais pas trop la littérature sur l'algorithmique, mais il me semble que la référence est la série de livres de Donald Knuth.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour

    Si tu utilises formula.begin(), tu obtiens un iterateur pour parcourir formula qui est un string. Donc c'est un itérateur sur un char. L'algo replace attend donc un char à chercher et un char pour le remplacement. Toi tu donnes des string, ça passe pas

    En fait, ce que tu souhaites faire n'est pas si évident que ça. Imagine que tu souhaites remplacer une clé qui fait 3 caractères par une chaîne qui en fait 10. Il faudrait faire : reallocation de la chaîne avec la nouvelle taille, copier la premier partie de la chaîne dans la nouvelle, copier l'élément à remplacer, copier le reste de la chaîne

    Le plus simple (mais non optimisé) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    string replace(string const& src, string const& key, string const& value) {
        string result;
        auto first = search(begin(src), end(src), begin(key), end(key)); // on cherche la clé
        if (first == end(src)) { 
            result = src; // clé non trouvée
        } else {
            result = string(begin(src), first) + value + string(first+key.size(), end(src)); // trouvé
        }
        return result;
    }
    Sinon, le mieux est probablement d'utiliser les expressions régulières

  4. #4
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 389
    Par défaut
    Merci pour ces explications.
    En faisant un tour sur le net j'ai trouver cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    	size_t start_pos = 0;
    	while((start_pos = str.find(from, start_pos)) != std::string::npos) {
    		str.replace(start_pos, from.length(), to);
    		start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    	}
    }
    Elle fait ce que l'on lui demande mais n'est pas optimal a mon avis.

    Pour la regex je ne vois pas trop comment faire un replaceAll
    Ceci fonctionne t'il ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tr1::regex e (key);
    formula=tr1::regex_replace(formula,e,varContent);
    EDIT: en faite aucune des deux méthodes ne fonctionne....
    Voici un exemple:

    je veux remplacer
    AREMPLACER--> 10
    AREMPLACER2-->555
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    var a=AREMPLACER;
    var b= AREMPLACER2;
    if(b == AREMPLACER)
    .....
    devrais donner
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    var a=10;
    var b= 555;
    if(b == 10)
    .....
    malheureusement actuellement j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    var a=10;
    var b= 102; <-- fail
    if(b == 10)
    .....
    Une idée de comment je peux résoudre ceci ?

    EDIT: résolu, je parcours ma map<string,obj> a l'envers et ainsi plus de problème. je traite les plus grosses chaines en premier.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [xslt][Javascript] Problème de templates
    Par Dnallabar dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 03/11/2005, 11h55
  2. problème classes templates...
    Par youp_db dans le forum C++
    Réponses: 3
    Dernier message: 02/11/2005, 13h04
  3. Réponses: 3
    Dernier message: 22/03/2005, 09h13
  4. STL : std::set problème avec insert ...
    Par Big K. dans le forum MFC
    Réponses: 13
    Dernier message: 08/11/2003, 01h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo