corrigé

Transcription

corrigé
Tp 1 – correction
Structures de données (IF2)
Remarque générale : compilez et exécutez le code au-fur-et-à mesure de son écriture. Il est plus
facile de corriger une petite portion de code délimitée que de faire tout le travail à la fois. . .
Exercice 1 — Rappel sur la structure d’un programme Java
1. ce programme affiche «bonjour» si on l’appelle sans argument, et «bonjour» suivi du
premier argument sinon.
> java Bonjour
Bonjour
> java Bonjour Jean-Jacques
Bonjour Jean-Jacques
> java Bonjour Jean Jacques
Bonjour Jean
2. import permet d’utiliser des classes provenants d’autres bibliothèques. Ici, il ne sert à
rien, vu que l’on n’utilise rien venant de la classe Deug.
Par convention, java ne permet pas de donner un autre nom à la classe que le nom du
fichier.
La méthode main est la méthode éxécutée lors de l’appel du programme. void signifie
que cette fonction ne renvoie rien (oubliez static et public pour l’instant). String args[]
désigne les arguments passés dans la ligne de commande (Jean-Jacques (1 argument) et
Jean Jacques (2 arguments) dans les exemples ci-dessus).
Les commentaires peuvent s’écrire :
– // tout ce qui est sur le reste de la ligne est alors un commentaire
– /* ceci est un commentaire */
Les point-virgules sont placés après les instructions et également à la fin d’un import. On
en met aussi après les déclarations de propriétés.
Les parenthèses servent à passer des arguments à une méthode. Ligne 11, en l’absence
d’arguments, les parenthèses sont nécéssaire pour indiquer qu’il s’agit bien d’une méthode,
et non pas une propriété.
= est l’opérateur d’affectation.
== est l’opérateur mathématique qui teste l’égalité des deux termes.
3. Il y a deux étapes :
– on compile à l’aide de la commande javac
javac Bonjour.java
Ceci crée le fichier Bonjour.class écrit en bytecode ou code intermédiaire.
– on éxécute ce code à l’aide de la machine virtuelle java, à l’aide de la commande.
java Bonjour
– Déjà traité ci-dessus.
1
Exercice 2 — Équations
1. On se place dans le fichier Equation.java
import fr.jussieu.script.Deug;
import java.lang.*;
class Equation {
double a, b, c, delta, r1, r2;
}
Ces propriétés sont suffisantes mais pas nécessaires : les 2 équations x2 + x + 1 = 0 et
2x2 + 2x + 2 = 0 sont en effet les mêmes. Il y a une redondance dans le fait de se donner
a, b et c, et encore plus si l’on se donne delta, r1 et r2 que l’on peut calculer à partir des
précédents. En fait, une des façons les plus compactes de décrire toutes les équations du
second ordre serait de fixer a à 1 et de se donner b et c deux rééls.
2. Notre classe ressemble maintenant à ça :
class Equation {
double a, b, c, delta, r1, r2;
Equation(double _a, double _b, double _c)
{
a=_a;
b=_b;
c=_c;
}
}
Notez qu’un constructeur porte toujours le même nom que sa classe, et ne retourne aucune
valeur (il initialise seulement un objet).
Nous venons d’écrire un constructeur qui sera appelé lorque l’on créera une instance
d’Equation avec new. Par exemple si quelquepart on a :
Equation e = new Equation(1, 2, 3);
e est alors une référence vers un objet Equation dont les coefficients sont 1, 2 et 3.
3. On rajoute le membre suivant à la classe.
void calculerRacines(){
delta=b*b-4*a*c;
if (delta>=0)
{
r1=(-b-Math.sqrt(delta))/(2*a);
r2=(-b+Math.sqrt(delta))/(2*a);
}
}
Si on veut ajouter un drapeau (ou flag) indiquant la validité des racines stockées, notre
code va devenir le suivant :
class Equation {
double a, b, c, delta, r1, r2;
boolean racinesCalculees;
Equation(double _a, double _b, double _c)
{
2
racinesCalculees = false; //au départ, les racines ne sont pas à jour
a=_a;
b=_b;
c=_c;
}
void calculerRacines(){
if (!racinesCalculees) //pas la peine de les recalculer !
{
delta=b*b-4*a*c;
if (delta>=0)
{
r1=(-b-Math.sqrt(delta))/(2*a);
r2=(-b+Math.sqrt(delta))/(2*a);
}
racinesCalculees = true; //maintenant, elles sont à jour
}
}
4.
String toString()
{
if (!racinesCalculees)
return "Equation "+a+"*x^2+"+b+"*x+"+c+"=0";
else
{
if (delta>=0)
return "Equation "+a+"*x^2+"+b+"*x+"+c+" = 0. Racines "+r1+" et "+r2;
// on pourrait gérer les racines doubles aussi
else
return "Equation "+a+"*x^2+"+b+"*x+"+c+"=0. Pas de racine reelle.";
}
}
Exercice supplémentaire : modifier le code pour qu’il n’y ait pas d’horreurs du genre
x2 + −2x + −2.
5. Le fichier Probleme.java ressemble à ça :
import fr.jussieu.script.Deug;
class Probleme {
public static void main(String argd[]){
Equation monEquation=new Equation(1, 2, 1);
monEquation.calculerRacines();
Deug.println(monEquation);
}
}
Remarque : java va automatiquement chercher le membre toString() dans une classe pour
convertir une instance de cette classe en chaine de caractère. Ainsi, on peut se contenter
de mettre :
Deug.println(monEquation);
au lieu de
Deug.println(monEquation.toString());
6. On a donc ceci :
3
import fr.jussieu.script.Deug;
class Probleme {
public static void main(String argd[]){
Equation monEquation=new Equation(1, 2, 1);
monEquation.calculerRacines();
monEquation.a=0;
Deug.println(monEquation);
}
}
Le résultat n’est plus valide : on a modifié un coefficient sans modifier les valeurs du
discriminant et des racines ! Dans le cas présent, c’est encore pire, on n’a même plus une
équation du second degré. En fait on voudrait empêcher l’utilisateur de faire n’importe
quoi avec les propriétés d’une équation (comme mettre a à 0 ou bien afficher avant d’avoir
recalculé les racines).
7.
class Equation {
private double a, b, c, delta, r1, r2;
private boolean racinesCalculees;
public Equation(double _a, double _b, double _c)
{
racinesCalculees = false;
a=_a;
b=_b;
c=_c;
}
void public calculerRacines(){
racinesCalculees = true;
delta=b*b-4*a*c;
if (delta>=0)
{
r1=(-b-Math.sqrt(delta))/(2*a);
r2=(-b+Math.sqrt(delta))/(2*a);
}
}
public String toString()
{
if (!racinesCalculees)
return "Equation "+a+"*x^2+"+b+"*x+"+c+"=0";
else
{
if (delta>=0)
return "Equation "+a+"*x^2+"+b+"*x+"+c+" = 0. Racines "+r1+" et "+r2;
else
return "Equation "+a+"*x^2+"+b+"*x+"+c+"=0. Pas de racine reelle.";
}
}
}
Un utilisateur extérieur à la classe ne peut plus accéder à ses propriétés. En revanche, les
fonctions membres de la classes peuvent le faire, sinon, on ne pourrait rien faire du tout !
4
Remarquez les mots-clef public facultatifs rajoutés pour insister sur le fait que les méthodes
écrites sont accessibles pour un utilisateur.
Si on reprend le code de problème :
class Probleme {
public static void main(String argd[]){
Equation monEquation=new Equation(1, 2, 1);
monEquation.calculerRacines();
monEquation.a=0;
Deug.println(monEquation);
}
}
on aura une erreur ligne 5. Si on enlève cette ligne, tout se passe bien.
8. Si on voulait que l’utilisateur ne fasse pas n’importe quoi, on avait néanmoins envie qu’il
puisse accéder aux propriétés d’une instance de la classe. On définit donc des accesseurs
et modifieurs public pour les propriétés dont on souhaite qu’elles soient accessibles et/ou
modifiables.
public double getA()
{
return a;
}
public double getB()
{
return B;
}
public double getC()
{
return c;
}
public double getDelta()
{
return delta;
}
public double getR1()
{
return r1;
}
public double getR2()
{
return r2;
}
public boolean getRacinesCalculees()
{
return racinesCalculees;
}
public void setA(double x)
{
if (x!=0)
5
a=x;
//sinon on pourrait par exemple renvoyer un message d’erreur.
//ici, on choisit de ne rien faire
racinesCalculees=false;
}
public void setB(double x)
{
b=x;
racinesCalculees=false;
}
public void setC(double x)
{
c=x;
racinesCalculees=false;
}
On n’a pas envie que l’utilisateur puisse modifier directement delta, r1, r2 ou racinesCalculees.
Si l’utilisateur modifie directement les coefficients, le flag racinesCalculees est remis à
faux, ce qui empéchera d’afficher des résultats faux en utilisant toString().
On peut maintenant écrire ce genre de choses dans main :
import fr.jussieu.script.Deug;
class Probleme {
public static void main(String argd[]){
Equation monEquation=new Equation(1, 2, 1);
// une instance d’Equation
monEquation.calculerRacines();
Deug.println(monEquation);
//affiche : Equation 1.0*x^2+2.0*x+1.0 = 0. Racines -1.0 et -1.0
monEquation.setA(3);
Deug.println(monEquation);
//affiche : Equation 3.0*x^2+2.0*x+1.0 = 0.
Equation monEquation2=new Equation(3, 2., 4);
// une autre instance d’Equation
/* ... */
if (monEquation2.getRacinesCalculees())
{
Deug.println(monEquation2.getDelta());
}
else
{
monEquation2.calculerRacines();
Deug.println(monEquation2.getDelta());
}
6
}
}
Exercice 3 — Nombres complexes
Le fichier Complexe.java
import java.lang.*;
class Complexe {
private double re;
private double im;
public Complexe(){
re=0;
im=0;
}
public Complexe(double _re, double _im){
re=_re;
im=_im;
}
public double getRe()
{
return re;
}
public double getIm()
{
return im;
}
public void setRe(double _re)
{
re=_re;
}
public void setIm(double _im)
{
im=_im;
}
public String toString()
{
return re+" + i "+im;
}
public void additionner(Complexe c)
{
re+=c.re;
im+=c.im;
}
public void multiplier(Complexe c)
{
7
double new_re=re*c.re-im*c.im;
double new_im=re*c.im+im*c.re;
re=new_re;
im=new_im;
}
public void rotation(double theta)
{
Complexe c=new Complexe(Math.cos(theta), Math.sin(theta));
multiplier(c);
}
}
Un TestComplexe.java possible :
import fr.jussieu.script.Deug;
public class TestComplexe{
public static void main (String args[]){
Complexe premier, deuxieme, troisieme;
premier=new Complexe();
deuxieme=new Complexe(1, 2);
troisieme=deuxieme;
Deug.println("premier "+premier);
Deug.println("deuxieme "+deuxieme);
Deug.println("troisieme "+troisieme);
Deug.println();
premier.setRe(3);
deuxieme.setRe(4);
Deug.println("premier "+premier);
Deug.println("deuxieme "+deuxieme);
Deug.println("troisieme "+troisieme);
Deug.println();
premier.additionner(deuxieme);
Deug.println("premier "+premier);
Deug.println();
premier.multiplier(deuxieme);
Deug.println("premier "+premier);
Deug.println();
premier.rotation(Math.PI/2);
Deug.println("premier "+premier);
Deug.println();
}
}
8