DESS II – 2003/2004 – Solutions
Modalités
- Durée : 3 heures
- Tous les documents sont autorisés.
- Les sources java répondant à chaque exercice, et
seulement les sourcesseront obligatoirement copiés dans le répertoire
examjava0304(
tout en minuscules) créé à la racine de votre compte.
Nota Bene
Sauf mention contraire explicite, les diverses classes à créer seront non publiques (plus
précisément sans modificateur de visibilité devant), non statiques et non abstraites.
Solution de l’ex. 1 Classification par multi listes
Voici une solution possible :
import java.io.*;import java.util.*;
public class ListePersonnesMain {
public static void main(String[] args) { String chaineEntree = "z";
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
ListePersonnes laListe = new ListePersonnes();
System.out.println("Entrez vos nom et age 1 par ligne, ’q’ pour finir");
while (chaineEntree != null) { try {
chaineEntree = in.readLine();
if (chaineEntree == null || chaineEntree.equals("q")) break;
String nom = new String(chaineEntree);
int age = Integer.parseInt(in.readLine());
laListe.ajouter(new Personne(nom, age));
System.out.println("Entrez une nouvelle personne");
} catch (IOException e) {
System.err.println("Erreur d’E/S " + e.getMessage());
1
continue;
} catch (NumberFormatException e ) {
System.err.println("Erreur d’entree d’entier " + e.getMessage());
continue;
} }
System.out.println("Liste " + laListe);
} }
class Personne {
String nom;
int age;
LinkedList liste;
public Personne(String sonNom, int sonAge) { nom = sonNom;
age = sonAge;
liste = null;
} }
class ListePersonnes { LinkedList liste[];
int nbPers;
public ListePersonnes() {
liste = new LinkedList[100];
nbPers = 0;
}
public void ajouter(Personne p) {
Personne dejaLa = renvoyerPers(p.nom);
if (dejaLa != null) {
p.liste = dejaLa.liste;
(p.liste).add(p);
} else {
LinkedList nouvListe = new LinkedList();
liste[nbPers] = nouvListe;
p.liste = nouvListe;
nouvListe.add(p);
nbPers++;
} }
public Personne renvoyerPers(String sonNom) { for (int i = 0; i < nbPers; i++) {
ListIterator it = liste[i].listIterator();
while(it.hasNext()) {
Personne p = (Personne)it.next();
String nomCourant = p.nom;
if (nomCourant.equals(sonNom)) return p;
} }
return null;
}
public String toString() { String resultat = "\n";
for (int i = 0; i < nbPers; i++) {
ListIterator it = liste[i].listIterator();
while(it.hasNext()) {
Personne p = (Personne)it.next();
resultat = resultat + "(" + p.nom + ", " + p.age + ") -> ";
}
resultat = resultat + "null\n";
}
return resultat;
}
}
Solution de l’ex. 2 Calculatrice en notation post-fixée Une solution possible est constituée des classes suivantes :
ClasseCalcPostMain : package calcpostfixee;
import java.io.*;
public class CalcPostMain {
public static void main(String[] args) { String chaineEntree;
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
try {
System.out.println("Entrez vos expressions, 1 par ligne");
while ( (chaineEntree = in.readLine()) != null ) {
CalcPostFixee pile = new CalcPostFixee(chaineEntree, true);
System.out.println("Resultat : " + pile.renvoyerValeur());
System.out.println("Entrez une nouvelle expression");
}
} catch (IOException e) {
System.err.println("Erreur d’E/S " + e.getMessage());
} } }
ClasseCalcPostFixee : package calcpostfixee;
import java.util.*;
public class CalcPostFixee {
static final int EOL = 0; // Fin de ligne ou d’entree static final int VALEUR = 1; // valeur flottante (operande) static final int PUISS = 2; // ^
static final int MULT = 3; // * static final int DIV = 4; // / static final int PLUS = 5; // + static final int MOINS = 6; // -
static final int FIN = 7; // On s’en va PileEnListe pilePostFixee; // pile de calcul
StringTokenizer chaine; // chaine entree au clavier double valeurCourante; // operande courante
int lexemeCourant; // valeur du lexeme courant boolean bavarde;
public CalcPostFixee(String s, boolean estBavarde) { pilePostFixee = new PileEnListe();
chaine = new StringTokenizer(s, "+*-/^q ", true);
bavarde = estBavarde;
}
public double renvoyerValeur() { double resultat = 0;
int lexeme = -1;
try { do {
lexemeCourant = renvoyerLexeme();
calculer();
} while (lexemeCourant != EOL);
Double resultatDouble = (Double)(pilePostFixee.depiler());
resultat = resultatDouble.doubleValue();
} catch (FamineException e) {
System.err.println("Opérande manquante");
return 0;
}
if (pilePostFixee.estVide() == false) System.err.println("Opérateur manquant");
return resultat;
} /*
* Renvoie le prochain lexeme (token) de la chaine entree
*/
private int renvoyerLexeme() {
String chEntree = "";
try {
chEntree = chaine.nextToken();
} catch (NoSuchElementException e) { return EOL;
}
switch(chEntree.charAt(0)) {
case ’ ’ : return renvoyerLexeme();
case ’^’ : return PUISS;
case ’/’ : return DIV;
case ’*’ : return MULT;
case ’+’ : return PLUS;
case ’-’ : return MOINS;
case ’q’ : return FIN;
default : try {
valeurCourante = Double.parseDouble(chEntree);
} catch (NumberFormatException e) {
System.err.println("Erreur d’analyse lexicale");
return EOL;
}
return VALEUR;
} }
private void calculer() throws FamineException { switch(lexemeCourant) {
case EOL : break;
case FIN :
System.out.println("Sortie du programme");
System.exit(0);
case VALEUR :
pilePostFixee.empiler(new Double(valeurCourante));
if (bavarde) {
System.out.println("calculer() empile - Pile : " + pilePostFixee);
System.out.flush();
} break;
default : // Cas d’un operateur opBinaire(lexemeCourant);
} }
private void opBinaire(int operateur) throws FamineException { double resultat = 0;
double membreD = 0, membreG = 0;
Double membreDroitDouble = (Double)(pilePostFixee.depiler());
Double membreGaucheDouble = (Double)(pilePostFixee.depiler());
membreD = membreDroitDouble.doubleValue();
membreG = membreGaucheDouble.doubleValue();
switch(operateur) { case PUISS :
resultat = Math.pow(membreG, membreD);
break;
case PLUS :
resultat = membreG + membreD;
break;
case MOINS :
resultat = membreG - membreD;
break;
case MULT :
resultat = membreG * membreD;
break;
case DIV :
if (membreD != 0)
resultat = membreG / membreD;
else {
System.err.println("Division par zero");
pilePostFixee.empiler(new Double(membreG));
} break;
}
pilePostFixee.empiler(new Double(resultat));
if (bavarde) {
System.out.println("opBinaire() empile - Pile : " + pilePostFixee);
System.out.flush();
} } }
ClasseComportementPile :
package calcpostfixee;
import java.util.*;
public interface ComportementPile { // Teste si la pile est vide
public boolean estVide();
// Empile un element
public void empiler(Object o);
// Depile un element
// genere une exception en cas de pile vide
public Object depiler() throws FamineException;
// Renvoie la hauteur de la pile public int renvoyerHauteur();
// Renvoie le sommet de la pile (sans le depiler) // genere une exception en cas de pile vide
public Object renvoyerSommet() throws FamineException;
}
ClassePileEnListe : package calcpostfixee;
import java.util.*;
public class PileEnListe implements ComportementPile { private NoeudListe sommet;
private int hauteur;
public PileEnListe() { sommet = null;
}
public boolean estVide() { hauteur = 0;
return sommet == null;
}
public int renvoyerHauteur() { return hauteur;
}
public Object renvoyerSommet() throws FamineException { if (estVide())
throw new FamineException("Pile voirSommet()");
return sommet.donnees;
}
public void empiler(Object o) {
sommet = new NoeudListe(o, sommet);
hauteur++;
}
public Object depiler() throws FamineException { if (estVide())
throw new FamineException("Pile depiler()");
hauteur--;
Object donneesDessus = sommet.donnees;
sommet = sommet.suivant;
return donneesDessus;
}
public String toString() { String resultat = "";
for(NoeudListe n = sommet; n != null; n = n.renvoyerSuivant()) resultat = resultat + n.renvoyerDonnees() + " -> ";
resultat = resultat + "null";
return resultat;
}
}// class PileEnListe
ClasseNoeudListe : package calcpostfixee;
import java.util.*;
public class NoeudListe {
protected Object donnees;
protected NoeudListe suivant;
NoeudListe(Object donnees, NoeudListe suivant) { this.donnees = donnees;
this.suivant = suivant;
}
NoeudListe(Object donnees) { this(donnees, null);
}
public Object renvoyerDonnees() { return donnees;
}
public NoeudListe renvoyerSuivant() { return suivant;
}
}// class NoeudListe
ClasseFamineException : package calcpostfixee;
class FamineException extends Exception { public FamineException(String mess) {
super("Famine : " + mess);
} }
ClasseCalcPostFixeeLL : package calcpostfixee;
import java.util.*;
public class CalcPostFixeeLL {
static final int EOL = 0; // Fin de ligne ou d’entree static final int VALEUR = 1; // valeur flottante (operande)
static final int PUISS = 2; // ^ static final int MULT = 3; // * static final int DIV = 4; // / static final int PLUS = 5; // + static final int MOINS = 6; // -
static final int FIN = 7; // On s’en va LinkedList pilePostFixee; // pile de calcul
StringTokenizer chaine; // chaine entree au clavier double valeurCourante; // operande courante
int lexemeCourant; // valeur du lexeme courant boolean bavarde;
public CalcPostFixeeLL(String s, boolean estBavarde) { pilePostFixee = new LinkedList();
chaine = new StringTokenizer(s, "+*-/^q ", true);
bavarde = estBavarde;
}
public double renvoyerValeur() { double resultat = 0;
int lexeme = -1;
try { do {
lexemeCourant = renvoyerLexeme();
calculer();
} while (lexemeCourant != EOL);
Double resultatDouble = (Double)(pilePostFixee.removeFirst());
resultat = resultatDouble.doubleValue();
} catch (NoSuchElementException e) {
System.err.println("Opérande manquante");
return 0;
}
if (pilePostFixee.isEmpty() == false) System.err.println("Opérateur manquant");
return resultat;
} /*
* Renvoie le prochain lexeme (token) de la chaine entree
*/
private int renvoyerLexeme() { String chEntree = "";
try {
chEntree = chaine.nextToken();
} catch (NoSuchElementException e) { return EOL;
}
switch(chEntree.charAt(0)) {
case ’ ’ : return renvoyerLexeme();
case ’^’ : return PUISS;
case ’/’ : return DIV;
case ’*’ : return MULT;
case ’+’ : return PLUS;
case ’-’ : return MOINS;
case ’q’ : return FIN;
default : try {
valeurCourante = Double.parseDouble(chEntree);
} catch (NumberFormatException e) {
System.err.println("Erreur d’analyse lexicale");
return EOL;
}
return VALEUR;
} }
private void calculer() throws NoSuchElementException { switch(lexemeCourant) {
case EOL : break;
case FIN :
System.out.println("Sortie du programme");
System.exit(0);
case VALEUR :
pilePostFixee.addFirst(new Double(valeurCourante));
if (bavarde) {
System.out.println("calculer() empile - Pile : " + pilePostFixee);
System.out.flush();
} break;
default : // Cas d’un operateur opBinaire(lexemeCourant);
break;
} }
private void opBinaire(int operateur) throws NoSuchElementException { double resultat = 0;
double membreD = 0, membreG = 0;
Double membreDroitDouble = (Double)(pilePostFixee.removeFirst());
Double membreGaucheDouble = (Double)(pilePostFixee.removeFirst());
membreD = membreDroitDouble.doubleValue();
membreG = membreGaucheDouble.doubleValue();
switch(operateur) { case PUISS :
resultat = Math.pow(membreG, membreD);
break;
case PLUS :
resultat = membreG + membreD;
break;
case MOINS :
resultat = membreG - membreD;
break;
case MULT :
resultat = membreG * membreD;
break;
case DIV :
if (membreD != 0)
resultat = membreG / membreD;
else {
System.err.println("Division par zero");
pilePostFixee.addFirst(new Double(membreG));
} break;
}
pilePostFixee.addFirst(new Double(resultat));
if (bavarde) {
System.out.println("opBinaire() empile - Pile : " + pilePostFixee);
System.out.flush();
} } }