|
Site |
Cours VB.net |
|
|
|
Programmation fonctionnelle: l'IMC. |
|
|
Ce chapitre permet de 'réviser' pas mal de notion.
Qu'est ce que l'IMC?
L'index de masse corporelle est très utilisé par les médecins. Il est calculé à partir du poids et de la taille:
IMC=Poids/(Taille*Taille) (avec Poids en Kg, Taille en mètres)
Cela permet de savoir si le sujet est
maigre (IMC<18.5)
normal (IMC idéale=22)
en surpoids (IMC>25)
obèse (IMC>30).
On peut calculer le poids idéal par exemple PI= 22* T*T
Nous allons détailler ce petit programme:
Quel est le cahier des charges du programme?
L'utilisateur doit pouvoir:
Saisir un poids, une taille, cliquer sur un bouton 'Calculer'
Les routines doivent:
Vérifier que l'utilisateur ne fait pas n'importe quoi.
Calculer et afficher les résultats: l'IMC mais aussi, en fonction de la taille, le poids idéal, les poids limites de maigreur, surpoids, obésité.
Création de l'interface
Il faut 2 zones de saisie pour saisir le poids et la taille:
On crée 2 'TextBox' que l'on nomme
TexBoxPoids
TextBoxTaille.
On laisse la propriété Multiline à False pour n'avoir qu'une ligne de saisie.
Pour afficher les résultats , on crée 5 'label' les uns sous les autres. (Pour aller plus vite et que les labels soient de la même taille, on en crée un puis par un copier et des coller, on crée les autres)
labelImc 'pour afficher l'Imc
labelPi 'pour afficher le poids idéal
labelM 'pour afficher le poids limite de la maigreur.
labelS 'pour afficher le poids limite du surpoids
labelO 'pour afficher le poids limite de l'obésité.
Ensuite on ajoute des labels devant et derrière chaque TextBox pour indiquer devant, ce qu'ils contiennent et derrière, l'unité.
On ajoute 2 boutons:
ButtonCalcul ayant pour propriété Text= "&Calculer"
ButtonQuitter ayant pour propriété Text= "&Quitter"
Cela donne:
Pour faire beau:
La propriété Text de la fenêtre contient "Calcul IMC", pour afficher cela dans la barre de titre.
La propriété ForeColor de labelImc est en rouge.
La propriété BorderStyle des labels a la valeur 'Fixed3d' ce qui rend les bords visibles.
Ajout du Code
La procédure évènement Form1_Load qui se déclenche lorsque la fenêtre se charge initialise les zones d'affichage en les vidant:
Sub Form1_Load(..)Private
TextBoxTaille.Text = ""
TextBoxPoids.Text = ""
LabelImc.Text = ""
LabelPi.Text = ""
LabelM.Text = ""
LabelS.Text = ""
LabelO.Text = ""
End Sub
La procédure ButtonCalcul_Click qui se déclenche lorsque l'utilisateur clique sur le bouton 'Calculer' contient le code principal.
Voici la totalité du code, on le détaillera dessous.
Sub ButtonCalcul_Click(..)Private
Dim sPoids As Single 'Variable Single contenant le poids
Dim sTaille As Single 'Variable Single contenant la taille'******Controle de validité des entrées************
'Les valeurs saisies sont-elles numérique? If Not (IsNumeric(TextBoxTaille.Text)) ThenMsgBox("Entrez une valeur numérique pour la taille")
Exit Sub End If If Not (IsNumeric(TextBoxPoids.Text)) ThenMsgBox("Entrez une valeur numérique pour le poids")
Exit Sub End If'Convertir les textes saisis en single
' et les mettre dans les variablessTaille =
CType(TextBoxTaille.Text, Single) / 100sPoids =
CType(TextBoxPoids.Text, Single)'Les valeurs saisies sont-elles cohérentes?
If sTaille < 0.50 Or sTaille > 2.50 ThenMsgBox("Entrez une taille valide")
Exit Sub End If If sPoids < 20 Or sPoids > 200 ThenMsgBox("Entrez un poids valide")
Exit Sub End If'Effectuer les calculs et afficher les résultats.
LabelImc.Text = (Math.Round(sPoids / (sTaille * sTaille), 2)).ToString
LabelPi.Text = (Math.Round(22 * (sTaille * sTaille), 2)).ToString
LabelM.Text = (Math.Round(18.5 * (sTaille * sTaille), 2)).ToString
LabelS.Text = (Math.Round(25 * (sTaille * sTaille), 2)).ToString
LabelO.Text = (Math.Round(30 * (sTaille * sTaille), 2)).ToString
End Sub
Détaillons:
Quelles sont les différentes étapes?
On déclare les variables.
On vérifie que ce qui a été tapé est numérique.
On convertit le texte qui est dans la TextBox en Single
On teste si les valeurs de poids et taille sont cohérentes.
On fait le calcul et on affiche.
Déclaration de variables.
Dim sPoids As Single 'Variable Single contenant le poids
Dim sTaille As Single 'Variable Single contenant la tailleCe sont des variables 'privées' propre à la procédure (utilisation de Dim ou Private).
Contrôle de validité:
L'utilisateur est sensé taper un poids et une taille puis cliquer sur le bouton 'Calculer'. Mais il ne faut absolument pas lui faire confiance: il a peut-être oublié de taper le poids ou a donner une taille=0 (l'ordinateur n'aime pas diviser par 0!!), il a peut-être fait une faute de frappe et tapé du texte!!..
Donc il faut tester ce qui a été tapé, s'il y a erreur, on prévient l'utilisateur avec une 'MessageBox' puis on sort de la routine par (Exit Sub )sans effectuer de calcul.
Ici par exemple, on teste si le texte saisi dans la zone taille n'est pas numérique:
If Not (IsNumeric(TextBoxTaille.Text)) ThenMsgBox("Entrez une valeur numérique pour la taille")
Exit Sub End If
Amélioration: On aurait pu automatiquement effacer la valeur erronée et placer le curseur dans la zone à ressaisir:
If Not (IsNumeric(TextBoxTaille.Text)) Then
MsgBox("Entrez une valeur numérique pour la taille")
TextBoxTaille.Text=""
TextBoxTaille.Select()
Exit Sub End If
Conversion:
Si le texte est bien 'Numéric', on fait la conversion en réel simple précision (Single)
sTaille = CType(TextBoxTaille.Text, Single) / 100
On utilise CType pour convertir une String en Single.
On divise taille par 100 car l'utilisateur à saisi la taille en centimètre et les formules nécessitent une taille en mètre.
Problème du séparateur décimal dans les saisies.
Pourquoi saisir la taille en Cm? c'est pour éviter d'avoir à gérer le problème du séparateur décimal.
Si la taille était saisie en mètre, l'utilisateur aurait-il tapé "1.75" ou "1,75"?
On rappelle que pour convertir un texte en Single VB accepte le point et pas la virgule.
Pour ma part, si j'avais demandé de saisir des mètres, voici ma solution: j'ajouterais en début de routine une instruction transformant les ',' en '.':
TextBoxTaille.Text = Replace(TextBoxTaille.Text, ",", ".")
Faire les calculs et afficher les résultats.
Je fais le calcul:
sPoids / (sTaille * sTaille)
J'arrondis à 2 décimales après la virgule grâce à Math.Round( ,2):
Math.Round(sPoids / (sTaille * sTaille), 2)
Je convertis en String:
(Math.Round(sPoids / (sTaille * sTaille), 2)).ToString
J'affiche dans le label 'labelImc':
LabelImc.Text = (Math.Round(sPoids / (sTaille * sTaille), 2)).ToString
(J'aurais pu aussi ne pas arrondir le calcul mais formater l'affichage pour que 2 décimales soient affichées)
La procédure ButtonQuitter_Click déclenchée quand l'utilisateur clique sur le bouton 'Quitter' ferme la seule fenêtre du projet (c'est Me , celle où on se trouve), ce qui arrête le programme.
Private
Sub ButtonQuitter_Click()Me.Close()
End Sub
Structuration:
Ici on a fait simple: une procédure évènement calcule et affiche les résultats.
On pourrait, dans un but didactique 'structurer' le programme.
On pourrait découper le programme en procédure.
Une procédure (une fonction) faisant le calcul.
Une procédure (une fonction) affichant les résultats.
Si plusieurs procédures utilisent les mêmes variables il y a dans ce cas 2 possibilités:
Mettre les variables en 'Public' dans un module Standard.
Utiliser des variables privées et les passer en paramètres.
Première solution: Variables 'Public'
Créer dans un module standard des variables 'Public' pour stocker les variables Poids et Taille, résultats (Public sIMC A Single par exemple),créer dans ce même module standard une procédure Public nommée 'Calculer' qui fait les calculs et met les résultats dans les variables 'Public'; enfin dans le module de formulaire créer une procédure 'AfficheResultat' affichant les résultats.
Module standard:
'Déclaration de variables Public
Public sPoids As Single
Public sTaille As Single
Public sIMC A Single
..
'Procedure Public de calcul
Public Sub Calculer
sIMC=Math.Round(sPoids / (sTaille * sTaille), 2)
...
End Sub
Module de formulaire Form1:
'Procédure évènement qui appelle les divers routines
Private Sub ButtonCalculer_Click
...
sTaille = CType(TextBoxTaille.Text, Single) / 100
Calculer() 'Appelle la routine de calcul
AfficheResultat() 'Appelle la routine d'affichage
End Sub
'routine d'affichage toujours dans le formulaire
Private Sub AfficheResultat()
LabelImc.Text = sIMC.ToString
...
End Sub
On voit bien que la routine de Calcul est générale et donc mise dans un module standard et d'accès 'Public', alors que la routine d'affichage affichant sur Form1 est privée et dans le module du formulaire.
Seconde solution: Variables 'Privées' et passage de paramètres
On peut ne pas créer de variables 'public' mais créer des fonctions (CalculIMC par exemple) à qui on passe en paramètre le poids et la taille et qui retourne le résultat du calcul. Une procédure AfficheResultatIMC récupère en paramètre la valeur de l'IMC à afficher.
Module standard:
'Pas de déclaration de variables Public
..
'Function Public de calcul: reçoit en paramètre le poids et la taille
'retourne l'Imc
Public Function CalculerIMC (T as Single, P As Single) As Single
Return Math.Round(P / (T*T), 2)
End Sub
Module de formulaire Form1:
'Procédure évènement qui appelle les divers routines
Private Sub ButtonCalculer_Click
...
sTaille = CType(TextBoxTaille.Text, Single) / 100
'Appelle de la routine calcul avec l'envoie de paramètres sPoids et sTaille
'Au retour on a la valeur de L'imc que l'on envoie à la routine d'affichage.
AfficheResultatIMC(CalculerIMC(sTaille, sPoids)) 'Appelle la routine d'affichage
End Sub
'routine d'affichage
Private Sub AfficheResultatIMC(I As Single)
LabelImc.Text = i.ToString
End Sub
Remarque:
La ligne AfficheResultatIMC(CalculerIMC(sTaille, sPoids))
est équivalente à:
Dim s As single
s=(CalculerIMC(sTaille, sPoids)
AfficheResultatIMC(s))
mais on se passe d'une variable temporaire.
Conclusion:
Faut-il travailler avec des variables Public ou passer des paramètres?
Réponses:
Les savants disent qu'il faut éviter les variables Publics. Toutes les routines ayant accès à ces variables, il est toujours possible qu'une routine modifie une valeur sans qu'on le sache!!
Utiliser donc des variables le plus privées possible.
(on y reviendra)
|
|
|
|
|