Cliquez ici pour retirer la feuille de style si vous souhaitez imprimer ce document (ou en cas de problème d'affichage).
A partir de maintenant,
  • vous compilerez systèmatiquement avec la commande "make"
  • pour chaque exercice, vous creerez un fichier .h regroupant la déclarations des fonctions, des structures et les inclusion de bibliothèques externes
  • ce fichier sera protégé contre l'inclusion multiple à l'aide des instruction pré processeur #ifndef TRUC #define TRUC... #endif (voir cours)
  • vous écrirez sytèmatiquement la fonction main() dans un fichier séparé "test.c".
  • Vous pouvez vous inspirer de ce template de Makefile :
    1. all: test
    2. test: test.o tab.o
    3. gcc $^ -o test
    4. @echo END
    5.  
    6. clean:
    7. rm -f test *.o
    8.  
    9. test.o: test.c
    10. gcc -c -Wall -ansi -pedantic $<
    11.  
    12. %.o: %.c %.h
    13. gcc -c -Wall -ansi -pedantic $<
    14.  
    15.  

Saisie tableau

Faites une fonction qui prend un tableau de n entiers (n n'est pas une constante) et demande à l'utilisateurs de les saisirs afin de remplir le tableau.

affiche tableau

Faites une fonction qui affiche un tableau d'entier

Recherche dichotomique

Ecrire une fonction récursive de recherche dichotomique d'une valeur dans un tableau trié d'entiers de taille n.

Tri d'un tableau d'entier

Ecrire une fonction qui trie un tableau d'entier à l'aide d'une méthode dichotomique recurssive.
  • Ecrivez d'abord une fonction swap qui inverse deux entiers
  • Ecrivez ensuite une fonction move_first qui prend un tableau et positione le premier élément à sa place dans le tableau.
  • Ecrivez une fonction sort_tab qui place tous les élement à leur place, en commencant par le premier element puis en s'appelant recurssivement avec le sous tableau a gauche de la nouvelle place du premier et le sous tableau à droite.

Complexes

  • Ecrire, dans un fichier complex.h, la définition d'un nombre complexe sous la forme d'un type structuré. Déclarer également les prototypes des fonctions suivantes :
    • new_complex qui crée un nombre complexe en prenant les parties réelle et imaginaire comme paramètres;
    • print_complex qui affiche, sur la sortie standard, un nombre complexe de la façon suivante : la partie réelle suivie d'un espace puis de la partie imaginaire;
    • sum qui calcule la somme de deux nombres complexes;
    • conjugate qui calcule le conjugué d'un nombre complexe;
    • norm qui calcule la norme d'un nombre complexe.
  • Implémenter dans un fichier complex.c, les fonctions précédentes. Tester votre code en créant un fichier main.c où seront implémentés des tests. Ne pas oublier de faire un Makefile pour compiler vos sources.

Chaînes de caractères

Rappel : une chaîne de caractères en C est le début d'un tableau de caractères, jusqu'à rencontrer le caractère spécial '\0'. Un tableau de caractères est l'adresse du premier caractère. Les suivants sont rangés de façon contigüe dans la mémoire.

  • Ecrivez une fonction qui prend deux chaînes de caractères et renvoit la plus petite selon l'ordre lexicographique (sans utiliser de fonctions de string.h).

Nous allons maintenant définir un nouveau type MutableString qui sera une structure contenant un tableau de caractères chars de taille MAX, une constante définie par exemple à 255 et contenant les caractères de la chaine (sans '\0'!), plus un entier length donnant le nombre de caractères. Vous allez réécrire quelques fonctions de string.h pour ce nouveau type.

Lisez toutes les questions avant de commencer.

  1. Dans un fichier mutable_string.h définir le type MutableString (rappel : un entier length et un tableau de caractères de taille MAX). Vous ajouterez au fur et à mesure dans ce fichier le prototype des fonctions que vous écrivez dans la suite.
  2. Dans un fichier mutable_string.c écrire une fonction MutableString newString(char * s);. Le paramètre s est une chaîne de caractères au sens du C (avec un '\0' pour délimiter la fin). La fonction:
    • Déclare une MutableString et initialise son champs length à la taille de la chaine s (nombre de caractères sans '\0' - vous pouvez faire une fonction intermédiaire pour calculer cette taille, interdiction d'utiliser strlen. Si vous faites une fonction intermédiaire, celle-ci ne devra pas apparaître dans le .h).
    • Copie la chaîne s dans le tableau (sans utiliser strcpy, car de toutes facons on ne veut pas copier le '\0')
    • Renvoit une copie de la MutableString (pourquoi pas son adresse ?)
    • Testez le code suivant :
      1. #include <stdio.h>
      2. #include "string.h"
      3.  
      4. int main(){
      5. MutableString s;
      6. printf("%p\n",&(s.chars[2]));
      7. s=newString("coucou");
      8. printf("%p\n",&(s.chars[2]));
      9. return 0;
      10. }
      11.  
      Qu'en déduisez vous ?
  3. Ajoutez la procédure void printString(MutableString * s) qui affiche la MutableString sur la sortie standard (pourquoi passe t on la structure pas adresse ? est on obligé ?)
  4. Ajoutez la fonction int append(MutableString * s1, char * s2); qui ajoute s2 à la fin de s1, et qui renvoit le nombre de caractères ajoutés à s1 (pourquoi peut-il être différent de la taille de s2 ?).
  5. Ajoutez une fonction int compareString(MutableString * s1, MutableString * s2); qui renvoie 0 si s1 et s2 sont égales, 1 si s1 est plus grande que s2 et -1 si elle est plus petite.
  6. Pourquoi ces fonctions prennent-elles des pointeurs en paramètre ? est-on obligé ?
  7. Vérifiez que vous avez ajouté le prototype de toutes les fonctions que vous avez écrites dans mutable_string.h. Une fois le fichier .o correctement généré (gcc -Wall -ansi -pedantic *.c -c), le fichier main2.c suivant doit compiler sans warning ni erreur avec la commande gcc -Wall -ansi -pedantic main2.c -c ; gcc main2.o mutable_string.o -o exercice2, et son exécution ne doit produire aucune erreur :
    1. #include <stdio.h>
    2. #include "string.h"
    3.  
    4.  
    5. MutableString procedure(char * s){
    6. return newString(s);
    7. }
    8.  
    9.  
    10. int main(int argc, char ** argv){
    11.  
    12. MutableString s1;
    13. MutableString s2;
    14. MutableString s3;
    15. MutableString s4;
    16.  
    17. s1 = newString("test1");
    18. printString(&s1);
    19. printf("\n");
    20. s1 = procedure("test1");
    21. printString(&s1);
    22. printf("\n");
    23. s2 = procedure("test2");
    24. printString(&s1);
    25. printf(" ");
    26. printString(&s2);
    27. printf("\n");
    28.  
    29. s3=newString("cou");
    30. append(&s3,"cou\n");
    31. printString(&s3);
    32.  
    33. printf("%d\n",compareString(&s1,&s2));
    34. s3=newString("azezty");
    35. s4=newString("azertyuiop");
    36. printf("%d\n",compareString(&s3,&s4));
    37.  
    38. return 0;
    39. }
    40.  
    41.  
  8. Remplacer le tableau static de taille MAX de la structure par un simple pointeur. Modifier newString() pour qu'elle fasse une allocation dynamique (Attention au type du paramètre !!) et append() pour qu'elle utilise realloc en cas de besoin. Ajouter une fonction freeString().