Université Mohammed Premier Faculté des Sciences Département de Mathématiques et d’Informatique Année universitaire 2012-2013 Filière : SMI Module : POO Java Semestre : S5 Responsable du cours : El Mostafa DAOUDI Solution TD: Série Numéro 5 Exercice 1 : 1. Définir une méthode, nommée « memeClasse() », pour tester si 2 objets passés en argument appartiennent ou non à la même classe. 2. Redéfinir la méthode « memeClasse() » pour tester si un objet « objO » est de la même classe que l'objet courant ( l’objet qui appelle la méthode « memeClasse() »). Solution : class TestObjet { // question 1 public static boolean memeClasse(Object o1, Object o2) { if ((o1 != null && o2 != null) && (o1.getClass() == o2.getClass())){ return true; } else return false; } // question 2 public boolean memeClasse(Object o) { if ((o != null) && (o.getClass() == this.getClass())){ return true; } else return false; } } /* Pour les tests, on suppose qu’on a trois classes ClassA, ClassB et ClassC, puis on compare des instances de ces trois classes */ public class TestMemeClass { public static void main(String[] args) { Object objA = new ClassA(); Object objB = new ClassB(); Object objC = new ClassC(); Object objAA = new ClassA(); boolean b1 = TestObjet.memeClasse(objA, objB); // b1=false boolean b2 = TestObjet.memeClasse(objA, objAA); // b2=true boolean b3 = TestObjet.memeClasse(objB, objC); // b3=false System.out.println("b1= "+b1+" b2= "+b2+" b3= "+b3); } } Exercice 2 : SMI – S5 Solution du TD-5 POO - Java, 2012-2013 1 Ecrire une classe qui a deux méthodes: - Une méthode qui prend en paramètre une chaine « s » de type String et un caractère « ch » et qui retourne le nombre de caractères « ch » présents dans la chaine « s » en utilisant la méthode indexOf(). - La méthode main() dans laquelle on récupère les paramètres « s » et « ch » sur la ligne de commande. - Réécrire la méthode main() dans afin que les paramètres soient lus au clavier. Solution1: /* Dans cette solution, on suppose que la chaîne « s » à traiter et le caractère « ch » à chercher dans la chaine « s », sont obtenus sur la ligne de commande. */ import java.io.*; public class TestIndexOf { public static int nbCaracteres(String s, char ch) { int cp=0; int n; while((n=s.indexOf(ch))!=-1) { cp++; s=s.substring (n+1); } return cp; } public static void main(String[] args) throws IOException { try { String s = args[0]; char ch= args[1].charAt(0); int cp = nbCaracteres(s, ch); System.out.println("cp= "+cp ); } catch (ArrayIndexOutOfBoundsException exc) { System.out.println("Nombre d'arguments doit être égal à 2"); } } } Solution2 /*Dans cette solution, on suppose que la chaîne « s » à traiter et le caractère «ch» à chercher dans la chaine « s », sont lus au clavier (on peut aussi utiliser la classe «Scanner»). */ import java.io.*; public class TestIndexOf { public static int nbCaracteres(String s, char ch) { int cp=0; int n; while((n=s.indexOf(ch))!=-1) { cp++; s=s.substring (n+1); } return cp; } public static void main(String[] args) throws IOException { InputStreamReader in = null; BufferedReader tampon = null; try { /* ouverture du flux de caractères : la source de données à connecter au flux est le clavier représenté par le nom de fichier logique « System.in » */ in = new InputStreamReader(System.in); // Connecte le flux avec le tampon tampon = new BufferedReader(in); /* Remarque : les deux instructions peuvent être écrites en une seule instruction SMI – S5 Solution du TD-5 POO - Java, 2012-2013 2 BufferedReader tampon = new BufferedReader(new InputStreamReader(System.in)); */ System.out.print("Entrez Une chaine:"); String s = tampon.readLine(); System.out.print("Entrez un caractère :"); int n = tampon.read(); char ch=(char)n; int cp = nbCaracteres(s, ch); System.out.println("cp= "+cp ); // affiche n=3 } catch (IOException ioe) { System.out.print("Erreure de lecture au clavier :"); //System.err.println(ioe); } finally { try { tampon.close(); in.close(); } catch (IOException exception1) { System.out.print("Erreure de fermeture des flux :"); exception1.printStackTrace(); } } } } Exercice 3: Le but est de définir une classe qui calcule et affiche xn où x est un réel et n étant un entier strictement positif. 1. Dans ce premier cas, on ne se préoccupe pas des cas d'erreurs qui peuvent se produire. Ecrire une classe nommée CalcPuissance qui a deux méthodes: - Une méthode non récursive nommée « puiss()» qui prend « x » et « n » en paramètres et qui retourne xn. - Une méthode récursive nommée « puissIter()» qui prend « x » et « n » en paramètres et qui retourne xn. - La méthode main(). Pour les tests, on suppose que x et n sont fournis en ligne de commande. 2. Dans le deuxième cas on s’intéresse aux erreurs qui peuvent se produire, en particulier: - Si le nombre d’arguments est < 2, le programme affiche le message suivant : « Le nombre d’arguments est <2 : Donner sur la ligne de commande un réel suivi d’un entier». - Si les arguments fournis ne correspondent pas à un double suivi d’un entier (puissance), le programme affiche le message suivant : «Mauvais format des arguments : Donner sur la ligne de commande un réel suivi d’un entier ». - Si n est négatif, le programme affiche le message suivant : «La puissance n doit être un entier strictement positif ». - Si la puissance n est trop grande (le résultat retourné est erroné), le programme affiche le message suivant : « La puissance n est trop grande » Solution Question 1 public class CalcPuissance { public static double puiss(double x, int n){ if (n==1) return x; else { return x*puiss(x, n-1); } } public static double puissIter(double x, int n){ SMI – S5 Solution du TD-5 POO - Java, 2012-2013 3 double p=1; for(int i=1;i<=n;i++) p=p*x; return p; } public static void main(String[] args) { double x=Double.parseDouble(args[0]); int n=Integer.parseInt(args[1]); double r=puiss(x,n); System.out.println("r recurssive = "+r); double ri=puissIter(x,n); System.out.println("r itératif = "+ri); } } Question 2 : class ExceptionNegatif extends Exception {} class ExceptionGrand extends Exception {} public class Exercice2 { public static double puiss(double x, int n)throws ExceptionNegatif, ExceptionGrand { if (n<0) throw new ExceptionNegatif(); if (n==1) return x; else { double r1=puiss(x, n-1); double r=x*r1; if (r/r1!=x) throw new ExceptionGrand(); return x*puissExcp(x, n-1); } } public static double puissIter(double x, int n)throws ExceptionNegatif, ExceptionGrand { if (n<0) throw new ExceptionNegatif(); double p=1, p1=1; for(int i=1;i<=n;i++){ p=p*x; if (p/p1!=x) throw new ExceptionGrand(); p1=p; } return p; } public static void main(String[] args) { try { double x=Double.parseDouble(args[0]); int n=Integer.parseInt(args[1]); double r=puiss(x,n); System.out.println("puissance recurssive = "+r); double ri=puissIter(x,n); System.out.println("la puissance itérative = "+ri); } catch(ArrayIndexOutOfBoundsException exc){ System.out.println("Nb arguments est <2: Donner un réel suivi d’un entier. "); } catch (NumberFormatException e){ System.out.println(" Mauvais format: Donner un réel suivi d’un entier "); } SMI – S5 Solution du TD-5 POO - Java, 2012-2013 4 catch (ExceptionNegatif e){ System.out.println(" La puissance n doit être un entier strictement positif "); } catch (ExceptionGrand e){ System.out.println(" La puissance n est trop grande "); } } } Exercice 4 : Ecrie une classe nommée « Copie » tel que si la commande > java Copie fichier1 fichier2 Copie le fichier « fichier1 » dans « fichier2 ». Solution 1 : /* En utilisant les flux d’Octets */ import java.io.*; public class TestEntreeSortie { public static void main(String[] args) throws IOException { FileInputStream in = null; FileOutputStream out = null; try { String fich1=args[0]; String fich2=args[1]; in = new FileInputStream(fich1); out = new FileOutputStream(fich2); int c; while ((c = in.read()) != -1) out.write(c); } catch (IOException e) { System.out.println("Problème d'ouverture de fichier "); } finally { try { in.close(); out.close(); } catch(IOException e){ System.out.println("Problème de fermeture de fichier "); } } } } Solution 2 : /* En utilisant les flux à tampon d’Octets */ import java.io.*; public class TestEntreeSortie { public static void main(String[] args) throws IOException { FileInputStream in = null; FileOutputStream out = null; BufferedInputStream tamponIn = null; BufferedOutputStream tamponOut=null; try { SMI – S5 Solution du TD-5 POO - Java, 2012-2013 5 String fich1=args[0]; String fich2=args[1]; in = new FileInputStream(fich1); tamponIn = new BufferedInputStream(in); out = new FileOutputStream(fich2); tamponOut = new BufferedOutputStream(out); int c; while ((c = tamponIn.read()) != -1) tamponOut.write(c); } catch (IOException e) { System.out.println("Problème d'ouverture de fichier "); } finally { try { tamponIn.close(); tamponOut.close(); in.close(); out.close(); } catch(IOException e){ System.out.println("Problème de fermeture de fichier "); } } } } Exercice 5: Le but de cet exercice est de définir des classes qui peuvent intervenir dans la gestion des filières. 1. Définir une classe nommée « Etudiant » pour modéliser un étudiant. Elle possède : - Au moins quatre attributs privés, en cas de besoin vous rajoutez d’autres attributs, à savoir: nom : de type String pour mémoriser le nom de l’étudiant. niveau : de type int pour mémoriser le niveau d’inscription. On suppose que l’inscription est annuelle, dans ce cas, l’attribut niveau pend les valeurs 1, 2 ou 3. moy: de type float pour mémoriser la moyenne des notes de l’étudiant par niveau d’inscription. - un constructeur pour créer et initialiser les attributs d’un objet de type « Etudiant ». On suppose que la moyenne n’est pas initialisée pendant la création de l’objet. - une methode setNotes() : pour mettre à jour la moyenne des notes. 2. On suppose que la filière a 3 niveaux. Un étudiant ne peut s’inscrire que dans un niveau. Définir une classe nommée « Filière » pour modéliser une filière. Cette classe possède : - Au moins deux attributs privés, en cas de besoin vous rajoutez d’autres attributs, à savoir nom : de type String pour mémoriser le nom de la filière. listEtudiants : de type tableau d’Etudiant pour mémoriser tous les étudiants inscrits dans une filière. - un constructeur pour créer et initialiser les attributs d’un objet de type « Filiere ». On suppose que l’inscription des étudiants ne se fait pas pendant la création de la filière. - une methode ajouteEtudiant() : pour ajouter (inscrire) un étudiant dans la filière. Lorsque le tableau mémorisant les étudiants inscrits dans une filière est plein et que l'on veut encore rajouter des étudiants, on pourra alors agrandir le tableau d'une quantité égale à la taille du tableau courant (dans ce cas la capacité du tableau sera doublée par rapport à la taille courante). - Une méthode trie() : pour trier les étudiants par niveau. SMI – S5 Solution du TD-5 POO - Java, 2012-2013 6 - Une méthode setMoyenne() : pour faire la saisie des moyennes par niveau. Une méthode deliberaton() : pour faire les délibérations par niveau. Un étudiant est considéré « admis » si la moyenne est 10, sinon il est « ajourné ». - Une méthode afficheResultat(): affiche, par niveau, le nom, la moyenne et le résultat des étudiants. 3. Définir une classe nommée « TestFiliere » qui contient la méthode main(). Pour les tests : - On inscrits 6 étudiants dans une filière. Tous les étudiants n’ont pas tous le même niveau. - On fait la saisie des notes, par niveau. - On fait les délibérations par niveau. - On affiche les résultats par niveau N.B. - Pour la lecture au clavier, on utilise la classe Clavier.java de la manière suivante : int n = Clavier.lireInt() ; // pour saisir un entier. float x = Clavier.lireFloat() ; // pour saisir réel simple précision. String s = Clavier.lireString() ; // pour saisir une chaine de caractères. Solution: class Etudiant { private String nom; private float moy; private String resultat="Ajournée"; private int niveau; // niveau 1, 2 ou 3 public Etudiant(String nom, int niveau){ // constructeur this.nom=nom; this.niveau=niveau; } public void setMoy(float moy){ this.moy=moy; } public float getMoy(){ return moy; } public void setResultat(String resultat) { this.resultat=resultat; } public int getNiveau(){ return niveau; } public String getNom(){ return nom; } public String toString(){ return nom+": "+moy+": "+resultat; } } class Filiere { private String nom // nom de la filière private Etudiant listEtudiants []; // contient les étudiants private int nbe=0; // nombre d’étudiants public int nb1, nb2, nb3; //nombre d’étudiants par niveau public Filiere(String nom, int n){ // constructeur de la filière. n étant le nombre prévu d’étudiants this.nom=nom; listEtudiants = new Etudiant [n]; } SMI – S5 Solution du TD-5 POO - Java, 2012-2013 7 public void ajoutEtudiant(String nom, int niveau){ int l=listEtudiants.length; if (nbe<listEtudiants.length){ // il reste encore de la place dans le tableau listEtudiants[nbe]=new Etudiant(nom, niveau); } else { Etudiant [] tab= new Etudiant [2*l]; /* création d’un nouveau tableau de taille plus grande (2 fois la taille actuelle du tableau contenant les étudiants */ System.arraycopy(listEtudiants, 0, tab, 0, l); listEtudiants=tab; listEtudiants[nbe]=new Etudiant(nom,niveau); //ajout du nouveau étudiant } nbe++; if(niveau==1) nb1++; // mettre à jour le nombre d’étudiants pour le niveau 1 else if(niveau==2) nb2++; // mettre à jour le nombre d’étudiants pour le niveau 2 else nb3++; // mettre à jour le nombre d’étudiants pour le niveau 3 } public void trie(){ Etudiant listeTrie [] = new Etudiant[nbe]; int j1=0, j2=nb1, j3=nb1+nb2; for(int i=0;i<nbe;i++){ if (listEtudiants[i].getNiveau()==1){ // On peut utiliser switch listeTrie[j1]= listEtudiants[i]; j1++; } if (listEtudiants[i].getNiveau()==2){ listeTrie[j2]= listEtudiants[i]; j2++; } if (listEtudiants[i].getNiveau()==3){ listeTrie[j3]= listEtudiants[i]; j3++; } } listEtudiants = listeTrie; } public void deliberation(int niveau){ // délibertion par niveau int debut=0, fin=0; // le début et la fin dans le liste d’étudiants pour un niveau donné if (niveau==1){ debut=0; fin=nb1-1; } if (niveau==2){ debut=nb1; fin=nb1+nb2-1; } if (niveau==3){ debut=nb1+nb2; fin=nbe-1; } SMI – S5 Solution du TD-5 POO - Java, 2012-2013 8 for(int i=debut;i<=fin;i++){ if (listEtudiants[i].getMoy()>=10.) listEtudiants[i].setResultat("admis"); } } public void setMoyenne(int niveau){ // Saisie des moyennes par niveau int debut=0, fin=0; // le début et la fin dans le liste d’étudiants pour un niveau donné if (niveau==1){ debut=0; fin=nb1-1; } if (niveau==2){ debut=nb1; fin=nb1+nb2-1; } if (niveau==3){ debut=nb1+nb2; fin=nbe-1; } for(int i=debut;i<= fin;i++){ float moy; System.out.print(listEtudiants[i].getNom()+": Moyenne = "); moy = Clavier.lireFloat() ; listEtudiants[i].setMoy(moy); } } public int getNb1(){ return nb1; } public int getNbe(){ return nbe; } public void afficheResultat(int niveau){ int debut=0, fin=0; // le début et la fin dans le liste d’étudiants pour un niveau donné if (niveau==1){ debut=0; fin=nb1-1; } if (niveau==2){ debut=nb1; fin=nb1+nb2-1; } if (niveau==3){ debut=nb1+nb2; fin=nbe-1; } System.out.print("Niveau : "+niveau); for(int i=debut;i<= fin;i++){ System.out.print(listEtudiants[i]);//appel de toString() } } } SMI – S5 Solution du TD-5 POO - Java, 2012-2013 9 public class GestionFiliere { public static void main(String[] args) { String nomE, nomF; int n; int niveau; System.out.print("nom de la filière: "); nomF = Clavier.lireString() ;; System.out.print("Entrer la taille initiale : "); n= Clavier.lireInt(); Filiere F=new Filiere(nomF,n); for(int i=0; i<6; i++) { System.out.print("nom de l'Etudiant : "); nomE = Clavier.lireString() ; System.out.print("Entrer le niveau d'inscription : "); niveau= Clavier.lireInt(); F.ajoutEtudiant(nomE,niveau); } F.trie(); for(int i=1; i<=3; i++) { F.setMoyenne(i); } for(int i=1; i<=3; i++) { F.deliberation(i); } for(int i=1; i<=3; i++) { F.afficheResultat(i); } } } SMI – S5 Solution du TD-5 POO - Java, 2012-2013 10