Proposition de Correction TP4 PEROUMALNAÏK M. mail: mperouma@univ-ag.fr web : http://grimaag.univ-ag.fr/~mperouma/ Seconde partie : Pointeurs I] Exercice 6 : Conception : 1] Enoncé A partir du programme principal suivant (voir énoncé ): Ecrivez la fonction int calculelongueur(char* texte) qui doit calculer la longueur de la chaîne passée en paramètre d'entrée. Ce calcul devra se faire à l'aide du pointeur de char «p_lettre» qui se déplacera sur la chaîne en recherchant le caractère de fin de chaîne. 2] Proposition de correction a) Explications Avant toute chose, regardons de plus près l'entête proposée pour la fonction calculelongueur int calculelongueur(char texte[taille]) Selon moi, cette façon d'écrire n'est pas propre, donc, tout au long de ce corrigé, quand il s'agira de travailler sur un tableau, quelque sera son type, j'utiliserai un pointeur vers les données de ce tableau. Je remplaçe donc par l'écriture suivante (équivalente mais à mon sens plus élégante et plus proche de la vérité) int calculelongueur(char* texte)
Dans cet exercice, la chaine de caractères est passée en paramètre de la fonction et nous devons utiliser le pointeur p_lettre pour circuler sur cette chaine. Plus généralement, un pointeur contient une adresse mémoire d'une zone d'un certain type, et incrémenter le pointeur revient à adresser la zone mémoire suivante. Considérons l'exemple suivant : #include<stdio.h> main() char chaine[6]='s','a','l','u','t','\0'; int i; for(i=0;i<6;i++) printf(«%c»,*(chaine+i)); printf(«\n»); Ce code permet d'afficher successivement les cases du tableau de caractère chaine en utilisant uniquement le fait que chaine soit un tableau : une suite de zones mémoire de même type (donc de même taille) juxtaposées. On passe ainsi d'une case à l'autre en incrémentant le pointeur sur ces cases. Nous venons donc de voir comment, à l'aide d'un pointeur, on peut parcourir les cases d'un tableau donné : nous pouvons donc accéder au contenu de chacune de ces cases. Sachant que le caractère de fin de chaîne utilisé par la fonction scanf en utilisant le type «%s» pour la saisie est '\0', nous pouvons déterminer la longueur d'une chaine donnée en la parcourant : tant que nous n'avons pas rencontré ce caractère, la chaîne n'est pas terminée. Nous avons désormais tous les éléments pour remplir le corps de la fonction calculelongueur
b) Code Il y avait plusieurs façons de faire, tant au niveau de la boucle utilisée (for, while, do... while) qu'au niveau de l'utilisation de cette boucle. Dans tous les cas, dans le corps de la fonction, on devait : initialiser le pointeur p_lettre à texte (<=> &texte[0]) utiliser une variable pour déterminer le nombre d'itérations de la boucle avoir comme condition d'arrêt la rencontre avec le caractère '\0' renvoyer le nombre trouvé Voir le fichier TP4_exo4.c => (http://grimaag.univ-ag.fr/~mperouma/telechargements/tp4_exo4.c )
II] Exercice 7 : Conception 1] Enoncé A partir du programme de tri par sélection réalisé au cours des séances précédentes, écrivez un programme de tri dit «non destructif». Il s'agit d'utiliser un tableau de pointeurs de même taille que le tableau à trier, dont les cases pointent vers chacune des cases de ce tableau. Dans un premier temps, modifiez le programme de départ de façon à disposer d'un tel tableau de pointeurs. Ensuite, réalisez le tri par sélection sur le tableau de pointeurs : lorsqu'une permutation sera nécessaire entre deux cases du tableau d'entiers, on prendra soin de ne pas modifier ce tableau mais de permuter les éléments du tableau de pointeurs pointant sur les cases concernées. Ainsi, une fois le tri réalisé, le tableau d'origine n'est pas modifié (d'ou le terme de «non destructif»), mais le tableau de pointeurs est lui trié correctement. 2] Proposition de correction a) Explications Pour réaliser cet exercice, nous allons nous servir comme base de la correction de l'exercice n 1 du TP3 (http://grimaag.univ-ag.fr/~mperouma/telechargements/tp3_exo1.c ) Cependant, le code de la correction étant un peu complexe, nous allons pour les explications utiliser le code suivant (remis par l'un de vos collègues, corrigé et complété):
N 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 34 35 36 37 38 39 40 #include<stdio.h> #define TAILLE 10 main() int tab[taille]; int i,imin,j,temp=0; //Initialiser le tableau printf("saisissez %d entiers :\n",taille); for(i=0;i<taille;i++) printf("[%d]? :",i); scanf("%d",&tab[i]); //Premier affichage for(i=0;i<taille;i++) printf("%d ",tab[i]); //Tri par sélection for(j=0;j<taille 1;j++) imin=j; for(i=j;i<taille;i++) if(tab[i]<tab[imin]) imin=i; temp=tab[imin]; tab[imin]=tab[j]; tab[j]=temp; //Affichage après tri for (i=0;i<taille;i++) printf("%d ",tab[i]);
Tout d'abord, nous allons modifier le programme pour pouvoir avoir le tableau de pointeurs : il faut déclarer ce tableau puis l'initialiser avec les adresses du tableau d'entiers : Déclaration : Insérer à la ligne 6 : int* p_tab[taille]; Initialisation : Insérer à la ligne 18 : for(i=0;i<taille;i++) p_tab[i]=&tab[i]; Ensuite, au lieu de manipuler le tableau d'entier, nous allons effectuer nos manipulations sur le tableau de pointeurs : 1) changer le type de la variable temp pour pouvoir permuter les pointeurs 2) remplacer les références à tab[i] par *(p_tab[i]) sauf pour la permutation, puisqu'ici on modifie l'ordre des pointeurs : remplacer tab[x] par ptab[x]. Il ne reste plus qu'a afficher les tableaux de fin, avec deux boucles, une première pour afficher le tableau d'origine (qui n'a pas été modifié) et une seconde pour afficher les données suivant l'ordre du tableau de pointeur. Affichage : Insérer à la ligne 37 printf(" Tableau originel :\n "); Et à la ligne 40 printf(" Tableau classé :\n "); for (i=0;i<taille;i++) printf("%d ",*(ptab[i])); b) Code Voir le fichier TP4_exo5.c => (http://grimaag.univ-ag.fr/~mperouma/telechargements/tp4_exo5.c )
III] Le mot de la fin Merci à tous pour cette année passée ensemble, désolé encore du retard pris pour les corrections. N'oubliez pas que je reste à votre disposition jusqu'à la veille des examens, n'héstez pas à m'envoyer vos mails ou à passer au bureau. Bon courage pour la suite, Cordialement, PEROUMALNAÏK M. mail : mperouma@univ-ag.fr