TP


Cliquez ici pour retirer la feuille de style si vous souhaitez imprimer ce document (ou en cas de problème d'affichage).
Notes :
  • Pensez à indenter votre code !! Faites le à la main (utile pour apprendre), à l'aide d'un éditeur qui sait le faire (gvim, emacs), ou encore avec la commande unix indent, mais faites le !
  • N'utilisez pas de navigateur de fichier ! Apprenez à ne vous servir que du terminal.

FUUUuuuu SION!

Écrivez une fonction qui fusionne deux tableaux de double (supposés triés) dans un nouveau tableau (qui doit donc conserver la propriété d'être trié). Attention, les tableaux n'ont pas forcément la même taille. Réfléchissez bien à la signature de la fonction (comment transmettre la taille du nouveau tableau à la fonction appelante ? Que faire en cas d'erreur d'allocation ? Si l'un des tableaux n'est pas trié ? etc.) Que manque-t-il au code de l'hypothétique fonction appelante suivante ?
  1. void fonction(){
  2. int i;
  3. double tab1[3]={1.0,2.0,3.0};
  4. double tab2[3]={1.1,2.1,2.6};
  5. double fusion[];
  6. /* appel de fusion() que nous supposons correct */
  7. for(i=0;i<6;i++)printf("%f",fusion[i]);
  8. printf("\n");
  9. /* que manque t-il ici ? */
  10. }

Miroir mon beau miroir

  1. On veut écrire une fonction qui modifie un tableau d'entier en inversant tous ses éléments. Pour cela on écrit d'abord la fonction swap() qui échange deux entiers passé en paramètres. Faire le code le plus simple et concis possible, puis miroir qui parcours le tableau du début jusqu'au milieu en échangeant chaque élément avec son symétrique par rapport au milieu (le premier avec le dernier, le deuxième avec l'avant dernier, etc.).
  2. Faire la même chose avec un tableau de chaînes de caractères en copiant collant votre code et en modifiant le moins de chose possible.
  3. Maintenant on voudrait que la même fonction fonctionne pour tous les types. Il faut pour cela modifier swap et miroir :
    • elles prennent maintenant des adresses mémoire non typées (void*) pour pouvoir être appellées aussi bien avec des tableaux d'entiers qu'avec des tableaux de doubles par exemple. On ne peut plus alors écrire tab[3] pour acceder à la troisième case du tableau. Il faut à la place utiliser *(tab+3*taille_du_type) (*** voir la note en bas)
    • elles prennent donc séparemment la taille du type (dans un autre paramètre)
    • il faut utiliser la fonction memcpy au lieu de l'affectation (=) dans swap (puisque qu'on ne connait la taille de ce qu'on veut copier que par le paramètre).
    • La variable temporaire doit donc en plus être allouée dynamiquement (et libérée avant le retour de swap).
    Le code suivant doit fonctionner :
    1. #define N 4
    2. int main(void){
    3. int i;
    4.  
    5. int tab1[N] ={1,2,3,4};
    6. char* tab2[N] ={"aa","bb","cc","dd"};
    7. char tab3[N][3] ={"aa","bb","cc","dd"};
    8.  
    9. for(i=0;i<N;i++)printf("%d ",tab1[i]);
    10. printf(" => ");
    11. miroir(tab1,N,sizeof(int));
    12. for(i=0;i<N;i++)printf("%d ",tab1[i]);
    13. printf("\n");
    14.  
    15. for(i=0;i<N;i++)printf("%s ",tab2[i]);
    16. printf(" => ");
    17. miroir(tab2,N,sizeof(char*));
    18. for(i=0;i<N;i++)printf("%s ",tab2[i]);
    19. printf("\n");
    20.  
    21. for(i=0;i<N;i++)printf("%s ",tab3[i]);
    22. printf(" => ");
    23. miroir(tab3,N,sizeof(char)*3);
    24. for(i=0;i<N;i++)printf("%s ",tab3[i]);
    25. printf("\n");
    26.  
    27. return 0;
    28. }

***NOTE

Notez que si vous avez écrit

void * p = ...
...
...p+...

Ca marche mais c'est faux au sens de la spec du C (l'option -pedantic doit vous rajouter un warning). L'artihmetique des pointeurs n'est possible que sur les vrais pointeurs. Le plus simple pour résoudre ce problème est de caster le void* en char* car sizeof(char) = 1 par definition (c'est d'ailleurs ce que fait gcc, c'est pour ca que le code au dessus fonctionne) :

void * p = ...
char * p2 = (char*)p;
...
...p2+...