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 :

Erreur sémantique lors de la concaténation de deux chaines de caractères


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut Erreur sémantique lors de la concaténation de deux chaines de caractères
    Bonjour à tous,

    J'ai pour les cours à expliquer le fonctionnement d'un bout de code, j'en comprend bien le sens mais j'ai une erreur alors que je ne devrais pas en avoir.

    La ligne qui fait planter le programme est la ligne, je ne comprends pas pourquoi :/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memmove (dest+ l_dest, ajout, nb_carac_max - l_dest);
    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
     
    int main()
    {
        char tab1[10] = "Coucou, ";
        char tab2[40] = "tu veux voir ma paire de lunette ?";
    // On créé deux tableau et l'on va concaténer le premier au second.
        concat(tab1,tab2,70);
        cout<< tab1;
    // On affiche la concaténation du tableau 1
        return(0);
    }
     
    /*Fonction cacaténer
    Elle permet de concaténer une chaîne de caractère 2 à une chaine de caractère 1 afin d'obtenir un seul tableau.
    */
     
    char* concat(char *dest, const char *ajout, int nb_carac_max)
    {
        int l_dest= strlen(dest);
        int l_ajout= strlen(ajout);
     
        if( nb_carac_max <= 0 || nb_carac_max > l_dest + l_ajout)
        {
            nb_carac_max= l_dest+ l_ajout;
        }
     
        if( nb_carac_max > l_dest)
        {
            memmove (dest+ l_dest, ajout, nb_carac_max - l_dest);
        }
        dest[nb_carac_max] = '\0';
        return dest;
    }
    Questions :
    Pour le prof écrit "return dest;" et non pas "return (dest);" ?
    Dernière modification par gbdivers ; 27/12/2012 à 10h44.

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Points : 158
    Points
    158
    Par défaut
    Ton tableau tab1 n'a pas une taille suffisante pour la concaténation, utiliser memmove dans un tel cas ne peut que conduire à des Undefined Behavior.

  3. #3
    Membre confirmé Avatar de Flow_75
    Femme Profil pro
    Ingénieure
    Inscrit en
    Mai 2005
    Messages
    1 096
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieure
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 096
    Points : 633
    Points
    633
    Par défaut
    Salut,

    Le probleme du plantage est que ton tableau de destination n'est alloué que pour 10 caractères.

    Ensuite, le

    est exactement pareil que :

    Juste que ca enleve toute ambigüité.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Super
    Merci beaucoup, je me disais que cela provenait de la taille du tableau, mais je pensais naïvement que celui-ci s'agrandissait automatiquement ^^
    Résolu

  5. #5
    Invité
    Invité(e)
    Par défaut
    Dernière question ^^

    Quel est l'intérêt du return dans cette fonction ?

  6. #6
    Membre confirmé Avatar de Flow_75
    Femme Profil pro
    Ingénieure
    Inscrit en
    Mai 2005
    Messages
    1 096
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieure
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 096
    Points : 633
    Points
    633
    Par défaut
    Cela permet de retourner le pointeur de la chaine de caractères résultant de la concaténation

  7. #7
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Juste par curiosité: c'est un cours de C ou un cours de C++?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Comme d'habitude, du "C avec iostream"…

    Ce que je déteste les profs qui agissent ainsi.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    J'ose espérer que le but de ce cours avec des char[] et des char* est de, par la suite, montrer les avantages des std::string
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  10. #10
    Invité
    Invité(e)
    Par défaut
    J'ose espérer que le but de ce cours avec des char[] et des char* est de, par la suite, montrer les avantages des std::string
    Et tu as tout à fait raison mon ami, le prof nous a demandé ensuite de le comparer avec une fonction identique mais totalement en C++ (utilisation de .size(), du type string, de la concaténation directe de deux chaines de caractère en string).

    Autres questions donc, en comparer le code initial en C

    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
    char* concat(char *dest, const char *ajout, int nb_carac_max)
    {
        int l_dest= strlen(dest);
        int l_ajout= strlen(ajout);
     
        if( nb_carac_max <= 0 || nb_carac_max > l_dest + l_ajout)
        {
            nb_carac_max= l_dest+ l_ajout;
        }
     
        if( nb_carac_max > l_dest)
        {
            memmove (dest+ l_dest, ajout, nb_carac_max - l_dest);
        }
        dest[nb_carac_max] = '\0';
        return dest;
    }
    Avec celui en C++

    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
    string& concat_string(string& dest, const string& ajout, int nb_carac_max)
    {
        int l_dest= dest.size(), l_ajout= ajout.size();
     
        if (nb_carac_max <=0 || nb_carac_max > l_dest+ l_ajout)
        {
            dest = dest + ajout;
        }
        else
            if(nb_carac_max> l_dest)
            {
                dest= dest.substr(0,nb_carac_max - l_dest);
            }
            else if( nb_carac_max < l_dest)
            {
                dest = dest.substr(0,nb_carac_max);
            }
        return (dest);
    }
    Il a posé 4 questions :

    1) Quelles sont les différences ?

    2) Pourquoi la version en C++ est-elle plus facilement maintenable ?

    3) Est-ce que l'utilisation de nb_carac_max est toujours justifié ?

    4) Est ce que le code fonctionne et que fait-il ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    concat_string(tab1,tab2)= concat_string(tab1,tab2)+ tab1;
    Que pensez-vous de ma réponse ?
    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
    /* Explications
    1)  Les différences :
        - la récupération de la taille de la chaîne de caractère se fait grâce à .size() alors qu'en C on utilise strlen();
        - la concaténation se fait par dest+ajout au lieu d'utiliser la fonction memmove en C.
        - la fonction permet .substr permet de tronquer la partie d'une chaîne de caractère.
     
    2) C'est la version en c++ qui est la plus facilement utilisable et maintenable car il n'y a pas de contrainte liée à la taille du tableau d'origine
    contrairement à la version en C.
     
    3) Oui l'utilisation de nb_carac_max est toujours justifié, dans le cas ou l'utilisateur entre une valeur négative, elle permet également
    de choisir le nombre de caractère qu'il souhaite récupérer en retour.
     
    4) Oui le code est correcte, on concatène deux chaîne de caractère (tab1 concaténé avec tab2) + tab1 qui est(tab1 concaténé avec tab2).
    Ce qui éguivant à transformer tab1 en tab1 modifié +tab1 modifié.
    Cela est possible car la fonction concat_string renvoit un string, et l'on peut concactèner deux string entre eux avec l'opérateur +.
    */

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    En fait, dans le code C++, il y a les trois quart des lignes (en fait, 18/19 des lignes ) qui ne servent strictement à rien

    Franchement, je me demande quelle sera la prochaine étape du prof
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Le jour où je vois du vrai code C++ écrit ainsi, je demande à son responsable de le réécrire

    Du coup, j'ai du mal pour les réponses à tes questions, j'ai l'impression qu'elles sont à apprécier dans une certain contexte que l'on n'a pas. Je vais donner mon avis, mais qui est 100% subjectif.

    1/ Il y a plein de différences de syntaxe, bien entendu. On évite de devoir parcourir les chaînes pour en calculer la longueur. Il y a une partie de l'algorithme qui ne marche pas : dest.substr(0,nb_carac_max - l_dest); : Si l_dest vaut 1, et nb_carac_max vaut 10, on va récupérer les 9 premiers caractères d'une chaîne qui en contient 1... Ca ne va pas planter, car le C++ est bien fait, mais je ne vois vraiment pas le but..

    2/ Telle qu'écrite, j'ai du mal à dire si elle est plus aisément maintenable, puisque je n'ai aucune idée de ce qu'elle est sensée faire . Le seul avantage que j'y vois c'est que quoi qu'il arrive, elle produira un résultat sans avoir corrompu la mémoire, même si je ne comprends pas la nature de ce résultat. La version C peut corrompre la mémoire si l'utilisateur se plante dans sa gestion de buffers

    3/ Non, absolument pas ! Une fonction de concaténation doit concaténer, et rien d'autre. Si l'utilisateur veut réduire la taille finale après concaténation, qu'il le fasse explicitement. Mais cette réduction ne fait pas partie de la notion de concaténation, et n'a rien à y faire. Le fait qu'elle apparaisse dans la version C est une limite du langage, qui ne permet pas de gérer les chaînes de caractères et oblige son utilisateur à se focaliser sur des détails bas niveau qui viennent perturber la clarté du code.
    Si on a vraiment besoin d'une fonction qui concatène en tronquant, sans utiliser plus de mémoire que nécessaire, alors, pourquoi pas, mais il ne faut pas l'appeler concat.

    4/ Ce code ne fonctionne pas : On modifie plusieurs fois la même variable à l'intérieur d'une même expression (sans qu'il y ait de point de séquence, pour être plus précis), ce qui n'est pas autorisé. C'est comme si on écrivait int a = i++ + i++;
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

Discussions similaires

  1. erreur de concaténation de deux chaines
    Par 3aychoucha dans le forum C++
    Réponses: 5
    Dernier message: 08/09/2011, 11h34
  2. concaténation de deux chaines
    Par mdh12 dans le forum C
    Réponses: 13
    Dernier message: 11/11/2009, 20h25
  3. Erreur kettle lors de la synchronisation de deux tables.
    Par kilrou dans le forum kettle/PDI
    Réponses: 9
    Dernier message: 20/08/2009, 12h30
  4. problème de concaténation de deux chaines
    Par info79 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 25/01/2008, 17h04
  5. comparer deux chaines de caractères
    Par peuf23 dans le forum Langage
    Réponses: 3
    Dernier message: 30/01/2006, 14h31

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