IFT2030 -- Travail pratique #3 -- 31/03/06 ALLOCATION DYNAMIQUE AVEC C ET JAVA Marc Feeley
Date de remise: 17 avril ---
Le TP3 a pour but de vous faire pratiquer la programmation impérative et en particulier les concepts suivants:
- les énoncés de contrôle, - l'allocation dynamique, - les pointeurs.
Vous avez à réaliser un programme en C et un programme en Java ainsi que rédiger un rapport qui analyse vos programmes.
--- 1. Programmation
Vous devez réaliser l'application suivante en C et en Java. Dans chaque cas, vous devez exploiter les forces du langage pour exprimer au mieux votre programme (par exemple, en C, utilisez l'arithmétique sur les pointeurs, en Java utilisez les exceptions). Dans le rapport, vous devez expliquer les forces et faiblesses de ces langages pour la réalisation de cette application. Il est fortement suggéré de
commencer par la réalisation du programme Java et de reproduire à peu près la même structure de programme dans la version en C.
1.1 Spécification de l'application
L'application est un gestionnaire de bottin d'adresses postales très simplifié. Lorsque l'application est lancée, la base de donnée d'adresses est vide. À l'aide de commandes entrées au clavier (l'entrée standard du programme), l'usager peut ensuite ajouter une adresse, éliminer une adresse, ou demander l'adresse d'un individu.
L'usager ne doit pas être limité dans le nombre d'adresses qu'il peut entrer dans la base de donnée (la seule limite doit être l'espace mémoire disponible sur la machine). Lorsque l'application termine, la base de donnée n'est PAS sauvegardée.
Une adresse contient:
- le nom de l'individu - le numéro de maison - le nom de la rue - le nom de la ville
Dans ce travail, nous allons supposer que toutes ces informations sont des chaînes de caractères de longueur QUELCONQUE.
Le programme doit afficher l'incitateur "COMMANDE? " à l'écran.
L'usager spécifie alors une commande en entrant une des lettres suivantes après l'incitateur (et rien avant ni après la lettre):
a pour ajouter ou remplacer une adresse de la base de donnée e pour éliminer une adresse de la base de donnée
i pour imprimer l'adresse d'un individu
L'usager peut également entrer une fin de fichier (ctrl-D au clavier) pour terminer l'application.
Lorsqu'une commande "a" est entrée, l'usager doit entrer les
informations sur l'adresse à ajouter sur les 4 prochaines lignes, dans l'ordre indiqué ci-haut. Si l'individu en question existe déjà dans la base de donnée, les nouvelles informations remplacent les
anciennes.
Lorsqu'une commande "e" est entrée, l'usager doit entrer sur la ligne suivante le nom de l'individu qui doit être éliminé. Si l'individu n'existe pas, le programme affiche le message "INDIVIDU INCONNU".
Lorsqu'une commande "i" est entrée, l'usager doit entrer sur la ligne suivante le nom de l'individu recherché. Si l'individu n'existe pas, le programme affiche le message "INDIVIDU INCONNU", sinon les informations sur l'individu sont imprimées sur les 4 prochaines lignes.
Si le format d'entrée n'est pas respecté il faut afficher le message
"ERREUR" et terminer le programme. Il faut également afficher ce message et terminer le programme pour toute erreur, par exemple si la mémoire est épuisée (en Java une exception de type OutOfMemoryError sera lancée, en C la fonction malloc retournera NULL).
Voici un exemple d'utilisation de l'application:
COMMANDE? a Sophie 101 St-Jean Laval COMMANDE? a Bernard 1234 Mercier St-Jean COMMANDE? a Sophie 34 Mercier Verdun COMMANDE? i Julie
INDIVIDU INCONNU COMMANDE? i Sophie Sophie 34 Mercier Verdun COMMANDE? e Sophie COMMANDE? i Sophie
INDIVIDU INCONNU COMMANDE? A ERREUR
Le format d'entrée et de sortie indiqué ici doit être respecté à la lettre car vos programmes seront testés automatiquement et le résultat sera comparé (avec l'utilitaire "diff") avec le résultat produit par notre programme (dont le binaire exécutable est disponible dans
"~dift2030/tp3/modele"). Faites attention tout particulièrement à des blancs superflus que votre programme pourrait imprimer. Lorsque vos programmes seront testés, nous ferons varier artificiellement l'espace mémoire disponible aux programmes. Il est donc tout à fait possible que n'importe quel requête d'allocation mémoire échoue.
Pendant la phase de développement de votre programme C, utilisez le truc suivant pour isoler les problèmes d'allocation mémoire dans votre programme. Insérez au tout début de votre programme une ligne
qui contient:
#include "/u/dift2030/tp3/debug.h"
Ce fichier redéfinit les fonctions de gestion mémoire (malloc et free) de telle façon que certaines erreurs de programmation seront
détectées. N'oubliez pas d'enlever cette ligne lors de la remise de votre programme. Il est important que votre fonction main soit définie ainsi:
int main (int argc, char *argv[]) ...
1.2 Contraintes de programmation
Pour simplifier la programmation et la correction, on vous demande de représenter la base de donnée par une liste d'individus. Cette liste doit être allouée dynamiquement.
Par souci de conservation d'espace mémoire, on vous demande aussi de:
1) Partager autant que possible les chaînes de caractères identiques.
C'est à dire que si deux individus habitent la ville de "St-Jean", il ne devrait y avoir qu'une seule chaîne "St-Jean" allouée en mémoire. Il n'est pas nécessaire non plus d'allouer une chaîne si un individu habite la rue "St-Jean" (ou s'il se nomme "St-Jean"!). Supposez qu'il n'y a pas de partage entre les chaînes "St-Jean" et "Lac St-Jean".
2) Au cours de l'exécution du programme, il faut récupérer l'espace mémoire occupé par les informations qui ne sont plus utilisées dans la base de donnée.
3) Lorsque le programme termine, normalement ou à la suite d'une erreur, il faut récupérer tout l'espace mémoire occupé par la base de donnée.
Dans le programme C, utilisez seulement la fonction getchar pour lire les commandes de l'usager (car la fonction gets est dangereuse, faites
"man gets" pour les détails). Dans le programme Java, vous pouvez utiliser la méthode readLine de la classe java.io.BufferedReader.
Dans le programme C, n'utilisez pas la fonction exit pour terminer l'exécution. Votre programme doit terminer proprement en sortant de la fonction main, qu'il termine normalement ou à la suite d'une erreur.
2. Rapport
Vous devez rédiger un rapport qui:
1) Explique brièvement le fonctionnement général de chaque programme (maximum de 1 page au total).
2) Compare les programmes en expliquant chaque problème de programmation rencontré et comment le problème a été résolu dans chaque langage (de 3 à 5 pages au total). Exemples de problèmes de programmation: comment lire les chaînes de longueur quelconque, comment implanter le partage des chaînes,
comment récupérer l'espace occupé par les chaînes, comment traiter les erreurs.
3) Résume les forces et faiblesses de chaque langage pour la programmation de cette application (maximum de 1/2 page).
4) En un maximum de 1/2 page répondez à la question suivante. Pour implanter le partage de chaînes il aurait été possible d'utiliser une table d'adressage dispersé (hashing) avec liste de collisions externe. C'est-à-dire que chaque élément de la table est
une liste des chaînes qui ont la même valeur de hachage. Pour savoir si une chaîne existe déjà il suffit donc de hacher la chaîne et la chercher dans la liste appropriée de la table.
Cette approche est plus efficace que celle demandée ci-haut mais elle introduit un problème important d'allocation mémoire dans le programme Java. Décrivez ce problème et comment on pourrait faire pour le régler. Si vous ne voyez pas de problème, expliquez l'implantation de votre table de hachage.
3. Évaluation
- Ce travail compte pour 10 points dans la note finale du cours. Vous DEVEZ le faire par groupes de 2 personnes. Indiquez vos noms clairement au tout début de vos programmes.
- Chaque programme sera évalué sur 2.5 points et le rapport sur 5 points.
Un programme qui plante à l'exécution, même dans une situation extrême, se verra attribuer zéro sur 2.5 . Assurez-vous de prévoir toutes les situations d'erreur (en particulier un appel à la fonction malloc de C qui retourne NULL).
- Vous devez remettre votre rapport au démonstrateur au plus tard le 17 avril. Vous avez jusqu'à minuit le même jour pour remettre vos programmes. Vous serez pénalisés de 5 points sur 10 par jour de retard.
- Vous devez remettre vos programmes par remise électronique grâce à la commande suivante:
remise ift2030 tp3 tp3.c tp3.java classe1.java classe2.java Notez que le programme C est contenu dans un seul fichier (qui doit se nommer tp3.c), que chaque classe du programme Java est dans un fichier et que la classe principale qui contient la méthode main doit se nommer tp3.java.