Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Débuter
Débuter Forum d'entraide pour débuter en langage de programmation C++. Avant de poster : cours d'initiation au C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 27/12/2012, 09h59   #1
yamura
Invité de passage
 
Inscription : avril 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : avril 2011
Messages : 56
Points : 1
Points : 1
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 :
memmove (dest+ l_dest, ajout, nb_carac_max - l_dest);
Code :
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);" ?
yamura est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/12/2012, 11h17   #2
backlash
Membre habitué
 
Inscription : mars 2010
Messages : 114
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 114
Points : 119
Points : 119
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.
backlash est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/12/2012, 11h19   #3
Flob91
Membre expérimenté
 
Avatar de Flob91
 
Florent
Ingénieur
Inscription : mai 2005
Messages : 791
Détails du profil
Informations personnelles :
Nom : Florent
Âge : 29
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Ingénieur
Secteur : Industrie

Informations forums :
Inscription : mai 2005
Messages : 791
Points : 548
Points : 548
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é.
Flob91 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/12/2012, 11h25   #4
yamura
Invité de passage
 
Inscription : avril 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : avril 2011
Messages : 56
Points : 1
Points : 1
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
yamura est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/12/2012, 11h44   #5
yamura
Invité de passage
 
Inscription : avril 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : avril 2011
Messages : 56
Points : 1
Points : 1
Dernière question ^^

Quel est l'intérêt du return dans cette fonction ?
yamura est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/12/2012, 11h53   #6
Flob91
Membre expérimenté
 
Avatar de Flob91
 
Florent
Ingénieur
Inscription : mai 2005
Messages : 791
Détails du profil
Informations personnelles :
Nom : Florent
Âge : 29
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Ingénieur
Secteur : Industrie

Informations forums :
Inscription : mai 2005
Messages : 791
Points : 548
Points : 548
Cela permet de retourner le pointeur de la chaine de caractères résultant de la concaténation
Flob91 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/12/2012, 12h09   #7
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 665
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 665
Points : 4 420
Points : 4 420
Juste par curiosité: c'est un cours de C ou un cours de C++?
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/12/2012, 09h11   #8
leternel
Membre Expert
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 175
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

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

Informations forums :
Inscription : juin 2007
Messages : 1 175
Points : 2 476
Points : 2 476
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.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 28/12/2012, 11h19   #9
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 665
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 665
Points : 4 420
Points : 4 420
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
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 19h28   #10
yamura
Invité de passage
 
Inscription : avril 2011
Messages : 56
Détails du profil
Informations forums :
Inscription : avril 2011
Messages : 56
Points : 1
Points : 1
Citation:
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 :
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 :
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 :
concat_string(tab1,tab2)= concat_string(tab1,tab2)+ tab1;
Que pensez-vous de ma réponse ?
Code :
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 +.
*/
yamura est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 23h35   #11
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 602
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 602
Points : 13 220
Points : 13 220
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 30/12/2012, 17h22   #12
JolyLoic
Rédacteur/Modérateur
 
Avatar de JolyLoic
 
Homme Loïc Joly
Développeur informatique
Inscription : août 2004
Messages : 4 669
Détails du profil
Informations personnelles :
Nom : Homme Loïc Joly
Âge : 38
Localisation : France

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

Informations forums :
Inscription : août 2004
Messages : 4 669
Points : 9 860
Points : 9 860
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.
JolyLoic est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 12h14.


 
 
 
 
Partenaires

Hébergement Web