II. Contrôle de l'exécution▲
À propos de ce chapitre
Ce chapitre aborde les concepts fondamentaux requis pour effectuer n'importe quelle tâche avec Ruby. Vous devrez probablement traiter des données provenant de l'utilisateur, ou exécuter une tâche plusieurs fois. Tout ceci sera introduit dans ce chapitre.
II-A. Boucles▲
Dans cette section, nous allons vous initier à un des aspects les plus puissants de la programmation : les boucles.
Démarrez votre éditeur favori, et entrez-y les lignes suivantes :
Pouvez-vous deviner ce que fera ce bout de code? Sauvegardez le fichier sous le nom boucles.rb et exécutez-le :
Comme vous avez pu le constater, le contenu de la boucle a été exécuté 4 fois. Il s'agit probablement du moyen le plus direct que Ruby nous offre pour reproduire des tâches.
II-A-1. Compter▲
Nous allons ici nous servir de ce que nous venons d'apprendre sur Ruby et les variables pour afficher les nombres compris entre 1 et 5 :
Souvenez-vous, la méthode Integer#to_s se charge de convertir la valeur numérique représentée par l'objet en une chaine de caractères. Nous avons besoin de cette méthode pour pouvoir concaténer le résultat à la chaine « count = ».
Lors de l'exécution, vous devriez avoir ceci :
II-A-2. Somme de nombres▲
Supposons que nous devons calculer la somme de tous les nombres compris entre 1 et 11. Nous venons juste de découvrir comment obtenir les nombres compris entre 1 et 11. Il nous reste simplement à les additionner :
Et voici ce qui s'affichera à l'écran :
II-A-3. Étaler une expression sur plusieurs lignes▲
Dans le dernier exemple, l'expression puts devenait quand même longue. Que faire si nous devions afficher une ligne deux, trois, ou quatre fois plus longue ?
Vous pouvez couper l'expression en plusieurs lignes, en terminant chaque ligne par le caractère «backslash» ('\').
Le caractère «backslash» doit absolument être le dernier caractère de la ligne. Si vous rajoutez un espace après, vous obtiendrez une erreur.
Essayez ceci dans IRB :
La ligne « =>nil » signifie simplement que la méthode puts ne renvoie rien.
En fait, ce n'est pas tout à fait vrai. puts renvoie quand même une valeur qui représente un état non initialisé. Ruby représente cet état particulier par l'expression nil.
Si nous avions écrit ceci :
etat = puts "Salut"
La variable etat aurait contenu nil.
Nous venons donc de voir comment étaler notre commande puts sur deux lignes. Mettons donc en pratique (dans notre programme) ce que nous venons d'apprendre :
En effet, nous pouvons utiliser cette technique pour afficher autant de lignes que nous désirons :
Vous n'êtes évidemment pas obligé de présenter la sorte du programme de cette façon. Cependant, nous pensons que l'utilisateur comprendra mieux le fonctionnement du programme. Voici ce que vous pouvez obtenir lors de son exécution :
II-A-4. Plus d'exemples▲
Nous allons ici vous montrer deux autres exemples à propos des boucles dans Ruby.
II-A-4-a. Compter à l'envers▲
Et si nous essayions de compter à l'envers? Ce concept peut se révéler fort utile, imaginez que la Nasa vous demande d'écrire un programme de décomptage pour leurs fusées! Essayez de copier ceci dans un nouveau programme :
Et voici le résultat fort attendu (notez que nous ne sommes pas responsables de l'explosion de votre ordinateur) :
II-A-4-b. Travailler sur une variable un certain nombre de fois▲
Évidemment, nous pouvons utiliser des boucles pour effectuer plusieurs fois une même opération sur une même variable.
Voici un exemple pratiquement valable. Il s'agit de calculer la factorielle d'un nombre.
La factorielle d'un nombre est le produit de tous les nombres compris entre 1 et ce nombre. Vous me suivez ? Par exemple, voici l'expression pour calculer la factorielle du nombre 6 :
6! = 6 * 5 * 4 * 3 * 2 * 1 = 720
Les mathématiciens utilisent le symbole n! pour représenter la factorielle du nombre n
Tapez ceci dans un nouveau programme Ruby, et démarrez-le :
II-A-4-c. Quelques exercices▲
- Que vaut la somme des entiers compris entre 1 et 1000 ?
- Que vaut la somme des entiers compris entre 10 et 100 ?
- Écrivez un programme qui affiche les paroles de la chanson :
1 kilomètre à pied, ça use, ça use
1 kilomètre à pied, ça use, ça use les souliers
La peinture à l'huile, c'est bien difficile
Mais c'est bien plus beau
Que la peinture à l'eau
2 kilomètres à pied...
(arrêtez-vous à 100 kilomètres)
II-B. Saisir des données provenant de l'utilisateur▲
Dans cette section, nous allons écrire un programme qui salue l'utilisateur. Le programme lui demandera son nom avant de le saluer. La méthode pour lire une chaine de caractère venant de l'utilisateur s'appelle gets.
Sauvez le fichier et démarrez-le :
Que s'est-il passé ? Pourquoi ce fichu programme va-t-il à la ligne ?
La réponse est évidente : tout simplement parce que vous avez entréune nouvelle ligne au clavier. Oui, souvenez-vous, quand vous avez appuyé sur la touche Enter…
Nous allons regarder ceci de plus près dans IRB. Démarrez IRB et tapez l'expression nom = gets. L'ordinateur va attendre une saisie, entrez une chaine quelconque. Regardez attentivement ce qu'il va se passer :
Que signifie donc ce «\n» à la fin de la chaine de caractères ?
Ce «\n» représente un retour à la ligne. Il s'agit du caractère envoyé par le clavier lorsque l'utilisateur appuie sur la touche Enter.
Avez-vous remarqué comment nous venons d'utiliser IRB pour comprendre ce qu'il s'était passé ? Il arrivera tôt ou tard que votre code se comporte d'une façon anormale. À ce moment-là, essayez-le dans IRB, vous comprendrez plus facilement la source de vos ennuis !
II-B-1. Ce fichu «\n»!▲
OK, nous savons maintenant ce qui ne va pas. Mais comment résoudre ce problème?
Il existe précisément une méthode qui s'occupera de retirer le caractère «\n» d'une chaine de caractères : String#chomp. Retournons dans IRB pour tester directement cette méthode :
Magnifique! La méthode String#chomp nous renvoie la chaine de caractères sans le retour à la ligne. Nous pouvons donc maintenant écrire :
Notez bien que la variable nom contient toujours le saut à la ligne. La bonne variable (sans le «\n») est nouveau_nom. Mais pourquoi utiliser une autre variable? Pourquoi ne pas simplement écrire ceci :
>>nom = nom.chomp
De cette façon, nous retirons directement le saut à la ligne de la variable nom.
II-B-2. Retour à notre programme▲
Il est maintenant temps de corriger le problème dans notre code :
Une dernière petite réflexion :
- chomp est une méthode de la classe String (souvenez-vous de la notation : String#chomp) ;
- gets nous renvoie une chaine de caractères (précisément, un objet de la classe String !).
Pourquoi ne pas écrire gets.chomp ? De cette façon, String#chomp sera appelé sur ce que gets retournera. En d'autres termes, nous pouvons écrire :
N'est-ce pas joli? Mettez à jour votre code et invoquez Ruby :
II-B-3. Quelques exercices▲
- Écrivez un programme qui capture deux mots du clavier, et qui les imprime sur l'écran dans l'ordre opposé de leur saisie.
- Écrivez un programme dont le comportement devra ressembler à ceci :
Pour calculer l'année de naissance de l'utilisateur, effectuez une simple soustraction entre l'année courante et son âge.
- Écrivez un programme qui demandera à l'utilisateur un nombre ainsi qu'une chaine de caractères. Ensuite, le programme doit afficher autant de fois la chaine inversée. Exemple :
Il existe plusieurs solutions possibles à cet exercice. Choisissez celle que vous préférez.
- Devinez ce que produira Ruby avec cette ligne :
nombre = gets.chomp.to_i
Essayez-la dans IRB.
- Écrivez un programme qui calculera et affichera la factorielle d'un nombre entré au clavier par l'utilisateur. Il devra fonctionner comme ceci :
Vous pouvez réutiliser le code que nous avons écrit au chapitre précédent.
II-C. Conditions▲
Dans Ruby, il est possible d'effectuer plusieurs actions en fonction d'une série de conditions, en utilisant le mot magique if. Voici un exemple :
#1
if ville == "Toronto"
age_legal_alcool = 19
#2
else
age_legal_alcool = 21
end
Ce qui veut dire :
- #1 Si (if) le contenu de la variable ville est égale à (==) la chaine « Toronto », alors nous affectons à la variable age_legal_alcool le nombre 19 ;
- #2 Sinon (else), nous affectons à la variable age_legal_alcool le nombre 21.
II-C-1. Vrai ou faux▲
Ruby permet de distinguer deux états différents d'une expression :
- vrai (true) ;
- faux (false).
Le meilleur moyen d'illustrer cette théorie est d'expérimenter quelques exemples. Comme toujours, démarrez IRB et entrez les commandes suivantes :
L'instruction if évalue si une expression quelconque (par exemple, ville == « Toronto ») est soit vraie (true), soit fausse (false) et ensuite agit en conséquence.
Notez bien la différence entre les opérateurs = et == :
- = est un opérateur d'affectation (il permet d'assigner une valeur à une variable)
- == est un opérateur de comparaison (il permet de comparer l'état de deux expressions)
II-C-2. Opérateurs conditionnels▲
Voici une liste regroupant la plupart des opérateurs conditionnels :
Opérateur |
Effet |
---|---|
== |
égal à |
!= |
n'est pas égal à |
> |
est plus grand que |
< |
est plus petit que |
>= |
est plus grand ou égal à |
<= |
est plus petit ou égal à |
II-C-3. Comparaison de chaines de caractères▲
Comment ces opérateurs se comportent-ils avec des chaines de caractères? L'opérateur == vérifie si deux chaines sont exactement identiques. Les autres opérateurs se basent sur la table ASCII pour produire et renvoyer un état de comparaison.
Qu'est-ce que cette table ASCII? Il s'agit d'une table contenant tous les caractères pouvant être générés par le clavier. Ces caractères sont triés dans cet ordre :
- D'abord les chiffres (012…789) ;
- Ensuite les lettres majuscules (ABC…XYZ) ;
- Finalement les lettres minuscules (abc…xyz).
ASCII: « American Standard Code for Information Interchange ». Ce code permet d'échanger des informations entre des ordinateurs construits par différentes entreprises. Il a été conçu pour la langue anglaise à la base. Néanmoins, il ne convient pas pour les autres langues utilisant des caractères spéciaux (comme le japonais, par exemple). Pour remédier à ce problème, Ruby utilise un système d'encodage nommé UTF8, qui permet de combiner des caractères ASCII (codés sur un octet) et des symboles spéciaux (codés sur deux octets).
Maintenant, démarrez IRB et entrez ceci :
Avez-vous remarqué comment IRB peut clarifier les choses? Vous devriez vous habituer à essayer d'abord certaines idées dans IRB. C'est un outil génial, utilisez-le !
II-C-4. L'instruction elsif▲
L'instruction elsif vous permet de rajouter plus d'une condition dans votre expression. Prenez ceci par exemple :
#1
if âge >= 60
puts "Prix senior"
#2
elsif age >= 14
puts "Prix adulte"
#3
elsif âge >= 2
puts "Prix enfant"
#4
else
puts "Gratuit!"
end
Essayons de comprendre ceci :
- #1 Si la variable âge contient une valeur plus grande ou égale à 60, nous donnons un prix senior.
- #2 Si ce n'est pas vrai, mais que âge est plus grand ou égal à 14, nous donnons un prix adulte.
- #3 Si ce n'est pas vrai, mais que âge est plus grand que 2, nous donnons un prix enfant.
- #4 Sinon, c'est gratuit !
Ruby exécutera cette séquence de conditions une par une. Uniquement la première condition vraie sera exécutée. Vous pouvez rajouter autant de elsif que vous désirez.
II-C-5. Un exemple: prix.rb▲
Pour rendre les choses plus simple à comprendre, nous allons rajouter ces conditions dans un programme. Il devra demander l'âge de l'utilisateur, et ensuite afficher le prix correspondant à cet âge :
Ce programme devrait se comporter comme ceci :
Soyez bien conscient de l'ordre dans lequel vous rajoutez vos conditions avec elsif. Seulement le code associé à la première condition évaluée comme étant «vraie» sera exécuté. Cet exemple illustre bien ce danger :
age = 21
if âge >5
puts "Plus vieux que 5 ans"
elsif âge >10
puts "Plus vieux que 10 ans"
elsif âge >20
puts "Plus vieux que 20 ans"
elsif âge >30
puts "Plus vieux que 30 ans"
end
En lisant ce code rapidement, il semblerait logique que le programme affiche « Plus vieux que 20 ans » à l'écran. Il n'en est rien! Comme dit plus haut, seule la première condition valide remporte la mise. Le programme affichera « Plus vieux que 5 ans ».
Voici la bonne méthode à utiliser :
age = 21
if âge >30
puts "Plus vieux que 30 ans"
elsif âge >20
puts "Plus vieux que 20 ans"
elsif âge >10
puts "Plus vieux que 10 ans"
elsif âge >5
puts "Plus vieux que 5 ans"
end
II-C-6. Quelques exercices▲
- Triez ces caractères en utilisant l'ordre ASCII : 2, u, A, 4, w, f, R, y
-
Souvenez-vous, la table ASCII contient tous les caractères pouvant être générés par le clavier. Utilisez IRB pour déterminer où se trouve le caractère « ? » (point d'interrogation) ?
- Avant 0 ?
- Après 9 mais avant A ?
- Après Z mais avant a ?
- Après z ?
-
En se basant sur la question précédente, écrivez un programme Ruby qui accepte un caractère quelconque au clavier. Il devra afficher un des messages suivants :
- x se situe avant 0
- x se situe entre 9 et A
- x se situe entre Z et a
- x se situe après z
II-D. Les boucles while▲
Maintenant que vous êtes familiers avec les conditions dans Ruby, il est temps de voir un autre type de boucle: la boucle while («tant que»).
Cette boucle est un peu plus intéressante que celle que vous venez de voir. Elle se base sur une condition :
while condition
...
end
Ou condition n'est rien d'autre qu'une expression conditionnelle, comme celles que nous venons d'appréhender précédemment.
II-D-1. Compteur▲
Voici un exemple tout simple, illustrant l'utilisation d'une boucle while :
Analysons le programme.
- Initialisation de compteur à 0.
- Comme compteur est bien inférieur à 10, nous rentrons dans la boucle.
- Dans la boucle, nous affichons un message, et nous incrémentons compteur de 1. Maintenant, compteur vaut 1.
- Comme compteur est toujours inférieur à 10, nous sautons à nouveau dans la boucle.
- …
Le scénario se répétera jusqu'à ce que compteur soit égal à 10. Voici la sortie du programme :
En d'autres mots, une boucle while répétera la boucle tant que la condition sera évaluée comme étant vraie.
II-D-2. Puissance de 2▲
Certaines choses sont faciles à réaliser avec une boucle while, mais moins évidentes avec n.times.
Supposez que nous voulons calculer la plus grande puissance de 2 plus petite que 10000. C'est très facile à programmer avec une boucle while :
Voici ce que ça donne :
Imaginez combien ça aurait été difficile d'arriver au même résultat, en utilisant n.times.
II-D-3. Quelques exercices▲
- Reimplémentez le dernier programme, pour qu'il demande à l'utilisateur une valeur maximale (à la place de 10000). Le programme devra se comporter de cette façon :
- Démarrez le même programme, en y entrant 1e10 comme entrée. Que se passe-t-il ?
Si vous avez utilisé la méthode String#to_i, il y a des chances pour que 1e10 soit converti par le nombre 1. Essayons de comprendre pourquoi dans IRB :
Comme vous pouvez le remarquer, 1e10 est en Float (nombre flottant). Donc, vous devez utiliser la méthode String#to_s.
II-E. Écrire de bons programmes▲
II-E-1. Commentaires▲
Un commentaireest une zone de texte dont chaque ligne est préfixée par le symbole #. Ces lignes seront ignorées par Ruby, donc vous pouvez les utiliser pour écrire des commentaires pour votre usage personnel. Par exemple :
# Calcule la plus grande puissance de 2
# inférieure à 10000.
nombre = 1
while nombre < 10_000
nombre *= 2
end
Les commentaires sont un peu comme des notes personnelles. Simplement pour vous aider à vous souvenir de ce que vous avez écrit.
II-E-1-a. Comment utiliser des commentaires▲
- Écrivez des commentaires pour chaque étape de votre programme. Essayez de les rendre clairs et précis.
- Expliquez toujours ce votre code fait, pas comment il le fait. Si le comment n'est pas évident en lisant le commentaire, alors vous devez réorganiser votre code.
- Dans le doute, il vaut mieux écrire plus de commentaires, que pas assez.
II-E-2. Indentation▲
L'indentation se résume à une mise en page réalisée à l'aide de tabulations ou d'espaces, afin de rendre un code source plus lisible.
Indentez toujours votre code. Il s'agit d'un des principes les plus fondamentaux, que vous devez assimiler si vous désirez produire de bons programmes.
Bien
# Additionne des nombres impairs
nombre, somme = 1, 0
while nombre < 100
# % donne le reste
if nombre % 2 == 1
somme += nombre
end
puts somme
end
Pas bien
# Additionne des nombres impairs
nombre, somme = 1, 0
while nombre < 100
# % donne le reste
if nombre % 2 == 1
somme += nombre
end
puts somme
end
Il existe plusieurs standards en matière d'indentation. En général, les programmeurs utilisent soit une tabulation, soit 2, 4 ou 8 espaces. Choisissez le style qui vous convient le mieux !