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

Langage C++ Discussion :

Plantage et fonctionnement aléatoire


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut Plantage et fonctionnement aléatoire
    Bonjour,

    J'ai écris une fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template< typename Functor >
        void preprocess ( string& str , Functor cond )
    qui a pour role d'enlever un caractère prédéfini encapsulé dans l'objet cond de la chaine de caractère str.

    Exemple de fonctionnement attendu si le caractère à enlever est 'c' :

    str = "cccccciiiiiiiiiccccccccccccccooooooccccccccccpppppp"

    après appel à la fonction preprocess str devient :

    str = "iiiiiiiiioooooopppppp"


    Cependant le programme fonctionne mal c'est à dire qu'il n'enlève pas tous les caractères correspondant dans la chaine str, par moment il plante. Le débugger m'indique que la pile d'appel est dans l'état suivante après la réception de SIGSEV :

    #0 77179F40 msvcrt!memmove() (C:\windows\system32\msvcrt.dll??)
    #1 00000000 0x0044a8b5 in std::string::_M_mutate() (????)
    #2 00000000 0x004495b8 in std::string::erase() (????)
    #3 0041CD3F Parser::preprocess<Parser::IsCaracter<(char)99> >(str=@0x22ff0c, cond={<No data fields>})
    #4 00401672 main(argc=1, argv=0x7a1008)


    Mon code est le suivant :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <iostream>
    #include <string>
     
    using namespace std;
     
    namespace Parser
    {
        template< char caracter >
        struct IsCaracter
        {
            bool operator() ( char c ){ return c == caracter; }
        };
     
        template< typename Functor >
        void preprocess ( string& str , Functor cond )
        {
            for ( string :: iterator it = str.begin () ; it != str.end () ; it++ )
                if ( cond ( *it ) )
                    str.erase ( it );
        }
    }
     
    int main(int argc, char *argv[])
    {
        string s;
     
        while ( true )
        {
            getline ( cin , s );
            Parser :: preprocess ( s , Parser :: IsCaracter< 'c' > () );
            cout << s << endl;
        }
     
        return 0;
    }
    Merci d'avance de votre aide.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,

    erase peut invalider les itérateurs. Il ne faut donc pas les garder sur la boucle après l'effacement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            while (it != str.end ())
            {
                if ( cond ( *it ) )
                {
                   it = str.erase ( it );
                }
                else
                {
                   ++it;
                }
            }

    P.S. : même s'il n'y a qu'une ligne, je te conseille de prendre le réflexe de toujours mettre des accolades après un if/for/while. Cela améliore la lecture du code et évite de nombreux bugs. C'est souvent une règle de codage imposée.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    Merci, le code fonctionne.

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par backlash Voir le message
    Bonjour,

    J'ai écris une fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template< typename Functor >
        void preprocess ( string& str , Functor cond )
    qui a pour role d'enlever un caractère prédéfini encapsulé dans l'objet cond de la chaine de caractère str.

    Exemple de fonctionnement attendu si le caractère à enlever est 'c' :

    str = "cccccciiiiiiiiiccccccccccccccooooooccccccccccpppppp"

    après appel à la fonction preprocess str devient :

    str = "iiiiiiiiioooooopppppp"


    Cependant le programme fonctionne mal c'est à dire qu'il n'enlève pas tous les caractères correspondant dans la chaine str, par moment il plante. Le débugger m'indique que la pile d'appel est dans l'état suivante après la réception de SIGSEV :

    #0 77179F40 msvcrt!memmove() (C:\windows\system32\msvcrt.dll??)
    #1 00000000 0x0044a8b5 in std::string::_M_mutate() (????)
    #2 00000000 0x004495b8 in std::string::erase() (????)
    #3 0041CD3F Parser::preprocess<Parser::IsCaracter<(char)99> >(str=@0x22ff0c, cond={<No data fields>})
    #4 00401672 main(argc=1, argv=0x7a1008)


    Mon code est le suivant :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <iostream>
    #include <string>
     
    using namespace std;
     
    namespace Parser
    {
        template< char caracter >
        struct IsCaracter
        {
            bool operator() ( char c ){ return c == caracter; }
        };
     
        template< typename Functor >
        void preprocess ( string& str , Functor cond )
        {
            for ( string :: iterator it = str.begin () ; it != str.end () ; it++ )
                if ( cond ( *it ) )
                    str.erase ( it );
        }
    }
     
    int main(int argc, char *argv[])
    {
        string s;
     
        while ( true )
        {
            getline ( cin , s );
            Parser :: preprocess ( s , Parser :: IsCaracter< 'c' > () );
            cout << s << endl;
        }
     
        return 0;
    }
    Merci d'avance de votre aide.
    Et...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <string>
    #include <algorithm>
    ...
    s.erase(std::remove(s.begin(), s.end(), 'c'), s.end()). 
    ...
    Qui a l'avantage d'avoir été debuggé pour toi par des tas de gens très efficaces

    A propos, on ne fait jamais i++ sur un itérateur : on fait ++i ; la sémantique n'est pas la même, et on s'évite une copie de contenu inutile.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Et...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <string>
    #include <algorithm>
    ...
    s.erase(std::remove(s.begin(), s.end(), 'c'), s.end()). 
    ...
    Qui a l'avantage d'avoir été debuggé pour toi par des tas de gens très efficaces .
    +1. Et avec std::remove_if si le prédicat est un peu plus compliqué que juste une comparaison de caractère.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    En effet

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Pourrais-tu nous dire pourquoi tu as choisi de faire d'IsCharacter un foncteur templatisé plutôt qu'une bête fonction ?

  8. #8
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par oodini Voir le message
    Pourrais-tu nous dire pourquoi tu as choisi de faire d'IsCharacter un foncteur templatisé plutôt qu'une bête fonction ?
    La je peux répondre à sa place : l'appel à la fonction ne sera pas inlinée, et appeler une fonction pour chaque char dans ce contexte, ce n'est pas très efficace
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

Discussions similaires

  1. [Écran] Fonctionnement aléatoire bouton M/A ecran Packard Bell L17CX
    Par lileo dans le forum Périphériques
    Réponses: 19
    Dernier message: 05/04/2012, 17h48
  2. [MYSQL] - fonctionnement aléatoire
    Par ArKam dans le forum Administration système
    Réponses: 12
    Dernier message: 22/09/2011, 10h35
  3. Fonctionnement aléatoire de mon projet
    Par Go'Gaule dans le forum Débuter
    Réponses: 20
    Dernier message: 06/08/2011, 16h38
  4. Fonctionnement aléatoire d'un converter
    Par kense dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 04/06/2010, 11h29
  5. Plantage Xp pro aléatoire
    Par paolito95 dans le forum Sécurité
    Réponses: 26
    Dernier message: 12/08/2006, 20h37

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