Accès rapide :
La vidéo
L'instruction for
La syntaxe du for
Les expressions du for sont facultatives
Utilisation d'un for pour parcourir un tableau
Utilisation d'Eclipse pour produire un squelette de code pour un for
Travaux pratiques
L'instruction while
La syntaxe du while
Assistance proposée par Eclipse
Travaux pratiques
L'instruction do/while
La syntaxe du do while
Assistance proposée par Eclipse
Travaux pratiques
Cette vidéo vous montre comment utiliser les instructions de boucle du langage (for
, while
et do while
).
L'instruction for
permet de définir une boucle. Une boucle permet de répéter un certain nombre de fois une ou plusieurs instruction.
On parle aussi d'un traitement itératif (répétitif). Le for
n'est pas la seule instruction itérative : d'autres instructions Java
(le while
, le do while
, ...) permettent aussi de définir des boucles, nous les verrons ensuite.
Pour en revenir au for
, bien que ce soit l'instruction itérative la plus riche, en informations à fournir, cette instruction est assez
simple à comprendre. Un for
attend trois expressions ainsi qu'une ou plusieurs instructions à répéter. Voici le format de l'instruction
for
:
1 2 3 |
for ( initExp; testExp; incExp ) { // Bloc d'instructions à exécuter } |
Commençons par parler des trois expressions. Elles doivent obligatoirement être séparées par des caractères ;
.
Voici la signification de chacune d'entre elles.
initExp : cette première expression est appelé expression d'initialisation. Effectivement, pour effectuer une boucle, nous aurons besoins
de créer et d'initialiser une variable. Cette variable sera détruite une fois que l'instruction for
sera terminée.
testExp : cette seconde expression doit effectuer un test (donc doit renvoyer un booléen). Si le résultat de cette expression est vrai, alors
une nouveau tour de boucle sera effectué. Si l'expression renvoie false
, alors la boucle s'arrête. C'est donc une expression de
« rebouclage ». Il est a noter que cette expression est évaluée avant chaque exécution du bloc de code à répéter. Si le premier coup
l'expression renvoie directement false
, alors aucun tour de boucle ne sera réalisé.
incExp : cette dernière expression permet d'incrémenter votre variable de boucle à la fin de chaque tour de boucle.
Pour ce qui est du code à répéter, il peut y avoir une instruction ou plusieurs. S'il n'y en a qu'une, alors les accolades ne sont pas obligatoire. Voici un exemple concrêt qui affiche les dix premiers entiers positifs (en commençant par un).
1 2 3 4 5 6 7 8 9 10 11 |
public class Demo { public static void main( String [] args ) { for ( int counter = 1; counter <= 10; counter++ ) System.out.println( counter ); System.out.println( "Bye bye" ); } } |
counter
semble donc approprié. Pour autant, un index de boucle est souvent appelé i
.
Donc l'exemple commence par initialiser la variable counter
à la valeur 1 et comme 1 est inférieur à 10 alors on afficher cette valeur.
Ensuite, counter
est incrémenté, il vaut donc maintenant 2. On restete l'expression de rebouclage et comme 2 est inférieur à 10, on affiche
2. Et ainsi de suite jusqu'à afficher 10. Après ce dernier affichage, counter
est incrémenté : il passe à 11 et comme 11 n'est pas
inférieur ou égal à 10, la boucle s'arrète. On finit donc par afficher "Bye bye"
. Voici le résultat produit par l'exemple précédent.
$> javac Demo.java $> java Demo 1 2 3 4 5 6 7 8 9 10 Bye bye $>
Ce second exemple permet d'afficher les dix premiers entiers positifs (en commençant par un) mais aussi de calculer la somme de ces entiers. Comme nous devons répéter deux instructions, les accolades sont donc obligatoires.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Demo { public static void main( String [] args ) { int sum = 0; for ( int counter = 1; counter <= 10; counter++ ) { System.out.println( counter ); sum += counter; } System.out.println( "Sum == " + sum ); } } |
Et voici les résultats produits par l'exemple ci-dessus.
$> javac Demo.java $> java Demo 1 2 3 4 5 6 7 8 9 10 Sum == 55 $>
Vous n'êtes pas obligé de fournir les trois expressions d'un for. Mais attention, vous êtes obligé d'indiquer leur abscence en plaçant correctement
les deux caractères ;
. L'exemple ci-dessous de définit pas l'expression d'initialisation. Pour faire en sorte que le programme tourne
correctement, la variable counter
est malgré tout définie en dehors de la boucle.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Demo { public static void main( String [] args ) { int counter = 1; for ( ; counter <= 10; counter++ ) { System.out.println( counter ); } System.out.println( "Bye bye" ); } } |
;
à l'intérieur des paranthèses de l'instruction for
.
Effectivement, il n'y a pas d'expression juste devant ce caractère.
Du coup, il est très simple de réaliser une boucle infinie : en voici un petit exemple ci-dessous. Dans cet exemple, j'ai oublié d'incrémenter la variable de boucle. Sans action de votre part, ce programme ne se terminera pas.
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Demo { public static void main( String [] args ) { for ( int counter = 1; counter <= 10; ) { System.out.println( counter ); } System.out.println( "Bye bye" ); } } |
Ce dernier exemple produit aussi une boucle infinie. Là c'est radical : il n'y a aucune expression renseignée.
1 2 3 4 5 6 7 8 9 10 11 |
public class Demo { public static void main( String [] args ) { for ( ; ; ) { System.out.println( "Infinite loop" ); } } } |
On peut utiliser l'instruction pour parcourir les différentes valeurs d'un tableau. Par contre il ne faut pas oublier que les indices d'un tableau
commencent à 0. Donc si l'on considère un tableaux de chaînes de caractères contenant les noms des douze mois de l'année, il convient de faire
« varier » votre variable de boucle de 0 à 11. Voici un petit exemple de parcours d'un tableau via l'instruction for
traditionnelle (j'utilise ce qualificatif de traditionnelle, car il existe aussi une instruction « for each » mais nous l'étudierons
ultérieurement).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Demo { public static void main( String [] args ) { String [] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; for ( int index=0; index<12 ; index++ ) { System.out.println( months[ index ] ); } } } |
Mais nous aurions pu faire encore mieux et demandant sa taille directement au tableau. Cela évitera des erreurs sur la taille de ce dernier.
length
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Demo { public static void main( String [] args ) { String [] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; for ( int index=0; index<months.length ; index++ ) { System.out.println( months[ index ] ); } } } |
Encore une fois, un IDE (Integrated Development Environment) peut vous assister dans la production de votre code.
Dans ce cours, je pars du principe que vous utilisez Eclipse, mais la procédure ici décrite fonctionne aussi sur de nombreux autres ateliers de développement.
Si vous souhaitez obtenir un squelette de code pour une instruction for
, commencez par taper for
puis appuyez
simultanément sur CTRL + Espace. Une liste de propositions vous sera affichée, il ne vous restera plus qu'à y sélectionner l'assistant souhaité.
Voici une petite capture d'écran issue de l'IDE Eclipse.
Je vous propose de faire un peu de mathématiques en me codant un programme calculant une puissance. Bien entendu, le langage Java fourni déjà la
méthodes Math.pow( value, power )
qui permet de calculer une puissance. Néanmoins, je vous demande de coder un algorithme de calcul de
puissance vous même en utilisant une boucle for
. Pour rappel, voici comment calculer une puissance (on ne travaillera que sur des entiers
positifs)
Le programme proposera de saisir à partir du clavier la valeur à utiliser ainsi que la puissance à laquelle élever la valeur.
Pour réaliser cette saisie, je vous propose d'utiliser le code suivant.
Nous reviendrons ultérieurement sur ce Scanner
et la construction try
(ici c'est plus précisément un « try-with-resources »),
pour l'heure acceptez simplement que la méthode nextInt
vous renvoie l'entier saisie sur la console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.Scanner; public class Demo { public static void main( String [] args ) { try ( Scanner scanner = new Scanner( System.in ) ) { System.out.print( "Veuillez saisir votre value : " ); int value = scanner.nextInt(); // TODO: continuer le TP } } } |
Voila, c'est maintenant à vous de faire. Jouez le jeu et ne passez pas directement à la correction ;-)
La correction
Il faut donc multiplier x le nombre de fois spécifié par la puissance : comme on connait à l'avance le nombre de tours de boucles à effectuer,
la construction for
est toute indiquée pour ce programme. Voici ma proposition pour ce TP.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.Scanner; public class Power { public static void main( String [] args ) { try ( Scanner scanner = new Scanner( System.in ) ) { System.out.print( "Veuillez saisir votre value : " ); int value = scanner.nextInt(); System.out.print( "Veuillez saisir votre puissance : " ); int power = scanner.nextInt(); int result = 1; for( int pow=0; pow<power; pow++ ) { result = value * result; } System.out.printf( "%d^%d == %d\n", value, power, result ); } } } |
Et voici quelques exemples d'utilisation de notre programme.
$> java Power Veuillez saisir votre value : 2 Veuillez saisir votre puissance : 0 2^0 == 1 $> java Power Veuillez saisir votre value : 2 Veuillez saisir votre puissance : 1 2^1 == 2 $> java Power Veuillez saisir votre value : 2 Veuillez saisir votre puissance : 2 2^2 == 4 $> java Power Veuillez saisir votre value : 2 Veuillez saisir votre puissance : 3 2^3 == 8 $>
Le while
est plus simple à utiliser que le for
. Effectivement, une seule expression est attendue par le while
(la condition de rebouclage) contre trois pour le for
. En français, while signifie tant que : donc la boucle va tourner tant que
l'expression de rebouclage calcule true
. Voici la syntaxe générale du while
:
1 2 3 |
while ( testExp ) { // Bloc d'instructions à exécuter } |
A titre d'exemple, voici un programme effectuant deux fois une même boucle, mais la première fois la boucle est gérée par une instruction for
,
alors que la seconde fois, c'est l'instruction while
qui est utilisée. Dans les deux cas, on affiche tous les chiffres de 0 à 9.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class Demo { public static void main( String [] args ) { // La première boucle est réalisée via l'instruction for for( int i=0; i<10; i++ ) { System.out.print( i + " " ); } System.out.println(); // La seconde boucle est réalisée via l'instruction while int i=0; while( i<10 ) { System.out.print( i + " " ); i++; } System.out.println(); } } |
Et voici les résultats produits par cet exemple de code.
$> java Demo 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
On peut donc aussi bien utiliser le for
ou le while
pour réaliser une quelconque boucle. La syntaxe divergera juste un petit peu.
Du coup, vous vous posez certainement une question : quand utiliser l'instruction for
et quand utiliser l'instruction while
?
Pour moi, la réponse est simple ! Quand vous connaissez à l'avance, le nombre de tours de boucle à exécuter, préférez l'instruction for
car
elle est alors plus lisible. Par contre, si vous ne connaissez pas à l'avance le nombre de tours de boucle à exécuter, alors l'instruction
while
sera très certainement plus adaptées. En conséquence, dans l'exemple précédent, la version for
devrait être
privilégiée. Qu'en pensez-vous ?
Encore une fois, vous pouvez utiliser Eclipse pour générer un squelette de while
. Pour ce faire, commencez par tapez while
à l'endroit ou vous souhaitez insérer votre boucle, puis appuyez simultanément sur CTRL + ESPACE. Normalement, une liste de choix doit s'ouvrir :
veuillez alors choisir le modèle de code adapté, comme le montre la capture d'écran suivante.
Le but de ce TP est d'écrire un programme permettant de saisir des commandes pour faire bouger une hypothétique voiture télécommandée. Pour simuler la voiture, on utilisera des affichages sur la console pour indiquer les valeurs de certaines variables. Vous devez avoir deux variables :
La première sera appelée direction
. Son type sera un type énuméré à définir qui exposera deux états : FORWARD
(avancer)
et BACKWARD
(reculer).
La seconde sera appelée speed
et indiquera la vitesse (toujours positive) à laquelle la voiture se déplacera. La vitesse sera forcément
un multiple de 10. Si la vitesse est 0 alors la voiture est à l'arrêt.
Pour contrôler la voiture (et donc l'état de ces deux variables) vous devez utiliser des commandes. Voici la liste des commandes autorisées :
accelerate : permet d'augmenter la vitesse de 10.
decelerate : permet de diminuer la vitesse de 10. Attention, la vitesse ne pourra pas être négative.
foreward : permet de modifier la direction de la voiture afin d'avancer.
backward : permet de modifier la direction de la voiture afin de reculer.
exit : permet de quiter l'application.
Pour permettre la saisie d'une commande (d'une chaîne de caractères), je vous propose le code suivant.
Nous reviendrons ultérieurement sur ce Scanner
et la construction try
(ici c'est plus précisément un « try-with-resources »),
pour l'heure acceptez simplement que la méthode nextLine
vous renvoie la chaîne de caractères saisies sur la console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.Scanner; public class Demo { public static void main( String [] args ) { try ( Scanner scanner = new Scanner( System.in ) ) { System.out.print( "Enter a command: " ); String command = scanner.nextLine(); // TODO: continuer le TP } } } |
Voila, c'est maintenant à vous de me proposer une solution à ce problème. Jouez le jeu et ne passez pas directement à la correction ;-)
La correction
Pour répondre à notre problème, il me semble que le mieux est d'utiliser un switch
sur chaîne de caractères.
Si vous avez optez pour des if
imbriqués, votre programme peut très bien fonctionner, mais dans ce cas, veuillez recommencer avec un switch :-).
De plus, on ne sais pas à l'avance combien de commandes nous allons saisir. Il me semble donc plus judicieux d'utiliser un while
plutôt
qu'un for
. Même remarque : si vous avez utilisé un for
, modifier votre programme afin de tester avec un while
:-).
Voici ma proposition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import java.util.Scanner; enum Direction { FORWARD, BACKWARD; } public class Demo { public static void main( String [] args ) { System.out.println( "Super Car Remote - V1.0" ); int speed = 0; Direction direction = Direction.FORWARD; try ( Scanner scanner = new Scanner( System.in ) ) { boolean mustRun = true; while( mustRun ) { System.out.print( "Enter a command: " ); String command = scanner.nextLine(); switch( command ) { case "exit": mustRun = false; break; case "accelerate": speed += 10; break; case "decelerate": speed -= 10; if ( speed < 0 ) speed = 0; break; case "forward": direction = Direction.FORWARD; break; case "backward": direction = Direction.BACKWARD; break; default: System.out.printf( "Command %s not existing\n", command ); } if ( speed != 0 ) { System.out.println( "Your car go " + direction + " with speed of " + speed ); } else { System.out.println( "Your car is stopped!" ); } } } System.out.println( "Bye bye" ); } } |
Voici un petit exemple d'utilisation de notre télécommande virtuelle.
$> javac Demo.java $> java Demo Super Car Remote - V1.0 Enter a command: accelerate Your car go FORWARD with speed of 10 Enter a command: accelerate Your car go FORWARD with speed of 20 Enter a command: backward Your car go BACKWARD with speed of 20 Enter a command: decelerate Your car go BACKWARD with speed of 10 Enter a command: forward Your car go FORWARD with speed of 10 Enter a command: decelerate Your car is stopped! Enter a command: other Command other not existing Your car is stopped! Enter a command: exit Your car is stopped! Bye bye $>
L'instruction do while
est très proche de l'instruction while
. On peut litérallement la traduire par « faire tant que ».
La nuance, par rapport à l'instruction while
, c'est que la condition est évaluée après exécution du corps de la boucle.
Il en résulte que l'on fera au moins un tour de boucle, contrairement au while
qui peut sortir immédiatement (car la condition est
évaluée en premier). Voici la syntaxe générale de l'instruction do while
.
1 2 3 |
do { // Bloc d'instructions à exécuter } while ( testExp ); |
L'exemple suivant permet de saisir un identifiant et un mot de passe, tant que les informations renseignées ne sont pas correctes.
Comme il faut commencer par fournir les informations de connexion avant de les vérifier, l'instruction do while
est toute indiquée.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import java.util.Scanner; public class Demo { public static void main( String [] args ) { try ( Scanner scanner = new Scanner( System.in ) ) { String login, password; do { System.out.print( "Veuillez saisir votre identifiant : " ); login = scanner.nextLine(); System.out.print( "Veuillez saisir votre mot de passe : " ); password = scanner.nextLine(); } while( login.equals( "james" ) == false || password.equals( "007" ) == false ); System.out.println( "Bonjour James, vous êtes connecté !" ); } } } |
Comme précédement, il est possible de demander à Eclipse de produire un squelette de code pour votre instruction de boucle.
Pour ce faire, commencez par tapez do
à l'endroit ou vous souhaitez insérer votre boucle, puis appuyez simultanément
sur CTRL + ESPACE. Normalement, une liste de choix doit s'ouvrir : veuillez alors choisir le modèle de code adapté.
Ecrire un programme qui simule un shell classique en utilisant la boucle do while
. Pour quitter le shell on utilisera la commande exit
: comme on doit d'abord saisir la commande
avant de prendre la décision de sortir de la boucle, l'instruction do while
semble appropriée.
Les pseudo-commandes supportées sont ls
qui affichera la chaîne listing du dossier
, cd
qui affichera la chaîne on change de dossier
et donc,
exit
qui permettra de mettre fin à la boucle. Toute autre commande saisie produira un message d'erreur.
Pour permettre la saisie d'une chaîne de caractères, on utilisera le Scanner
vu dans l'exemple précédent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import java.util.Scanner; public class Demo { public static void main( String [] args ) { System.out.println( "MegaShell V1.0 - provided by KooR.fr" ); try ( Scanner scanner = new Scanner( System.in ) ) { String command; do { System.out.print( "$> " ); command = scanner.nextLine(); switch( command ) { case "exit": // Nothing to do break; case "ls": System.out.println( "listing du dossier" ); break; case "cd": System.out.println( "on change de dossier" ); break; default: System.out.println( "Commande non supportée" ); } } while( ! command.equals( "exit" ) ); System.out.println( "Exit shell" ); } } } |
Et voici un petit exemple d'utilisation de ce programme.
$> javac Demo.java $gt; java Demo MegaShell V1.0 - provided by KooR.fr $> ls listing du dossier $> cd on change de dossier $> zut Commande non supportée $> exit Exit shell
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :