Changes between Initial Version and Version 1 of 2009/CaoCourseTme2


Ignore:
Timestamp:
Jan 10, 2010, 11:43:07 PM (14 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 2009/CaoCourseTme2

    v1 v1  
     1{{{
     2#!html
     3<h1> TME2 : Langage C: tables de hachage</h1>
     4}}}
     5[[PageOutline]]
     6
     7= Objectif =
     8
     9Ce TME se décompose en deux parties:
     10La première partie porte sur l'analyse d'un programme C existant.
     11Dans la seconde partie vous devrez modifier ce programme pour
     12introduire de nouvelles fonctionnalités.
     13L'objectif est triple :
     14
     15 1. Il doit vous permettre de complêtez l'auto-évaluation de vos connaissances des outils de developpement C que vous avez commencée dans le précédent TME. Si vous ne savez pas répondre directement aux questions posées , vous devez trouver les réponses dans les documentations (man, web), ou auprès de vos camarades.
     16 1. Il introduit de nouveaux outils permettant l'indentation automatique d'un programme source (outil ''indent''), ou l'écriture d'une documentation (outil ''man'').
     17 1. Il présente une structure de données, la table de hachage, très utilisée dans tous les programmes où on a besoin de rechercher un objet par son nom.
     18
     19Il vous offre également un modèle de programme, avec Makefile et man pour vos futurs développements.
     20
     21Vous devez commencer par créer un répertoire ''tme2'' et y copier tous les fichiers se trouvant dans :
     22{{{
     23/users/enseig/encadr/cao/tme2
     24}}}æ
     25 
     26Ce répertoire contient tous les fichiers sources permettant de générer un programme qui utilise
     27une table de hachage pour compter le nombre total de mots
     28d'un fichier texte quelconque, ainsi que le nombre d'occurences de chaque mot.
     29
     30 *  {{{Makefile .......................}}} description du processus de construction de l'exécutable.
     31 *  {{{main.c, main.h .................}}} programme principal source et déclarations.
     32 *  {{{count.c, count.h ...............}}} analyseur lexical et fonctions de comptage et d'affichage du résultat.
     33 *  {{{dico.c, dico.h..................}}} fonctions de gestion de la table de hachage.
     34 *  {{{hash.c, hash.h..................}}} fonction générale de calcul de l'index à partir de la clé de hachage.
     35 *  {{{man1/tool.1 ....................}}} fichier au format man
     36
     37= Principe des tables de hachage =
     38
     39Une table de hachage est une structure de données permettant de représenter des
     40ensembles d'éléments, où chaque élément est un couple
     41de la forme (clé, donnée).  La clé est le plus souvent une chaîne de caractères.
     42La donnée peut être une valeur ou un pointeur sur une structure plus ou moins complexe.
     43Le principal objectif d'une table de hachage est d'accélérer la recherche d'un élément
     44par sa clé.
     45
     46Pour représenter un ensemble de couples (clé, data) la méthode la plus simple
     47consiste à les stocker dans une unique liste chainée.
     48La recherche d'un élément se fait alors par un parcours de la liste,
     49ce qui n'est pas très efficace si le nombre d'éléments est grand.
     50
     51Pour accélérer la recherche, on créé un tableau de listes chainées.
     52On définit ensuite une fonction, que l'on nomme '''fonction de hachage''',
     53qui calcule un index à partir de la clé.
     54Tout élément doit être rangé dans la liste chainée associée à la case du tableau
     55définie par l'index calculé par la fonction de hachage. 
     56
     57[[Image(Diapositive1.jpg, nolink)]]
     58
     59Dans la pratique, il n'est pas possible d'éviter les collisions: deux éléments
     60ayant des clés différentes peuvent avoir le même index de hachage, et seront donc
     61stockés dans la même liste chaînée.
     62Pour que la méthode soit efficace, il faut cependant que les éléments se répartissent
     63aussi uniformément que possible dans les différentes cases du tableau, et qu'il n'y ait
     64qu'un petit nombre d'éléments dans chaque liste chainée. Le nombre de cases du tableau
     65doit donc être du même ordre de grandeur que le nombre total d'éléments à stocker.
     66
     67Il existe plusieurs méthodes de calcul de l'index. La fonction hashindex() contenue
     68dans le fichier hash.c implémente celle proposée par Donald Knuth.
     69
     70La propriété principale d'une table de hachage est que, si la taille de la table
     71est du même ordre de grandeur que le nombre d'éléments, alors le temps de
     72recherche est en O(1), c'est à dire indépendant du nombre d'éléments, même pour
     73un million d'éléments, comme s'il s'agissait d'un simple tableau.
     74
     75= Etape 1 : Questions sur le code fourni =
     76
     77== A) Le Makefile ==
     78
     79Les premières questions portent sur le fichier [attachment:Makefile Makefile]
     80
     81Completez la liste des dépendances pour les cibles : {{{statt, main.o, ... }}}, puis re-écrivez les commandes en utilisant les variables automatiques : {{{$@ $< $^}}} [[BR]]
     82- {{{$@}}} : désigne le fichier cible d'une règle.[[BR]]
     83- {{{$<}}} : désigne le premier fichier de la liste des fichiers source d'une règle.[[BR]]
     84- {{{$^}}} : désigne la liste des fichiers source d'une règle.[[BR]]
     85
     86 * '''QA1''' Pourquoi est-il préférable de regrouper la definition des commandes et paramètres au début du Makefile?
     87 * '''QA2''' A quoi servent les options -p, -g, -Wall, -Werror, -ansi ? (man gcc)
     88 * '''QA3''' Comment demander l'optimisation maximale du compilateur ? (man gcc)
     89 * '''QA4''' L'option -p est présente dans LDFLAGS et CFLAGS, pourquoi n'est-ce pas le cas de -g ? (man gcc)
     90 * '''QA5''' Que fait la regle indent ? quelle est la signification des flags utilisés par le programme indent ? (man indent)
     91
     92== B) Le programme main ==
     93
     94Les questions suivantes portent sur le programme principal  [attachment:main.c main.c] 
     95Ce fichier contient la fonction main() et la fonction getarg() qui effectue l'analyse de la ligne de commande.
     96
     97 * '''QB1''' Expliquez à quoi sert chacun des fichiers inclus au début du fichier ''main.c''
     98 * '''QB2''' A quoi sert le fichier ''main.h'' ? A quoi servent les 2 premières lignes  et la dernière du fichier ''main.h'' Pourquoi inclure {{{stdio.h}}} ici ?
     99 * '''QB3''' Expliquez le fonctionnement de la fonction getopt() ({{{man 3 getopt}}})[[BR]]
     100    Vous ajouterez plus tard dans la fonction getarg() l'option -s qui demande de fournir des statistiques concernant l'utilisation de la tables de hachage.
     101 * '''QB4''' A quoi sert l'appel  ''return'' a la fin de la fonction main() ?
     102 * '''QB5''' A quoi sert l'appel système ''exit'' à la fin de la fonction usage() ?
     103 * '''QB6''' Quels sont les appels systeme utilisés dans ce fichier main.c ? Quelle precaution doit on prendre lors de leur utilisation ?
     104 * '''QB7''' Où sont definies les fonctions standards de la bibliothèque C ?
     105 * '''QB8''' Qu'est-ce qu'un filtre unix ? Que faut-il faire pour transformer ce programme en filtre ?
     106
     107== C) Le dictionnaire ==
     108
     109Le fichier [attachment:dico.c dico.c] rassemble les fonctions d'accès à une table de hachage utilisée comme dictionnaire.
     110 * '''QC1''' Quel est l'encombrement (en nombre d'octets) des structures créées en mémoire par la fonction dico_create(nb_item) , quand nb_item=10 ? Quelle différence y-at-il entre les appels système malloc() et calloc() ?
     111 * '''QC2''' Pourquoi la structure  {{{dico_item_t}}} définie dans le fichier [attachment:dico.h dico.h] a-t-elle un encombrement mémoire variable ? On aurait pu utiliser une structure de donnée de taille fixe en définissant le troisième champs de la structure comme un pointeur sur chaîne de caractères du type {{{char *KEY}}}. Pourquoi n'a-t-on pas utilisé cette technique ?
     112 * '''QC3''' Quelle est la seule fonction capable d'introduire un nouvel item dans le dictionnaire? Quelle est la technique utilisée dans la fonction dico_get() pour créer ce type d'objet de taille variable en mémoire ?
     113 * '''QC4''' Dans la fonction dico_get() comment fait-on pour tester le retour de l'appel système  malloc() ? à quoi celà sert-il ? Pourquoi teste-on la valeur de l'argument ''key'' au début de cette fonction ? Que fait la fonction perror() ?
     114 * '''QC5''' A quoi sert la structure {{{dico_iterator_t}}} définie dans le fichier [attachment:dico.h dico.h] ? Quelle est la signification des trois champs de cette structure ? Que font les fonctions dico_first() et dico_next() ?
     115 * '''QC6''' La fonction hashindex() peut-elle provoquer une erreur de segmentation ? Comment y remèdier proprement ?
     116
     117== D) La fonction de comptage des mots ==
     118
     119Le fichier [attachment:count.c count.c] contient le code de la fonction count(), qui compte le nombre d'occurences des différents mots présents dans le fichier texte analysé. Il contient également la fonction auxiliaire token() qui lit le fichier texte mot par mot,
     120et la fonction result_count() qui affiche les résultats.
     121
     122 * '''QD1''' Le mot clé ''static'' est utilisé de deux manières différentes dans le fichier ''count.c'' (à l'intérieur et à l'extérieur d'une fonction). Précisez sa signification pour chacune des deux utilisations.
     123 * '''QD2''' Dans la fonction token(), pourquoi ne peut-on pas utiliser l'appel système malloc() pour allouer la mémoire correspondant au tableau ''buffer'' ?
     124 * '''QD3''' La fonction token() doit renvoyer un nouveau "token" (mot) du fichier texte analysé, ainsi que le numéro de ligne, chaque fois qu'elle est appelée. Elle utilise les fonctions fgets() et  strtok(). Que font ces deux fonctions ?
     125 * '''QD4''' Pourquoi as-ton mis une étoile devant l'argument ''numero'' de la fonction token() ?
     126 * '''QD5''' La fonction result_count() utilise-t-elle des fonctions d'accès spécifiques pour effectuer le parcours des éléments présents dans la table de hachage ? Quelles sont ces fonctions d'accès et que font-elles ? Dans quel fichier sont-elles définies? Dans quel ordre vont être affichés les élément de la table ?
     127
     128= Etape 2 : Modifications du programme =
     129
     130== A) affichage des numéros de ligne ==
     131
     132Le programme qui vous est fourni affiche, pour chaque mot présent dans le fichier texte analysé,
     133le nombre d'occurences de ce mot. Vous devez modifier le programme de façon à ce qu'il  indique
     134en plus, pour chaque mot, les numéros de toutes les lignes où le mot est présent.
     135
     136Le fichier Makefile est un fichier texte. Si on lance le programme {{{statt}}}  sur le fichier Makefile, on obtient quelque chose comme :
     137{{{
     138$ ./statt Makefile
     139              dico.o : 2 occurences
     140                 des : 3 occurences
     141                   : : 2 occurences
     142               clean : 3 occurences
     143           /dev/null : 2 occurences
     144                  2> : 2 occurences
     145             count.o : 2 occurences
     146                   # : 3 occurences
     147}}}
     148Après modification, il devra afficher:
     149{{{
     150$ ./statt Makefile
     151       
     152              dico.o : 2 occurences lignes: 23  22
     153                 des : 3 occurences lignes: 14   8   2
     154                   : : 2 occurences lignes: 22  19
     155               clean : 3 occurences lignes: 37  34
     156           /dev/null : 2 occurences lignes: 37  34
     157                  2> : 2 occurences lignes: 37  34
     158             count.o : 2 occurences lignes: 20  19
     159                   # : 3 occurences lignes: 14   8   2
     160}}}
     161Pour introduire cette nouvelle fonctionnalité, il faut:
     162 *  Définir un type de liste chainée pour le stockage des numéros de ligne. Cette structure contient deux champs: un pointeur vers l'élément suivant de la liste et un entier représentant le numéro de ligne.
     163 *  Changer la structure dico_item_s afin d'ajouter un champs contenant un pointeur sur la liste chainée contenant les numéros de lignes.
     164 *  Modifier la fonction count() pour ajouter un nouveau numéro de ligne dans la liste chaînée associée à l'item chaque fois que la fonction token() renvoie un mot.
     165 *  Mofifier la fonction result_count() pour parcourir les listes chaînées contenant les numéros de ligne et les afficher.
     166
     167== B) statistiques sur la table de hachage ==
     168
     169Vous donnerez également des statistiques sur l'usage de la table de hachage.
     170Vous fabriquerez pour cela une fonction {{{void dico_info(dico_root_t *)}}} dans le fichier {{{dico.c}}} qui affichera quelque-chose comme:
     171{{{
     172Informations sur la table de routage
     173Taux de remplissage          : 79.21 %
     174Longueur moyenne des listes  : 1.40
     175Longueur maximale des listes : 4
     176}}}
     177
     178== C) création d'un manuel en ligne ==
     179
     180Vous devez enfin écrire la page de manuel pour le programme ''statt''.
     181Le fichier [attachment:tool.1 tool.1] se trouve dans le répertoire man1, et contient une page de manuel
     182générique contenant des commentaires pour expliquer la syntaxe.
     183La structure de cette page est standard, c'est celle utilisée pour les commandes unix.
     184
     185Renommez le fichier ''tool.1'' en ''statt.1'', et modifiez son contenu pour documenter
     186le programme ''statt''.
     187
     188Pour rendre ce manuel utilisable en ligne, ajoutez le répertoire {{{.}}} à la variable d'environnement {{{MANPATH}}}:
     189{{{
     190export MANPATH=.:$MANPATH
     191}}}
     192Il suffit de taper la commande {{{  man statt  }}} dans le répertoire tme2 pour afficher la documentation.
     193
     194= Compte-Rendu =
     195
     196Pour la première partie de ce TME, vous rédigerez un compte-rendu contenant les réponse
     197aux questions posées, en respectant la numérotation.
     198
     199Pour la seconde partie, une démonstration des modifications introduites dans le programme vous
     200sera demandée au début du prochain TME.
     201