TD3 : tableaux avanc´ees, premi`ere classe et chaınes de caract`eres

publicité
TD3 : tableaux avancées, première classe et chaı̂nes
de caractères
1 Les tableaux
1.1 Éléments théoriques
Déclaration des tableaux Pour la déclaration des tableaux, deux notations sont
possibles. La première notation, place une paire de crochet par dimension du tableau juste après un type :
int[] unTableau;
double[][] unTableauBidimensionnel;
La seconde déclaration place la (ou les) paire(s) de crochets après le nom de la
variable liée.
int unTableau[];
double unTableauBidimensionnel[][];
Construction des tableaux La construction se fait en utilisant l’opérateur new
suivi du type de donnée contenues dans le tableau puis de la taille voulue pour
chaque dimensions entre crochets.
unTableau = new int[10];
unTableauBidimensionnel = new double[5][23];
Les tableaux peuvent aussi être construit en plusieurs étapes. Les dimensions
doivent être spécifiées de “la gauche vers la droite”. Chaque “sous tableau” est alors
un tableau de dimension inférieure. L’exemple ci dessous présente la construction
d’un tableau bidimensionnel triangulaire : src/TableauBidim.java
Chaque ligne est expliquée ci dessous :
– Le tableau donnees est déclaré bidimensionnel.
– Le tableau est partiellement construit, seule la première dimension est fixée à
10. tableau[i] est un tableau mono-dimensionnel (dimension 2 − 1) dont la
taille n’est pour l’instant pas fixée.
– La boucle crée un tableau mono-dimensionnel pour chaque tableau[i] dont
la taille vaut [i+1]
– Deux affectations sont ensuite effectuées.
Le tableau obtenu est donc triangulaire composé de 1 élément sur la première ligne,
2 sur la deuxième,. . .
Tableaux contenant des objets Les tableaux peuvent aussi contenir des objets.
La déclaration du tableaux est la même, un type (dans ce cas une classe) suivit du
1
nom du tableau :
String unTableau[];
String unTableauBidimensionnel[][];
La construction du tableau fait appel au mot clé new suivit du nom de la classe
et de (ou des) paire(s) de crochets contenant les dimensions.
unTableau = new String[10];
unTableauBidimensionnel = new String[5][23];
A la suite de la construction du tableau, les éléments contenus doivent être crées
un à un, souvent à l’aide d’une boucle. L’exemple suivant présente la construction
d’un tableau de chaı̂ne de caractères :
String tab[];
tab = new String[10];
for (int i = 0; i < 10; i++) {
tab[i] = new String();
}
Remarque Souvent, la déclaration et la construction du tableau sont faites en
une seule ligne :
int unTableau[] = new int[10];
double unTableauBidimensionnel[][] = new double[5][23]
1.2 Initialisation aléatoire d’une matrice
Écrivez un programme qui initialise une matrice de taille 10 par 5 avec des
valeurs aléatoires comprises entre 0 et 10.
Correction :
import java.util.Random;
public class InitialisationAleatoire {
public static void main(String[] args) {
int[][] matrice = new int[5][10];
Random gen = new Random();
// Remplissage de la matrice
for (int i = 0; i < matrice.length; i++) {
for (int j = 0; j < matrice[0].length; j++) {
matrice[i][j] = gen.nextInt(10);
}
}
// Affichage de la matrice
for (int i = 0; i < matrice.length; i++) {
2
for (int j = 0; j < matrice[0].length; j++) {
System.out.print(matrice[i][j]+" " );
}
System.out.println();
}
}
}
1.3 Somme de matrices
A partir du programme précédent, écrivez un programme qui calcule la somme
de deux matrices remplies aléatoirement.
Correction :
import java.util.Random;
public class SommeMatrices {
public static void main(String[] args) {
int[][] matrice1 = new int[5][10];
int[][] matrice2 = new int[5][10];
int[][] somme = new int[5][10];
Random gen = new Random();
// Remplissage de la matrice
for (int i = 0; i < matrice1.length; i++) {
for (int j = 0; j < matrice1[0].length; j++) {
matrice1[i][j] = gen.nextInt(10);
matrice2[i][j] = gen.nextInt(10);
}
}
// Calcul de la somme
for (int i = 0; i < matrice1.length; i++) {
for (int j = 0; j < matrice1[0].length; j++) {
somme[i][j] = matrice1[i][j] + matrice2[i][j] ;
}
}
// Affichage du resultat
for (int i = 0; i < somme.length; i++) {
for (int j = 0; j < somme[0].length; j++) {
System.out.print(somme[i][j]+" " );
}
System.out.println();
}
3
}
}
1.4 Produit de matrices
Écrivez un programme qui initialise aléatoirement deux matrices, l’une de 5×3 et
l’autre de 3 × 5 éléments. A partir du programme précédent, écrivez un programme
qui calcule le produit des deux matrices.
Correction :
import java.util.Random;
public class ProduitMatrices {
public static void main(String[] args) {
int[][] matrice1 = new int[5][3];
int[][] matrice2 = new int[3][5];
int[][] produit = new int[5][5];
Random gen = new Random();
// Remplissage de la matrice
for (int i = 0; i < matrice1.length; i++) {
for (int j = 0; j < matrice1[0].length; j++) {
matrice1[i][j] = gen.nextInt(10);
matrice2[j][i] = gen.nextInt(10);
}
}
// Calcul du produit
for (int ligne = 0; ligne < matrice1.length ; ligne++) {
for (int colonne = 0; colonne < matrice2[0].length;
colonne++) {
produit[ligne][colonne] = 0 ;
for (int m = 0; m < matrice1[0].length; m++) {
produit[ligne][colonne] = produit[ligne][colonne] +
( matrice1[ligne][m] * matrice2[m][colonne]);
}
}
}
// Affichage du resultat
for (int i = 0; i < produit.length; i++) {
for (int j = 0; j < produit[0].length; j++) {
System.out.print(produit[i][j]+" " );
}
System.out.println();
}
4
}
}
1.5 Classe matrice
Vous allez construire une classe Matrice dont le schéma UML est présenté dans
la figure ci dessous.
Matrice
- données : entier[][]
+ Matrice()
+ Matrice(Matrice uneMatrice)
+ Matrice(entier[][] unTableau)
+ Matrice(entier nbLignes,entier nbColonnes)
+ getNombreLignes() : entier
+ getNombreColonnes() : entier
+ getDonnées(entier ligne,entier colonne) : entier
+ setDonnées(entier ligne, entier colonne, entier uneValeur) :
+ RemplirMatriceAléatoirement() :
+ AfficherMatrice() :
+ CalculSomme(Matrice uneMatrice) : Matrice
+ CalculProduit(Matrice uneMatrice) : Matrice
+ CalculDeterminant() : entier
F IG . 1 – Schéma UML de la classe Matrice
1.5.1
Attributs
La classe matrice a un seul attribut, un tableau bidimensionnel qui contient les
valeurs de la matrice.
1.5.2
Méthodes
Les constructeurs La classe comporte quatre constructeurs :
– le premier constructeur ne reçoit aucun paramètre, il est vide.
– le second constructeur reçoit une matrice en paramètre et en construit une
copie.
– le troisième constructeur reçoit un tableau d’entiers et construit une matrice
à partir des valeurs contenues dans le tableau.
– le quatrième constructeur construit une matrice à partir du nombre de lignes
et du nombre de colonnes passés en paramètre.
5
La méthode d’affichage La méthode AfficherMatrice permet d’afficher le contenu
de la matrice en utilisant System.out.print et System.out.println et de tabulation (\t).
La méthode de remplissage La méthode RemplirMatriceAleatoirement permet de remplir aléatoirement une matrice avec des valeurs comprises entre 0 et 9
(inclus).
Les assesseurs Les attributs sont privés. Les données doivent donc être lues ou
modifiées en passant par des méthodes1 . Deux méthodes permettent de déterminer
les dimensions de la matrice :
– la méthode getNombreLignes renvoie le nombre de lignes contenues dans la
matrice
– de même, la méthode getNombreColonnes renvoie le nombre de colonnes
contenues dans la matrice.
Deux méthodes permettent de lire/écrire les données contenues dans la matrice :
– getValeur renvoie la valeur contenue aux coordonnées passées en arguments
d’appel
– La méthode setValeur permet de placer une valeur dans la matrice (la valeur
et les coordonnées sont passées par les arguments d’appel).
Ces deux méthodes vérifient que les coordonnées sont valides avant d’effectuer une
opération de lecture ou d’écriture.
Méthodes arithmétiques Deux méthodes permettent d’opérer des calculs arithmétiques
sur des matrices. Ces deux méthodes reçoivent une matrice en paramètre et renvoie une nouvelle matrice construite à partir de la matrice considérée (référencée
par this) et celle passée en paramètres.
– CalculSomme renvoie la somme
– CalculProduit renvoie le produit
Si les calculs ne sont pas possibles (tailles des matrices non compatibles,. . . )
ces méthodes renvoient null
Calcul du déterminant La méthode CalculDeterminant permet de calculer le
déterminant d’une matrice. Une méthode relativement facile à programmer est le
calcul récursif.
– si la matrice a une taille de 1 × 1, le déterminant est la valeur contenue dans
la matrice,
– sinon, on calcul le déterminant de manière récursive.
Exemple
pour une matrice
3×3


a0,0 a0,1 a0,2
A = a1,0 a1,1 a1,2 
a2,0 a2,1 a2,2
Le déterminant se calcul de la manière suivante :
1
Les méthodes permettant d’accéder à des données privées sont des assesseurs
6
a1,1 a1,2
a1,0 a1,2
a1,1 a1,2
+ a0,2 . det
− a0,1 . det
det A = a0,0 . det
a2,1 a2,2
a2,0 a2,2
a2,1 a2,2
puis
a
a
det 1,1 1,2
a2,1 a2,2
...
= a1,1 . det a2,2 − a1,2 det a2,1
Correction :
import java.util.Random;
public class Matrice {
/**
* Les donnees contenues dans la matrice
*/
public int[][] donnees;
/**
* Constructeur de base
*/
public Matrice() {
}
/**
* Construction d’une matrice a partir de ses dimensions
*
* @param nbLignes le nombre de lignes
* @param nbColonnes le nombre de colonnes
*/
public Matrice (int nbLignes, int nbColonnes){
if ( (nbLignes != 0) && (nbColonnes != 0) ){
this.donnees = new int[nbLignes][nbColonnes];
}
}
/**
* Construction d’une matrice a partir d’un tableau
*
* @param unTableau les donnees sources
*/
public Matrice (int[][] unTableau){
if ( (unTableau.length != 0) && (unTableau[0].length != 0) ){
7
this.donnees = new
int[unTableau.length][unTableau[0].length];
for (int i = 0; i < unTableau.length; i++) {
for (int j = 0; j < unTableau[0].length; j++) {
this.donnees[i][j] = unTableau[i][j];
}
}
}
}
/**
* Construit une matrice en copiant une matrice existant
*
* @param uneMatrice la matrice source
*/
public Matrice (Matrice uneMatrice){
this.donnees = new
int[uneMatrice.donnees.length][uneMatrice.donnees[0].length];
for (int i = 0; i < donnees.length; i++) {
for (int j = 0; j < donnees[0].length; j++) {
this.donnees[i][j] = uneMatrice.donnees[i][j];
}
}
}
/**
* Renvoie le nombre de lignes composant la matrice
*
* @return le nombre de lignes
*/
public int getNombreLignes(){
return this.donnees.length;
}
/**
* Renvoie le nombre de colonnes composant la matrice
*
* @return le nombre de colonne
*/
public int getNombreColonnes(){
return this.donnees[0].length;
}
/**
* Permet de lire un element de la matrice
*
* @param ligne l’abcisse de la cellule voulue
8
* @param colonne l’ordonnee de la cellule voulue
* @return la valeur de cet element
*/
public int getDonnees(int ligne, int colonne) {
if( (ligne<this.donnees.length) &&
(colonne<this.donnees[0].length) ){
return this.donnees[ligne][colonne];
}else{
return 0;
}
}
/**
* Permet d’ecrire un element dans la matrice
*
* @param ligne l’abcisse de la cellule voulue
* @param colonne l’ordonnee de la cellule voulue
* @param uneValeur la valeur a ecrire
*/
public void setDonnees(int ligne, int colonne, int uneValeur) {
if( (ligne<this.donnees.length) &&
(colonne<this.donnees[0].length) ){
this.donnees[ligne][colonne] = uneValeur;
}
}
/**
* Remplissage aleatoire de la matrice avec des valeurs
comprises en 0 et 9
*/
public void RemplirMatriceAleatoirement(){
Random generateurAleatoire = new Random();
for (int i = 0; i < this.donnees.length; i++) {
for (int j = 0; j < this.donnees[0].length; j++) {
this.donnees[i][j] = generateurAleatoire.nextInt(10);
}
}
}
/**
* Affiche le contenu de la matrice
*/
public void AfficherMatrice(){
for (int i = 0; i < this.donnees.length; i++) {
for (int j = 0; j < this.donnees[0].length; j++) {
System.out.print("\t"+this.donnees[i][j]);
}
9
System.out.println();
}
}
/**
* Calcul la somme de la matrice actuelle avec la matrice passee
en parametre
*
* @param uneMatrice la matrice a ajouter
* @return la somme matricielle
*/
public Matrice CalculSomme(Matrice uneMatrice){
Matrice Somme = null;
if( (this.donnees.length == uneMatrice.donnees.length) &&
(this.donnees[0].length == uneMatrice.donnees[0].length)
){
Somme = new Matrice
(this.donnees.length,this.donnees[0].length);
for (int ligne = 0; ligne < this.donnees.length ;
ligne++) {
for (int colonne = 0; colonne < this.donnees[0].length;
colonne++) {
Somme.donnees[ligne][colonne] =
this.donnees[ligne][colonne] +
uneMatrice.donnees[ligne][colonne];
}
}
}
return Somme;
}
/**
* Calcul le produit de la matrice actuelle avec la matrice
passee en parametre
*
* @param uneMatrice la matrice a multiplier
* @return le produit matriciel
*/
public Matrice CalculProduit(Matrice uneMatrice){
Matrice Produit = null;
if( (this.donnees.length == uneMatrice.donnees[0].length) &&
(this.donnees[0].length == uneMatrice.donnees.length) ){
Produit = new
Matrice(this.donnees.length,uneMatrice.donnees[0].length);
10
for (int ligne = 0; ligne < this.donnees.length ;
ligne++) {
for (int colonne = 0; colonne <
uneMatrice.donnees[0].length; colonne++) {
Produit.donnees[ligne][colonne] = 0 ;
for (int m = 0; m < this.donnees[0].length; m++) {
Produit.donnees[ligne][colonne] =
Produit.donnees[ligne][colonne] + (
this.donnees[ligne][m] *
uneMatrice.donnees[m][colonne]);
}
}
}
}
return Produit;
}
/**
* Calcul le determinant de la matrice de maniere recursive
*
* @return le determinant de la matrice
*/
public int CalculerDeterminant(){
int det = 0;
if ( this.donnees.length == this.donnees[0].length ){
if ( (this.donnees.length == 1 ) &&
(this.donnees[0].length == 1)){
det = this.donnees[0][0];
}else{
/* Parcours de la premiere ligne */
for (int colonne = 0; colonne < this.donnees[0].length;
colonne++) {
/* Creation du sous tableau */
int[][] sousTableau = new int[this.donnees.length 1][this.donnees[0].length - 1];
/* Remplissage du sous tableau */
for (int ligneTableau = 1; ligneTableau <
this.donnees.length; ligneTableau++) {
for (int colonneTableau = 0; colonneTableau <
this.donnees[0].length; colonneTableau++) {
if (colonneTableau<colonne){
sousTableau[ligneTableau-1][colonneTableau]
=
11
this.donnees[ligneTableau][colonneTableau];
}else{
if (colonneTableau>colonne){
sousTableau[ligneTableau-1][colonneTableau-1]
=
this.donnees[ligneTableau][colonneTableau];
}
}
}
}
/* Creation de la sous matrice a partir du sous
tableau */
Matrice sousMatrice;
sousMatrice = new Matrice(sousTableau);
/* Alternance de signe */
if(colonne % 2 ==0){
det = det + this.donnees[0][colonne] *
sousMatrice.CalculerDeterminant();
}else{
det = det - this.donnees[0][colonne] *
sousMatrice.CalculerDeterminant();
}
}
}
}
return det;
}
}
1.6 Classe de test
Écrivez une classe de test simple (juste une méthode main) pour tester votre
classe Matrice.
Correction :
public class TestMatrice {
/**
* @param args
*/
public static void main(String[] args) {
/*Matrice A,B,C;
A = new Matrice(2,3);
12
B = new Matrice(3,2);
A.RemplirMatriceAleatoirement();
B.RemplirMatriceAleatoirement();
System.out.println("A : ");
A.AfficherMatrice();
System.out.println("B : ");
B.AfficherMatrice();
System.out.println("Produit : ");
C=A.CalculProduit(B);
C.AfficherMatrice();*/
Matrice E;
E = new Matrice(3,3);
E.RemplirMatriceAleatoirement();
E.AfficherMatrice();
System.out.println("--- Determinant ---");
System.out.println(E.CalculerDeterminant());
}
}
2 Les chaı̂nes
2.1 Éléments théoriques
Les chaı̂nes de caractères sont représentées par différentes classes. La plus utilisée est la classe String. Son comportement est particulier et doit être bien compris pour éviter de “mauvaises surprises” lors du développement de programme.
La classe String est déclarée final dans le langage. Il est donc impossible de
créer une classe fille.
Construction de chaı̂ne La construction des chaı̂nes est simplifiée dans la langage. Il n’est pas nécessaire d’appeler directement le constructeur (c’est le seul cas
dans le langage Java !).
String maChaine;
maChaine = "Bonjour";
Dans la première ligne la référence est déclarée puis dans la deuxième ligne elle est
assigné à l’objet String contenant la chaı̂ne Bonjour. Elle peut être écrite (c’est
normalement l’usage) en une ligne :
String maChaine = "Bonjour";
13
Les chaı̂nes peuvent être mise bout-à-bout (concaténées) en utilisant l’opérateur
+. Il s’agit en fait d’une notation simplifiée évitant l’appel de la méthode concat de
la classe String.
String un = "Un";
String deux = " Deux";
String trois = un + deux;
Méthodes utiles de la classe String
– Pour obtenir le nombre d’élément (caractères) dans la chaı̂ne, on utilise la
méthode length().
– La méthode char charAt(int index) renvoie le caractère situé à la position
donnée par index, s’il existe.
– int indexOf(String str) permet de recherche la position (renvoyée par
l’entier) de la chaı̂ne str dans la chaı̂ne utilisée.
– Deux chaı̂nes peuvent être comparées en utilisant la méthode equals :
a.equals(‘‘Toto’’).
– Il est aussi possible de les comparer en ignorant la casse (majuscule/minuscule) avec la méthode equalsIgnoreCase.
– Les méthodes startsWith et endsWith permettent de vérifier si une chaı̂ne
contient une sous chaı̂nes en début/fin de la chaı̂ne considérée.
L’extrait ci-dessus présente l’utilisation de deux de ces méthodes :
src/ExempleChaine.java
Dans la document Java on trouve une méthode surchargée déclarée ainsi :
static String valueOf(...)
Cette méthode permet de convertir un type primitif en chaı̂ne de caractères
(entier, flottant,. . . ).
Comportement particulier des String Les chaı̂nes sont immuables. Toutes les
fonctions qui renvoient une chaı̂ne renvoient un nouvel objet.
String c=’’Bonjour’’;
String b;
b=c; // b et c designent le meme objet
c=c.toLowerCase(); // b et c ne designent plus le meme objet
2.2 Palindrome
Écrivez un programme qui demande un mot à l’utilisateur (la classe Scanner
propose une méthode nextLine() qui renvoie une chaine String) et vérifie si ce
mot est un palindrome. Un palindrome est un mot qui peut être lu de manière
identique de droite à gauche et de gauche à droite (comme, par exemple, le mot
kayak).
Correction :
14
import java.util.Scanner;
public class Palindrome {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String texte;
boolean pal;
int i=0;
System.out.println("Tapez un mot : ");
texte = scan.nextLine();
do{
if (texte.charAt(i)!= texte.charAt(texte.length()-i-1)){
pal = false;
}else{
pal = true;
}
i++;
}while( (i<texte.length()) && pal);
if (pal){
System.out.println(texte + " est un palindrome");
}else{
System.out.println(texte + " n’est pas un palindrome");
}
}
}
15
Téléchargement