Banière du site

[koala01.free.fr]->Tutoriaux->Principes de Programmation ->Le nassi-chneiderman

Image d'imprimante   image d'enveloppe

10.1 Principe de base

En nassichneideman, on considère que tout ce que l'on peut programmer n'est jamais qu'une action, ou même, plutôt, une procédure ou une fonction.

Après tout, quel que soit le langage de programmation utilsé, chaque instruction n'est le plus souvent qu'une procédure ou qu'une fonction fournie par le langage…

Pour représenter une action, on la mettra simplement dans un rectangle.

Les actions seront "empilées" les unes sur les autres dans l'ordre logique d'exécution, et regroupées entre elles par une "pince" représentant la routine créée par vous.

Le nom de la routine que vous créez prendra place dans la partie supérieure de la pince.

principe de base du nassichneiderman

Principe de base du nassichneideman

Evidemment, comme il n'y a plus rien pour différencier visuellement une action d'une autre, il s'agira de mettre à chaque fois le genre d'action à effectuer.

Si je devais transformer le premier flowchart que je vous ai présenté en nassichneiderman, il ressemblerait à peu près à ceci:

Première représentation du nassichneiderman du calcul de la surcace d'un disque

Première représentation du nassichneiderman du calcul de la surface d'un disque

Et, bien sûr, il est toujours intéressant de prévoir un tableau récapitulatif des variables utilisées

Tableau des varaibles utilisée
Nom Type

Utilisation

Rayon Entier Variable destinée à recevoir la valeur du rayon du disque
Surface Réel Variable destinée à recevoir la valeur de la surface du disque

Je vous l'accorde aisément, c'est largement moins visuel que le flowchart…

Cependant, comme je vous l'ai dit, un programme est rarement aussi rectiligne, ne serait-ce parce qu'il y a sans doute des alternatives, des traîtements répétitifs etc…

fleche haut

10.2 Les boucles

Une boucle est un tronçon de code qui se répète en fonction du résultat d'un test, donc, en définitive, en fonction de la valeur d'une donnée.

Nous nous sommes appeçu à la page précédente que le flowchart souffrait de ceraines insuffisances pour les boucles.

C'est justement l'un des domaines dans lequel le nassichneiderman prend l'avantage sur le flowchart.

Le moment où le test s'effectue pour décider de rentrer dans la boucle ou non permet de classer les boucles:

La différence entre les deux vous sera présentée dans les chapitres suivants.

fleche haut

10.3 Les boucle «jusque»

Comme le test qui permet de décider de rentrer dans la boucle s'effectue après que les actions de la boucle aient été effectuées la première fois, nous serons sûr, en utilisant ce type de boucle, que son contenu aura été effectué au minimum une fois.

Pour représenter ce type de boucle, nous créerons un "couloir" vertical qui descendra jusqu'au test en vue de déterminer s'il faut réeffectuer la boucle à gauche de toutes les actions qui devront être reprises dans la boucle.

Après la dernières instruciton de la boucle, nous mettrons la condition de sortie, éventuellement précédée éventuellement du terme "jusque "

Le shéma de principe des boucle jusque se représente comme suit:

shéma de principe d'une boucle «jusque»

shéma de principe d'une boucle «jusque»

Action1 représentant l'ensemble des actions à effectuer AVANT d'entrer dans la boucle, Action2 et Action3 représentant l'ensemble des actions à effectuer DANS la boucle, et Action4 représentant l'ensemble des actions à effectuer APRES avoir quitté la boucle.

Condition devra être un test logique, éventuellement complexe, dont le résultat global ne puisse être que «vrai» ou «faux»

NOTA:

Il est intéressant de noter, au sujet de condition, que si on a tendance à écrire naturellement une condition qui fera quitter la boucle, la plupart des langages de programmation utiliseront le test pour déterminer si ils doivent retourner dans la boucle…

Il faudra donc faire particulièrement attention, lors de la traduction en code source, à inverser si besoin est la condition, de manière à ce que la boucle soit effectivement quittée quand la condition pour le faire est remplie…

fleche haut

10.4 Les boucles «Tant Que»

Le but de ce genre de boucle est de vérifier AVANT l'exécution des instructions comprises dans la boucle si elles doivent ou non être effectuées.

Il s'en suit que, si la condition pour rentrer dans la boucle ne sont pas remplies au départ, la boucle ne sera même pas effectuée une seule fois.

La représentation de ce genre de boucle en nassichneiderman est sensiblement identique à celle utilisée pour la création de boucles «jusque», si ce n'est que la condition se trouvera AVANT les instructions comprises dans la boucle.

Evidemment, si on décide de mettre un terme avant la condition, on mettra "Tant" (ou "Tant que") au lieu de "Jusque"…

Le shéma de principe de la boucle tant que se représente donc ainsi:

shéma de principe d'une boucle «TANT QUE»

shéma de principe d'une boucle «TANT QUE»

Action1 représentant l'ensemble des actions à effectuer AVANT d'entrer dans la boucle, Action2 et Action3 représentant l'ensemble des actions à effectuer DANS la boucle, et Action4 représentant l'ensemble des actions à effectuer APRES avoir quitté la boucle.

Condition devra être un test logique, éventuellement complexe, dont le résultat global ne puisse être que «vrai» ou «faux»

NOTA:

La plupart des langages de programmation décident de rentrer dans la boucle si la condition est remplie, ce qui correspond ici parfaitement à ce que l'on aurait tendance à écrire naturellement.

Il n'y a donc absolument pas lieu, lors de la traduction en code source, d'inverser la condition

Il existe dans la plupart des langages de programmation une spécialisation de ce type de boucle, il s'agit de:

fleche haut

10.5 La boucle incrémentale ou boucle «Pour»

Il est en effet souvent utile de pouvoir effectuer une boucle un nombre précis, et bien souvent déterminé à l'avance, de fois et de disposer pour l'occasion d'un compteur incrémenté (ou décrémenté) automatiquement.

Ce rôle est joué par un type particulier de boucles: les boucle «Pour»

Comme ce type de boucle est basé sur les boucle "Tant Que", il n'y a rien d'étonnant à ce que leur représentation en nassichneiderman soit identique à celle des boucles "Tant Que", à ceci près que le texte qui les accompagne sera un peu modifié:

Il s'agit en effet de disposer d'une variable servant de "compteur", d'indiquer une valeur de départ, une valeur d'arrivée et, éventuellement d'un pas d'incrémentation (ou de décrémentation)

Le texte à insérer dans le nassichneidermant sera donc du genre de "Pour variable= Valeur de départ à valeur d'arrivée (par pas de valeur du pas)

Voici, pour la compréhension, le shéma de principe de sa représentation:

schéma de principe d'une boucle «Pour»

schéma de principe d'une boucle «Pour»

Action1 représentant l'ensemble des actions à effectuer AVANT d'entrer dans la boucle, Action2 et Action3 représentant l'ensemble des actions à effectuer DANS la boucle, et Action4 représentant l'ensemble des actions à effectuer APRES avoir quitté la boucle.

Variable sera à remplacer par le nom de la variable que vous avez choisi pour votre compteur, 1 étant la valeur de départ (éventuellement modifiable), XX étant la valeur "de sortie de la boucle", et YY étant la valeur du "pas d'incrémentation", au cas où vous souhaitez que le compteur ne soit pas incrémenté de 1

fleche haut

10.6 Les boucles sont interchangeables

En effet, comme je vous l'ai déjà dit et répété (et comme je le répéterai sans doute encore souvent), il n'y a pas de mauvaise manière de raisonner, pour autant que le raisonnement soit logique…

Tout au plus, vous vous rendrez compte qu'un raisonnement sera peut être plus ou moins efficace qu'un autre, peut être plus ou moins adapté à une situation donnée qu'un autre.

De cette manière, si vous souhaitez créer une boucle incrémentale, effectuée dix fois, le plus «logique» (ou du moins, à mon point de vue, et selon les circonstances) *semble* être l'utilisation d'une «Boucle Pour»…

Cependant, rien n'empêche à priori d'utiliser un autre type de boucle… Si ce n'est qu'il s'agira peut-être de concevoir l'ensemble de la boucle de manière différente.

Le "langage imaginaire" que j'ai mis au point pour ce tutorial dispose bien évidemment des trois types de boucles:

Pour créer une boucle "Pour", il utilisera fatalement l'instruction Pour (variable=valeur à valeur_maximale [éventuellement par pas de XX])

Pour créer une boucle "Tant" , il utilisera fatalement l'instruction Tant_Que (condition de rentrée dans la boucle)

Et, pour créer une boucle "Jusque", il utilisera fatalement l'instruction Jusque (condition de rentrée dans la boucle)

Evidemment, le bloc d'instructions à effectuer dans la boucle sera à mettre entre accolades "{ }"

Les instructions Pour(...) et Tant_Que(...) apparaîtront logiquement AVANT le bloc d'instructions à effectuer dans la boucle, alors que l'instruction Jusque(...) apparaîtra APRES le bloc d'instruction à effectuer dans la boucle.

Cela nous donne logiquement quelque chose ressemblant à:

vide principal(vide)
{
    instruction hors boucle
	pour (variable=1 à 10)
	{
	    //les instructions à effectuer dans la boucle pour
	}
	instuction hors boucle
	Tant_Que (test)
	{
	    //les instructions à effectuer dans la boucle tant
	}
	instruction hors boucle
	{
	    //les instructions à effectuer dans la boucle jusque
	} Jusque (test)
}

fleche haut

10.7 Comparons les nassichneiderman

Pour bien vous prouver que les boucles sont dans une large mesure interchangeable, voici la comparaison de la création d'une boucle incrémentale effectuée 10 fois, ainsi que la traduction dans mon langage imaginaire…

Pour rajouter à la vraissemblance, je vais même aller jusqu'à incérer cela dans un projet complet:

Le but de ce projet est tout simplement d'afficher la table de multiplication (entre 1 et 10) d'un nombre (entier) introduit par l'utilisateur.

Je vais donc, logiquement, commencer par énoncer le problème exactement de la manière présentée à la page "un peu de méthode"

fleche haut

10.8 Les trois possibilités…

comparaison des trois boucles

comparaison des trois boucles

fleche haut

10.9 … les codes que ca donne

Le code obtenu avec la boucle "Pour"
vide principale(vide)
{
//Le code obtenu pour la boucle pour
    Affich "Introduisez un nombre "|
    Aquiere Nombre|
    Pour (cpt=1 à 10)
    {
        Affich Nombre" X "cpt" = "nombre*cpt|
    }
}
Le code obtenu avec la boucle "Tant"
vide principale(vide)
{
//Le code obtenu pour la boucle Tant
    Affich "Introduisez un nombre "|
    Aquiere Nombre|
    cpt=1|
    Tant_Que (cpt<11)
    {
        Affich Nombre" X "cpt" = "nombre*cpt|
    }
}
Le code obtenu avec la boucle "Jusque"
vide principale(vide)
{
//Le code obtenu pour la boucle Jusque
    Affich "Introduisez un nombre "|
    Aquiere Nombre|
    cpt=1|
    faire
    {
        Affich Nombre" X "cpt" = "nombre*cpt|
    } Jusque(cpt<10)
}

fleche haut

10.10 … Et les différences

Du point de vue même du résultat, Les trois codes fourniront quelque chose d'exactement semblable.

Par contre, il y aura des différences essentielles sur la manière dont le résultat sera obtenu:

La boucle pour sera d'office effectuée un nombre précis de fois.  Que l'on modifie la valeur de départ et/ou la valeur d'arrivée, et nous serions en mesure d'avoir par exemple, la table de multiplication entre 35 et 100.

La boucle tant quant à elle, est parfaitement susceptible de ne jamais être effectuée.

Si on avait oublié de donner une valeur permettant de rentrer dans la boucle à la variable cpt (qui sert de compteur de boucle), elle ne se serait jamais exécutée.

De plus, si on avait oublié de faire s'incrémenter le compteur à l'intérieur de la boucle, on aurait pu laisser tourner l'application jusqu'à la fin des temps, elle n'aurait jamais été quitée.

Enfin, la boucle jusque se serait effectuée, quoi qu'il arrive, au minimum une fois, quelle qu'aurait pu être la valeur de départ de cpt.

Là encore, si on n'avait pas pris la précaution d'augmenter la valeur de cpt à l'intérieur de la boucle, mais en ayant quand meme donné une valeur susceptible de faire se réexécuter la boucle à cpt, elle se serait effectuée jusqu'à la fin des temps (ou, du moins, juqu'à ce que l'utilisateur décide de mettre fin de lui même à l'application).

fleche haut

10.11 Les Tests

Deux types de tests sont généralement disponibles avec les langages de programmation de troisème génération.

On trouve en effet la possiblité de créer des tests logiques, dont le résultat ne pourra être que «vrai» ou «faux», qui sont représentables en flowchart, que je nommerai logiquement «Test vrai/ faux» au long de ce tutorial, et celle de créer des tests en fonction de la valeur d'un variable précise, qui, bien que représentables en flowchart, ne permettent pas une traduction intuitive, que je nommerai «test à choix multiple» au long de ce tutorial.

fleche haut

10.12 les tests «vrai /faux»

La représentation d'un test de type vrai/faux est relativement simple:

on indique le test au centre de son rectanble, et on trace une ligne oblique au départ des deux coins supérieurs du rectangle de manière à ce qu'elles se rejoingent en bas du rectangle.

représentation d'un test vrai faux

représentation d'un test vrai faux

Nous obtiendrons alors la représentation de deux colones, dans lesquelles nous mettrons d'un côté les instructions à suivre si le test est vérifié, et de l'autre les instructions à suivre s'il ne l'est pas.

Encore une fois, nous tâcherons d'écrire le test de manière à ce que la plus grande partie des instructions soient à effectuer si le résultat est "vrai".

Evidemment, rien n'empeche de faire varier les largeurs de colones selon les besoins…

On peut donc parfaitement envisager de laisser une très petite colone "N" si aucune instruction ne doit être effectuée dans le cas où le résutat du test serait "faux:

Représentation d'un test «vrai faux» sans instructions dans la partie «faux»

Représentation d'un test «vrai faux» sans instructions dans la partie «faux»

fleche haut

10.13 Les tests «à choix multiples»

En flowchart, si on souhaite faire effectuer des actions différentes en fonction de la valeur d'une variable, on est obligé de faire un test sur chaque valeur différente envisagée pour la variable dans le genre de

représentation d'un test à choix multiple en flowchart

représentation d'untest à choix multiple en flowchart

Ce qui, lors de la traduction intuitive en code source pourrait très facilement se transformer en

si (Variable=1)
{
     //instructions à suivre si Variable vaut 1
}
Sinon
{
    si (Variable=2)
	{
            //instructions à suivre si Variable vaut 2
	}
	sinon
	{
	    si (Variable=3)
		{
            //instructions à suivre si Variable vaut 3
		}
		sinon
		{
            si (Variable=4)
			{
			     //instructions à suivre si Variable vaut 4
			}		     
		}
	}
}

Code qui, il faut en convenir, n'est ni des plus lisibles ni le plus efficace.

En nassichneiderman, nous indiquerons la variable à tester à droite, précédé ou non du terme "Selon".

Nous tracerons ensuite la diagonale entre le coin supérieur gauche et le coin inférieur droit de la cellule actuelle et créerons autant de colones que de valeurs envisagées pour la variable.

Il ne restera plus qu'à mettre en "titre" des colones les valeurs à prendre en compte pour chaque colone d'instructions et à mettre les instructions à effectuer dans la colone correspondant à la valeur concernée de la variable.

Typiquement, la dernière colone à droite servira aux instuctions à effectuer par défaut, c'est à dire à effectuer si la variable n'avait aucune des valeurs envisagées.

Cela nous donne quelque chose ressemblant à

reprézentation d'un test à valeur multiples en nassichneiderman

reprézentation d'un test à valeur multiples en nassichneiderman

Intuitivement, nous serons alors tentés d'utiliser les capacités du langage de troisième générations offertes par les tests à choix multiple:

Le langage de programmation que j'ai mis au point pour ce tutorial permet évidemment la gestion de ces test à choix multiple:

Pour indiquer la variable dont on veut vérifier la valeur, il utilise logiquement l'instruction Selon (variable_à_tester).

Pour indiquer la valeur prévue, il utilise l'instruction cas valeur_prévue, et, pour indiquer les instruction à effectuer par défaut (dans le cas où la variable n'aurait aucune des valeurs prévues), il utilisera simplement le terme "defaut", à chaque fois suivie des deux points ":" .

Enfin, pour indiquer au langage qu'il ne doit pas continuer le traitement, nous pouvons à tout moment utiliser l'instruction arret.

Intuitivement, les deux nassichneiderman seraient donc traduits en code source de la même manière, à savoir:

nom_de_la_procedure
{
    Selon (nom_de_la_variable)
    {
        cas valeur1:
            Instru1|
            Instru2|
            arret|
        cas valeur2:
            Instru3|
            arret|
        cas valeur3:
            Instru4|
            Instru5|
            arret|
        cas valeur4:
            Instru6|
            Instru7|
            Instru8|
            arret|
        defaut:
            //dans l'exemple présent, je n'ai prévu aucune instruction 
            //par défaut mais elles se trouveraient ici
    }
}

fleche haut

10.14 Les routines personnalisées

Le terme routine est un terme parfaitement générique qui représente un sous programme appelable à partir de n'importe quel point de l'application, et dont vous trouverez les explications sur la page consacrée aux routines.

Toutes les instructions des différents langages de programmation ne sont que des routines (des fonctions ou des procédures, précisément) mais il est souvent utile d'avoir recours à des routines personnalisées afin de ne pas être obligé de réécrire un code réutilisé à chaque fois que son usage est requis.

Pour faire la différence entre les instructions classiques du langage de programmation et les routines que nous aurons créées nous même, nous centrerons l'appel à nos routines personnalisées et nous créerons des carrés grisés à gauche et à droite selon le principe suivant:

Représentation de l'appel à une routine en nassichneiderman

Représentation de l'appel à une routine en nassichneiderman

image d'imprimante   image de mail   fleche haut

Evaluation donnée par les visiteurs
Cette page a été évaluée 27 fois et a obtenu une moyenne de compréhensible, sans plus
Mon appréciation sur la compréhensibilitéde cette page est:
  • incompréhensible
  • mal expliquée
  • compréhensible, sans plus
  • bien expliquée
  • très bien expliquée

fleche haut

[koala01.free.fr]->Tutoriaux->Principes de Programmation ->Le nassi-chneiderman

Copyright (©) 2005 (Philippe Dunski)

Ce cours est libre, vous pouvez le redistribuer et/ou le modifier selon les termes de la Licence Publique Générale GNU publiée par la Free Software Foundation (version 2 ou bien toute autre version ultérieure choisie par vous).

Ce cours est distribué car potentiellement utile, mais SANS AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la Licence Publique Générale GNU pour plus de détails.

Cependant, l'auteur apprécierait grandement que vous lui fassiez part de toute modification apportée à son contnu

Vous pouvez le contacter par mail à l'adresse koala01@free.fr

Vous pouvez trouver une adaptation française de la licence GNU/GPL à l'URL http://www.linux-france.org/article/these/gpl.html