Exercice 1
Reprenez l'exercice 6 de la leçon 2, mais cette fois le prénom et le nom seront normalisés de la même façon (toutes les lettres en minuscule sauf la première) par la fonctionnormaliser.
LP
IMApp
Scripts
Clients
Leçon 06
Reprenons le sujet de l'exercice 5 de la leçon 2 et supposons que l'on veuille introduire des tests dans ce petit programme pour s'assurer que les données saisies soient bien des nombres. Le nouveau code ressemble alors ça :
var saisie = prompt( "Nombre de parts par convive ?","" );
while ( isNaN( saisie ) )
saisie = prompt( "Mauvais nombre, recommencez !","" );
var parts_par_convive = Number( saisie );
saisie = prompt( "Nombre de convives ?","" );
while ( isNaN( saisie ) )
saisie = prompt( "Mauvais nombre, recommencez !","" );
var nombre_de_convives = Number( saisie );
saisie = prompt( "Nombre de parts par pizza ?","" );
while ( isNaN( saisie ) )
saisie = prompt( "Mauvais nombre, recommencez !","" );
var parts_par_pizza = Number( saisie );
alert( "Vous devez commander " +
Math.ceil( parts_par_convive * nombre_de_convives / parts_par_pizza ) +
" pizzas" );
Remarquez que dans ce programme, on répète trois fois la même boucle while. Cette répétition est
néfaste pour plusieurs raisons :
function tester() {
while ( isNaN( saisie ) )
saisie = prompt( "Mauvais nombre, recommencez !","" );
}
var saisie = prompt( "Nombre de parts par convive ?","" );
tester();
var parts_par_convive = Number( saisie );
saisie = prompt( "Nombre de convives ?","" );
tester();
var nombre_de_convives = Number( saisie );
saisie = prompt( "Nombre de parts par pizza ?","" );
tester();
var parts_par_pizza = Number( saisie );
alert( "Vous devez commander " +
Math.ceil( parts_par_convive * nombre_de_convives / parts_par_pizza ) +
" pizzas" );
Dans le code précédent, la fonction tester est une nouvelle action disponible dans le programme. Cette action est
définie une fois mais peut être exécutée plusieurs fois. Pour définir une fonction, on utilise le
mot-clef function suivi du nom de la fonction, suivi d'une paire de parenthèses et enfin du corps de la fonction
délimité par deux accolades.
Dans le code précédent, on constate que les trois appels à la fonction tester sont précédés de la même instruction
saisie = prompt(...). Dans ces instruction, seule la chaîne de caractères paramètre de la fonction
prompt change. Puisque ces instructions sont presque identiques, on peut les factoriser en
plaçant l'instruction saisie = prompt(...) dans la fonction tester. La chaîne de caractères paramètre de la
fonction prompt doit changer à chaque appel de la fonction et en conséquence, cette chaîne doit être un
paramètre de la fonction :
function saisir( message ) {
saisie = prompt( message );
while ( isNaN( saisie ) )
saisie = prompt( "Mauvais nombre, recommencez !","" );
}
var saisie;
saisir( "Nombre de parts par convive ?" );
var parts_par_convive = Number( saisie );
saisir( "Nombre de convives ?" );
var nombre_de_convives = Number( saisie );
saisir( "Nombre de parts par pizza ?" );
var parts_par_pizza = Number( saisie );
alert( "Vous devez commander " +
Math.ceil( parts_par_convive * nombre_de_convives / parts_par_pizza ) +
" pizzas" );
Remarquez qu'on a changé le nom de la fonction pour l'adapter à son nouveau rôle : maintenant, la fonction s'appelle saisir
car elle permet de saisir une valeur fournie par l'utilisateur, de tester cette valeur et lorsque cette valeur est un nombre, de l'affecter
à la variable saisie. Bien entendu, le nom d'une fonction peut être absolument quelconque, mais comme pour les variables, il est
important de choisir un nom significatif qui corresponde bien au rôle de la fonction. Maintenant, la fonction saisir a un
paramètre représenté par la variable message placée entre les parenthèses qui suivent le nom de la fonction. Le
paramètre est une information manquante dont la fonction a besoin pour s'exécuter et remplir son rôle. On peut voir le paramètre
comme une variable locale à la fonction : cette variable n'existe que dans le contexte de la fonction, elle est donc inaccessible à
l'extérieur de la fonction (dans le reste du programme). A l'inverse, la variable saisie est une variable globale
pour la fonction, car elle est définie à l'extérieur de la fonction. Une différence notable entre le paramètre message
et la variable globale saisie concerne l'existence même de ces variables :
saisie n'existe qu'en un seul exemplaire, et chaque fois qu'on appelle la fonction, c'est la
même variable que la fonction manipule
message est créé à chaque appel de la fonction et il ne vit que
le temps de l'exécution de la fonction. Il n'y a acun lien ni aucune mémoire entre les différents paramètres message
créés lors des différents appels à la fonction
saisir pour qu'elle
contrôle si son paramètre est bien un nombre, et s'il est compris dans un intervalle donné :
function saisir( message, min, max ) {
saisie = prompt( message );
while ( isNaN( saisie ) || saisie < min || saisie > max )
saisie = prompt( "Mauvais nombre, recommencez !","" );
}
var saisie;
saisir( "Nombre de parts par convive ?", 1, 5 );
var parts_par_convive = Number( saisie );
saisir( "Nombre de convives ?", 2, 10 );
var nombre_de_convives = Number( saisie );
saisir( "Nombre de parts par pizza ?", 4, 6 );
var parts_par_pizza = Number( saisie );
alert( "Vous devez commander " +
Math.ceil( parts_par_convive * nombre_de_convives / parts_par_pizza ) +
" pizzas" );
Remarquez que dans le test de la boucle while, on compare directement la valeur de la variable
saisie (une chaîne de caractères) avec un nombre (les paramètres min et max). Dans cette situation
JavaScript tente de convertir la chaîne de caractères en nombre, ce qui dans ce cas va réussir puisqu'on est sûr que la chaîne est bien
un nombre (pourquoi ?).
En regardant de près l'utilisation de la fonction saisir précédente, on voit qu'elle ne fait qu'affecter la chaîne de
caractères saisie à la variable saisie, après avoir vérifié que cette chaîne était bien un nombre positif. On peut aller plus
loin et donner à la fonction un rôle plus complet et surtout plus abstrait en lui demandant de retourner
le nombre saisi (bien sûr après avoir vérifié la chaîne de caractères saisie par l'utilisateur). Pour celà, la fonction doit maintenant
retourner une valeur, un peu à la façon d'une fonction mathématique comme le sinus. On modifie la fonction et le code de la
façon suivante :
function saisir( message, min, max ) {
var saisie = prompt( message );
while ( isNaN( saisie ) || saisie < min || saisie > max )
saisie = prompt( "Mauvais nombre, recommencez !","" );
return Number( saisie );
}
var parts_par_convive = saisir( "Nombre de parts par convive ?", 1, 5 );
var nombre_de_convives = saisir( "Nombre de convives ?", 2, 10 );
var parts_par_pizza = saisir( "Nombre de parts par pizza ?", 4, 6 );
alert( "Vous devez commander " +
Math.ceil( parts_par_convive * nombre_de_convives / parts_par_pizza ) +
" pizzas" );
Maintenant, la fonction saisir produit une valeur (un nombre) ! Autrement dit, l'appel de la fonction est une
expression qui produit une valeur. Remarquez un point très important : la variable saisie est maintenant
locale à la fonction ! En effet, il n'est plus nécessaire que le programme voit cette variable puisque tout le
processus de saisie, de vérification et de production du nombre est maintenant localisé dans la fonction. La variable saisie
est locale à la fonction car elle est déclarée (à l'aide du mot-clef var) dans le corps de la
fonction.
Les tableaux peuvent être passés en paramètre aux fonctions. Supposons par exemple qu'on désire calculer des moyennes de notes fournies sous
la forme de tableaux de notes (par exemple, un tableau par étudiant). On peut écrire la fonction moyenne suivante :
function moyenne( notes ) {
var somme = 0;
for ( var i = 0; i < notes.length; i++ )
somme += notes[i];
return somme / notes.length;
}
Cette fonction prend en paramètre un tableau contenant des nombres, calcule et retourne le moyenne de ces nombres. Remarquez que grâce à
l'attribut length, on a pas besoin de connaîte effectivement la taille du tableau ! Si on désire utiliser cette
fonction dans un programme qui lit interactivement les notes via la fonction prompt il faut prévoir une
fonction qui convertit des chaînes de caractères stockées dans un tableau en nombres. C'est le rôle de la fonction convertir :
function convertir( chaines ) {
for ( var i = 0; i < chaines.length; i++ )
chaines[i] = Number( chaines[i] );
}
Le paramètre chaines de la fonction convertir est un tableau contenant des chaînes de caractères, chacune d'elle
représentant un nombre. On peut maintenant à l'aide des fonctions chaines et moyenne écrire un programme qui demande
à l'utilisateur d'entrer une suite de notes et qui affiche la moyenne de ces notes :
var chaine = prompt( "Entrez les notes séparées par exactement un espace :",""); var notes = chaine.split( " " ); convertir( notes ); alert( "La moyenne est " + moyenne( notes ) );
Notez que la variable du programme qui recueille le tableau de chaînes de caractères et le paramètre de la fonctionDans cette version, la fonctionmoyenneont le même nom (notes), ce qui bien sûr n'est absolument pas nécessaire : le noms des paramètres d'une fonction peuvent être absolument quelconque et ne font jamais référence à des variables déclarées à l'extérieur de la fonction !
convertir agit sur son paramètre (un tableau) et convertit chaque élément (une chaîne de
caractères) en nombre. Une fonction pouvant retourner un tableau, on peut modifier la fonction convertir de façon
qu'elle :
function convertir( chaines ) {
var notes = [];
for ( var i = 0; i < chaines.length; i++ )
notes.push( Number( chaines[i] ) );
return notes;
}
Dans cette nouvelle version, la variables notes devient locale à la fonction, et contient un nouveau tableau
distinct du tableau paramètre chaines. Avec cette nouvelle version, le programme devient :
var chaine = prompt( "Entrez les notes séparées par exactement un espace :",""); alert( "La moyenne est " + moyenne( convertir( chaine.split( " " ) ) ) );Remarquez que cette dernière version parait très simple, pour peu qu'on dispose des deux fonctions
convertir et
moyenne. On peut imaginer ces fonctions comme faisant partie de JavaScript ou tout au moins d'une librairie de
fonctions utiles qu'on pourrait utiliser au besoin. C'est là le coeur même de l'activité de programmation web : développer des
fonctions générales et utiles qu'on pourra réutiliser dans plusieurs projets !
A partir de cette leçon et pour une grande partie des exercices à venir, un squelette de solutions va vous être proposé. Pour cette leçon, ces squelettes consistent en des fonctions vides dont vous devez comprendre le rôle et que vous devez ensuite compléter. Si un squelette ne vous inspire pas et que vous pensez à une solution différente, vous pouvez bien sûr opter pour votre solution.
Exercice 1
Reprenez l'exercice 6 de la leçon 2, mais cette fois le prénom et le nom seront normalisés de la même façon (toutes les lettres en
minuscule sauf la première) par la fonction normaliser.
Fichier(s)
Exercice 2
Reprenez l'exercice 1 de la leçon 3 en normalisant les prénoms et les noms à l'aide de la fonction normaliser de l'exercice
précédent, et en utilisant la fonction bienvenue pour fabriquer le message de bienvenue.
Fichier(s)
Exercice 3
Reprenez l'exercice 1 de la leçon 5 en utilisant maintenant deux fonctions jour et mois pour retourner
respectivement le nom du jour de la semaine et le nom du mois en fonction d'un entier compris entre 0 et 6 pour le jour, et compris entre
0 et 11 pour le mois. Les fonctions jour et mois retournent une chaîne de caractères adéquate pour signaler que
leur paramètre est erroné.
Fichier(s)
Exercice 4
Reprenez l'exercice 2 de la leçon 2 en utilisant maintenant deux fonctions moyenne et saisirNombre :
la fonction moyenne calcule et retourne la moyenne de ses trois paramètres, et saisirNombre lit la chaÎne de
caractères entrée par l'utilisateur et retourne le nombre correspondant. Tant que la chaîne fournie par l'utilisateur n'est pas un nombre, la
fonction lui demande une nouvelle chaîne.
Fichier(s)
Exercice 5
Reprenez l'exercice 4 de la leçon 3 en rèutilisant les deux fonctions moyenne et saisirNombre de l'exercice
précédent, et en utilsant la fonction appreciation qui retourne l'appréciation adéquate en fonction de la note (son paramètre).
Fichier(s)
Exercice 6
Reprenez l'exercice 4 de la leçon 4 en modifiant la fonction saisirNombre des exercices précédent, et en utilsant la fonction
table qui retourne sous forme d'une chaîne de caractères, la table de mutliplication de son paramètre. La fonction
saisirNombre permet maintenant de saisir un nombre compris dans un intervalle donné et elle a maintenant deux paramètres, les
bornes de cet intervalle.
Fichier(s)
Exercice 7
Reprenez l'exercice 8 de la leçon 4 en modifiant une fois encore la fonction saisirNombre des exercices précédent, et en
utilsant la fonction premier qui teste si son paramètre est un nombre premier. La fonction saisirNombre permet
maintenant de saisir un nombre positif ou nul, et elle n'a plus de paramètre.
Fichier(s)
Exercice 8
Reprenez l'exercice 5 de la leçon 5 en utilisant les fonctions suivantes :
saisirNombre : c'est la même fonction que dans les exercices 4 et 5
premiers : c'est la fonction principale de cet exerice. Elle prend un entier k en paramètre et retourne
les k premiers nombres premiers sous la forme d'un tableau de taille k
pasDivisible : c'est une fonction utilitaire qui est utilisée par la fonction précédente. Elle prend
en paramètre un entier n et un tableau d'entiers (premiers) t et teste si n est divisible
par un des entiers contenus dans t
resultats : c'est une fonction utilitaire qui sert à présenter les nombres premiers calculés. Elle prend
en paramètre un tableau d'entiers (premiers) et retourne une chaîne de caractères présentant la liste de ces entiers à raison
de 10 entiers par ligne
Fichier(s)
Exercice 9
Reprenez l'exercice 4 de la leçon 5. Maintenant, le programme doit afficher, à la demande l'utilisateur, plusieurs tirages successifs.
Pour chaque tirage, le programme doit afficher les 5 numéros du loto triés par ordre croissant. Pour réaliser ce tri,
vous devez utiliser la méthode sort d'une façon spéciale : cette méthode va être appliquée à un tableau
d'entiers et va prendre en paramètre une fonction de comparaison entre ces entiers, qui va être utilisée pour les
comparer entre eux durant le tri. Reportez-vous à la documentation pour comprendre comment utiliser sort
de cette façon.
Fichier(s)
Exercice 10
Reprenez l'exercice 2 de la leçon 4. Maintenant, il est possible de jouer plusieurs parties à la suite : à la fin d'une partie, le programme
demande à l'utilisateur s'il veut en jouer une autre. A la fin du jeu (après que toutes les parties aient été jouées), le programme affiche
des résultats comprenant :
Contrairement aux exercices précédents, aucun squelette n'est fourni pour cet exercice et vous devez le concevoir entièrement. A titre
indicatif, la solution de référence contient quatre fonctions, plus le code du programme principal.