Introduction à JAVA

Les structures de contrôle

2.1. Blocs d'instructions

Un bloc est un ensemble d'instructions contenues entre deux accolades { } . Il définit la visibilité (portée) des variables qui y sont déclarées.
Il est possible d'imbriquer des blocs.

2.2. Exécution conditionnelle

Il existe en JAVA deux structures : Si_alors_sinon ( if_then_else ) Au_cas_ou ( switch )

2.2.1 Structure if_then_else

Sous sa forme complète, cette instruction est codée :     if (expression) blocvrai; else blocfaux; L'expression du test qui doit être écrit entre deux parenthèses ( ) est une expression booléenne .
Si expression est vraie, alors on exécute les instructions contenues dans blocvrai sinon on exécute celles contenues dans blocfaux .     if (i==3) k = 1; else k = -1; Il est possible d'omettre le else . Si expression est fausse, alors aucun code n'est exécuté.
Il est possible d'imbriquer des structures if_then_else .

if (a == 1)
   st = "a vaut 1";
else if (a ==2)
   st = "a vaut 2";
else st = "a ne vaut pas 1 ou 2";

La branche else est rattachée au dernier if rencontré.

En cas de doute, il faut utiliser des accolades.

Exemple :

if (a ==1)
   if (b == 1) inst1; else inst2;

inst2 n'est exécutée que si a vaut 1 et si b est différent de 1.

Il est préférable d'écrire :

if (a ==1){
   if (b == 1) inst1; else inst2;}

2.2.2 L'opérateur ternaire

C'est un opérateur spécial qui autorise un test simple sans utiliser l'instruction if  :

variable = condition ? siTestVrai : si TestFaux

variable prend la valeur siTestVrai si le test booléen condition est vrai et la valeur siTestFaux dans le cas contraire.
Exemple :

int a = 1, b=3;
int mini = (a<b) ? a : b; //les parenthèses sont facultatives

Ce code est équivalent à :

int a = 1, b = 3;
int mini ;
if (a < b) then mini = a ; else mini = b;

2.2.3 Structure switch

En cas de tests multiples, il est préférable d'utiliser l'instruction switch plutôt qu'une série de if imbriqués. Cette instruction se comporte comme un aiguillage qui exécute des instruction différentes ( case ) selon le résultat d'une expression logique. A l'entrée dans la structure, cette expression est évaluée et son résultat est comparé à chaque valeur des instructions case . En cas d'égalité, les instructions de cette clause sont exécutées jusqu'à la rencontre d'une instruction break qui entraîne la sortie de la structure switch. La clause (optionnelle)   default est exécutée lorsque la valeur de l'expression d'aiguillage n'est égale à aucun des cas. D'un point de vue logique, les clauses case sont considérées comme des étiquettes  (label) : elles sont donc suivies du caractère «  :  ». (cf § 2.3.4)

Le type de la variable d'une instruction case doit être char, byte, short ou int.

Structure :

switch (variable){ //début du bloc switch
   case cas1: //cas1 = char, byte, short ou int
     instruc11;
     instruc12;
     break ; //si ce break est omis, on exécute aussi instruc21 et instruc22
   case cas2 :
     instruc21;
     instruc22;
     break;
   default :
     instruc_par_defaut;
    } // fin du bloc switch

Exemple  :

int erreur ;
. . .
switch (erreur){
case 1 : afficher("Argument de fonction non valide");
         erreur=0; break;
case 2 : afficher("Syntaxe incorrecte");
        erreur=0; break;
case 3 : afficher("Division par zéro");
        erreur=0; break;
default : afficher("Erreur inconnue");}

Selon la valeur de erreur , on sélectionne l'argument de la procédure afficher( ).

2.3 Exécutions itératives

Ces structures permettent une exécution répétitive du code (boucle). L'exécution cesse quand une condition de test n'est plus remplie. Dans JAVA, il existe trois structures itératives, while, do.while et for.

2.3.1 Boucles while

On exécute un bloc d'instruction tant que une condition est vraie.

while (condition) {
   instructions ;}

Déroulement :
A l'entrée dans la structure, on évalue le booléen ( condition ). Si le test est vrai, on exécute l'instruction qui suit (ou le bloc). On réévalue la condition. Si elle est toujours vraie, on exécute à nouveau le corps de la boucle et ainsi de suite jusqu'à la condition devienne fausse. On saute alors à l'instruction qui suit le corps de la boucle. Si le test est faux au départ, le contenu de la boucle n'est jamais exécuté.
L'une des instructions du corps de la boucle doit faire évoluer la valeur de condition sinon on obtient une boucle sans fin.
Exemple :

int i = 100, j = 0, somme = 0;
while (j <= i){
    somme += j;
    j++;}

A la sortie de la boucle, somme contient la somme des 100 premiers entiers.

Attention de ne pas mettre de point virgule après la condition.

Quand on fait cette erreur, non décelée par le compilateur (car la syntaxe est correcte) le code qui suit le point virgule n'est pas considéré comme faisant parti de la structure while !
Exemple :

int i = 100, j = 20;
while (j<= i);
  {   . . .
      j++;}

La valeur finale de j est 21.

2.3.2 Boucle do_while

Cette structure est très proche de la structure while. Sa syntaxe est :

do{
instructions;}
while (condition);

Dans cette boucle faire_tant_que , la condition est évaluée après l'exécution du corps de la boucle. Elle est au minimum exécutée une fois même si la condition à tester est fausse au départ.
Exemple :

int i = 100, j = 0, somme = 0 ;
do{
    somme += j;
    j++;}
while (j <= i);

A la sortie de la boucle, la variable somme contient la somme des 100 premiers entiers.

2.3.3 Boucles for

La structure de la boucle for est la suivante : for (exp1 ; exp2 ; exp3)
    instruction; Si le corps de la boucle contient plusieurs instructions, on utilise des accolades pour définir le bloc à itérer.

exp1 initialise le compteur (après une déclaration éventuelle auquel cas la portée de la variable compteur est limitée à la boucle)
exp2 est une condition de test qui est évaluée à chaque passage. La boucle est exécutée tant que exp2 est vraie.
Après exécution du contenu de la boucle, exp3 est exécutée. Cette expression est souvent l'incrémentation du compteur mais ce n'est pas obligatoire.

Une boucle for est alors équivalente à la structure while suivante :

initialisation_compteur;
while (condition){
    instructions ;
    incrementation ;}

On utilise en général la boucle for quand le nombre d'itérations est connu a priori.
Exemple :

int somme = 0;
for (int i=0; i<=100; i++) //la portée de i est limitée au bloc for
    somme+= i;

mais la structure suivante est également correcte :

int somme = 0;
for (int i=0; i<=100;){
    somme += i;
    i++ ;}

Remarques :
* exp1 et exp3 peuvent contenir plusieurs instructions qui sont alors séparées par des virgules.
Exemple :
for (int i=0,j=10; i<=100; i++,j--)
    instructions;
*  La boucle : for ( ; ; ;) {instructions;} correspond à la boucle : while (true){instructions;}

Il est possible d' imbriquer toutes les structures itératives. Il faut alors veiller à la portée des variables locales.

2.3.4 Etiquettes

Il est possible d'identifier une instruction ou un bloc avec une étiquette ( label ). L'étiquette est formée d'un nom arbitraire suivi du caractère « deux points ». Cette possibilité est utilisée avec les instruction de rupture break et continue .

2.3.5 Break

Cette instruction (déjà rencontrée dans switch) est aussi utilisable dans les trois structures itératives. Elle sert à interrompre le flot des instructions et à sortir du bloc courant sans exécuter les instructions qui suivent le break. Cette instruction permet de quitter « proprement » une structure itérative.
Exemple :
On cherche si un tableau tab[] de 100 entiers contient la valeur 5.

int valeur = 5 ;
boolean ok = false ;
for (int i = 0 ; i<100; i++){
   if (tab[i]==valeur){
      ok = true;
      break;}}
if (ok)...

On quitte la boucle dès que la valeur cherchée est trouvée.
On cherche maintenant si un tableau à deux dimensions tab[][] de 100*50 entiers contient la valeur 5 et on veut quitter la boucle dès que cette valeur est trouvée. Le code suivant :

int valeur = 5 ;
boolean ok = false ;
for (int i = 0 ; i<100; i++){
   for (int j = 0 ; j<50; j++){
      if (tab[i][j] == valeur){
         ok = true;
         break;}}}
if (ok) ...

ne fonctionne pas de la manière souhaitée car le break fait quitter seulement la boucle d'indice j.
Il faut utiliser un break label. Quand cette instruction est rencontrée, on quitte le bloc nommé par l'étiquette label.

int valeur = 5 ;
boolean ok = false ;
bcl1 :   //label
for (int i = 0 ; i<100; i++){
   for (int j = 0 ; j<50; j++){
      if (tab[i][j] == valeur){
         ok = true;
         break bcl1;}}}
if (ok) ...

2.3.6 Continue

Cette instruction modifie aussi le déroulement normal d'une boucle. Elle permet de sauter les instructions qui suivent continue et de redémarrer le flot d'instructions au niveau de l'évaluation de la condition de la boucle.
Contrairement à l'instruction break qui fait quitter la boucle, on saute les instructions qui suivent continue puis on continue l'exécution de l'itération.
L'instruction continue peut aussi se combiner avec une étiquette.

bcl1 :     //label
for (int i = 0 ; i<100; i++){
   for (int j = 0 ; j<50; j++){
      ...
      if (j == 15) continue;     // retour début boucle d'indice j
      ...
      if (i == 5) continue bcl1; // retour début boucle d'indice i
      ... }}

2.3.7 Return

Cette instruction termine immédiatement l'exécution des méthodes et procédures. On peut donc considérer que c'est aussi une instruction de contrôle.