GENISTA (1971) : TUTORIEL "BBC BASIC FOR WINDOWS" EN FRANÇAIS : CHAPITRE 16 : ROUTINES DÉFINIES PAR L'UTILISATEUR : "PROC"



Logo Genista, fondé en 1971

Guide Tutoriel de BBC BASIC for Windows, Ch. 16

BBC BASIC (BB4W) Tutorial: User-Defined Routines: PROC

Routines définies par l'Utilisateur : PROC (Tutoriel BBC BASIC, Ch. 16) [Genista]

Par Peter Nairn  •  Traduction : Guy Schaffner (Texte et images) (Genista)

informatique et programmation Vous avez appris à gérer les données, les variables, les tableaux à plusieurs dimensions, et vous souhaitez augmenter votre capacité à gérer toutes ces données.
Dans ce Chapitre, vous allez apprendre à définir des procédures et à les utiliser, ce qui vous permettra de créer vos propres commandes à l'intérieur d'un programme : c'est de l'automatisation et c'est surtout de la véritable programmation à un niveau déjà avancé.
Chapitre 15   •   Chapitre 16   •   Chapitre 17      

Chapitre 16 — Routines définies par l'Utilisateur : PROC



Nous avons déjà vu qu'il existe des commandes et des fonctions intégrées qui sont la colonne vertébrale du BASIC. On peut citer en exemple CLS, qui nettoie l'écran, et LOG(X) qui renvoie le logarithme de X. Tôt ou tard, au fur et à mesure que les programmes s'allongent, vous réaliserez que vous utilisez plusieurs fois les mêmes lignes de code dans un programme. Cette partie montre comment nous pouvons créer nos propres commandes à partir de ces lignes communes et comment nous pouvons les appeler ensuite à volonté.

BBC BASIC fournit deux méthodes pour faire cela : PROC et FN. Toutes deux permettent d'appeler une routine de la même façon que vous utilisez les commandes natives du BASIC . La différence, c'est que PROC est utilisée comme une commande (elle ne renvoie pas de valeur) alors que FN se comporte comme une fonction et renvoie une valeur que vous pouvez affecter à une expression ou utiliser dans l'expression. Ces différences exceptées, la structure et les règles sont dans une large mesure les mêmes, aussi traiterons-nous de PROC en premier lieu, mais souvenez-vous que beaucoup de ce qui va être dit s'appliquera aussi à FN.

Supposez que vous vouliez vider l'écran et afficher un petit titre au haut de la page. C'est facile, direz-vous, avec deux lignes de code :


      CLS
      PRINT TAB(2);"Guide pratique du BBC BASIC"
    

Eh bien, si nous voulons faire cela plusieurs fois, nous avons le choix entre copier ces lignes à chaque fois, ou bien nous pouvons les inclure dans un bloc de code que nous pourrons appeler chaque fois que nous le voudrons. Voici comment faire :


      REM PROC démonstration
      PROC_NouvelEcran
      INPUT A$
      PROC_NouvelEcran
      END
      
      DEF PROC_NouvelEcran
      CLS
      PRINT TAB(2);"Guide pratique du BBC BASIC"
      ENDPROC
    

Tiens, à propos : PROC signifie « procédure ». Avant qu'une PROC ne puisse être appelée, elle doit être définie. Le début de la définition est signalé par le mot-clé DEF (qui signifie « DEFinir »). La fin est signalée par ENDPROC (sans espace) et tout le code contenu entre les deux s'appelle le corps de la procédure. Quand le programme tourne, il arrive à la ligne 2 et se souvient de l'endroit où il se trouve. Il saute ensuite vers le corps de la PROC qu'il exécute. Lorsqu'il rencontre ENDPROC, il retourne là où il s'était interrompu et continue le programme comme précédemment. La même chose se passe quand il arrive à la ligne 4.

La pratique courante est de placer les définitions de PROC après END, c'est-à-dire après la fin du programme principal, afin que le code de ce programme ne soit pas parsemé de déclarations. Le nom de la PROC suit les conventions pour l'attribution d'un nom aux variables : le premier caractère doit être une lettre ou un souligné (on peut en fait aussi utiliser un chiffre, à la différence des variables) et ensuite, n'importe quels caractères alphanumériques. La première lettre du nom doit suivre le mot PROC, sans aucun espace. C'est une pratique courante, bien que ce ne soit pas obligatoire, de commencer par un souligné, juste pour rendre les choses un peu plus faciles à lire.

Donc, maintenant que nous pouvons afficher notre titre sur l'écran, que se passe-t-il si nous avons des titres différents en fonction de l'écran que nous voulons afficher ? Eh bien, nous pourrions écrire une PROC différente pour chaque écran, mais si nous avons 10 écrans, ça fait beaucoup de code qui est répété en plusieurs exemplaires. « BB4W » nous permet de passer une valeur à une PROC pour que cette PROC l'utilise de toutes les façons qu'elle peut trouver adaptée, aussi pouvons-nous passer un titre différent comme chaîne de texte chaque fois que nous appelons la PROC.


      REM Passer une valeur à une PROC
      PROC_NouvelEcran("Premier écran")
      INPUT A$
      PROC_NouvelEcran("Second écran")
      END
      
      DEF PROC_NouvelEcran(Titre$)
      CLS
      PRINT TAB(2);Titre$
      ENDPROC
    

Quelle en est l'utilité ? Le texte du titre est copié dans une variable de type chaîne nommée Titre$ et on s'en sert ensuite tout au long du corps de la routine, exactement comme si c'était une variable normale. Notez que le contenu de Titre$ n'a de sens que pendant l'exécution de la PROC.

On peut passer à une PROC autant de valeurs que l'on veut ; la règle est qu'une variable doit être du même type que celle de la ligne où elle est déclarée, et les variables doivent apparaître dans le même ordre. Par exemple, voici une variante qui nous permet de spécifier le titre et d'indiquer où il doit apparaître sur la ligne du haut.


      REM Passer une valeur à une PROC
      PROC_NouvelEcran(5, "Premier écran")
      INPUT A$
      PROC_NouvelEcran(10, "Second écran")
      END
      
      DEF PROC_NouvelEcran(Col%,Titre$)
      CLS
      PRINT TAB(Col%);Titre$
      ENDPROC
    

Lorsqu'une variable est passée à une PROC, cette procédure est libre de manipuler la valeur locale de toutes les façons qu'elle le veut. Comme elle travaille avec une copie, la variable originale n'est pas changée. Cette méthode de passer des données s'appelle « appel par valeur ».


      REM Appel par valeur : démonstration
      MaChaine$ = "Bonjour, tout le monde"
      PRINT "Valeur avant PROC ";MaChaine$
      PROC_FaireQuelqueChose(MaChaine$)
      PRINT "Valeur après PROC ";MaChaine$
      END
      
      DEF PROC_FaireQuelqueChose(UneChaine$)
      PRINT "Valeur passée à la PROC ";UneChaine$
      UneChaine$="Adieu, monde cruel"
      PRINT "Valeur après changement ";UneChaine$
      ENDPROC
    

Il y a des cas où nous voulons que la routine fasse quelque chose de permanent au contenu d'une variable. Pour cela, nous utilisons le mot-clé RETURN dans la déclaration de la PROC. Changez la ligne de déclaration et relancez le programme pour voir les effets :


      DEF PROC_FaireQuelqueChose(RETURN UneChaine$)
    

Ceci est nommé un « appel par référence ».

Vous pouvez passer l'intégralité de tableaux et de structures à une PROC, et pas seulement des variables à valeur unique. Pour ce faire, utilisez simplement le nom suivi de parenthèses vides pour indiquer que ce n'est pas une bonne vieille variable quelconque à qui nous avons affaire. Si vous vous souvenez de l'utilisation de DIM pour trouver la taille d'un tableau dans le chapitre sur les tableaux, vous pouvez à présent en voir une utilisation immédiate. Si un tableau est passé, nous pouvons l'utiliser pour vérifier qu'il a le nombre correct de dimensions de la bonne taille. Ceci aide à l'élimination d'erreurs dues au dépassement des limites.


      REM Pour passer un tableau
      DIM TableauInt%(2,3)
      PROC_TailleTablo(TableauInt%())
      END
 
      DEF PROC_TailleTablo(Tableau%())
      PRINT "Ce tableau a ";
      PRINT DIM(Tableau%());" dimensions."
      ENDPROC
    

Les structures n'ont pas de fonction correspondante, aussi vous devez seulement connaître les membres associés à cette structure.


      REM Passer une structure
      DIM MaStruct{A%,B$}
      MaStruct.A%=23
      MaStruct.B$="Vingt-trois"
      PROC_AfficheStruct(MaStruct{})
      END
 
      DEF PROC_AfficheStruct(St{})
      PRINT St.A%
      PRINT St.B$
      ENDPROC
    

Les tableaux et les structures sont toujours passés par référence. Ceci, parce que tableaux ou structures peuvent être volumineux (et il en est fréquemment ainsi), c'est pourquoi on les utilise. En faire une copie complète coûterait cher, à la fois en termes de mémoire et de temps de traitement que cela prendrait pour copier physiquement chaque valeur. Cela signifie que si vous changez une valeur dans des tableaux et des structures qui ont été passés, le changement est permanent.


      REM Passer une structure
      DIM MaStruct{A%,B$}
      MaStruct.A%=23
      MaStruct.B$="Vingt-trois"
      PROC_AfficheStruct(MaStruct{})
      PROC_AugmStruct(MaStruct{})
      PROC_AfficheStruct(MaStruct{})
      END
 
      DEF PROC_AfficheStruct(St{})
      PRINT St.A%
      PRINT St.B$
      ENDPROC 
 
      DEF PROC_AugmStruct(St{})
      St.A%=24
      St.B$="Vingt-quatre"
      ENDPROC
    


Variables de type LOCAL


Savoir que nous pouvons passer des valeurs dans une PROC est une idée très importante ; cela signifie que nous pouvons écrire des routines qui sont portables de programme à programme, aussi lorsque vous aurez testé une routine, vous pourrez la copier dans votre prochain programme, la mettre dans une « bibliothèque » ou la donner à tous vos amis de BBC BASIC sans avoir à la développer à nouveau. Pour faire cela de la façon la plus efficace, nous devons nous assurer que chaque variable utilisée dans la PROC n'est utilisée que dans la PROC, et nulle part ailleurs. On a déjà traité des valeurs passées depuis l'extérieur de la procédure. Ce dont nous avons besoin, c'est une méthode pour que les variables appartiennent uniquement à une routine. Voilà le moment précis où nous vient l'idée de variables locales.

Une variable locale est une variable qui existe au cours de l'exécution du corps d'une procédure et à laquelle on ne peut accéder que pour cette procédure-là. Il existe un mot-clé, indispensable pour que le BASIC sache que la variable doit être traitée comme variable locale, et ce mot, c'est LOCAL. Une variable définie comme locale commence à exister quand une routine est appelée, peut être utilisée n'importe où dans le corps du code et est rejetée quand on sort de la routine. Voyons un exemple, en supposant que nous voulons afficher une rangée de caractères dans notre PROC :


      REM LOCAL démonstration 1
      PROC_EcrisLigne("*")
      END
 
      DEF PROC_EcrisLigne(Car$)
      LOCAL Compteur%
      FOR Compteur% = 0 TO 79
        PRINT Car$;
      NEXT Compteur%
      ENDPROC
    

Les variables locales suivent les conventions des variables normales (globales), en ce qui concerne le nom et les types de définitions.

Vous pouvez aussi déclarer des tableaux et des structures en tant que LOCAL, mais une instruction DIM supplémentaire est indispensable pour y parvenir :


      REM Tableau LOCAL
      PROC_A
      END
 
      DEF PROC_A
      LOCAL MonTableau%()
      DIM MonTableau%(10)
      REM Faire quelque chose...
      ENDPROC
    

L'instruction LOCAL dit ici au BASIC qu'il lui faudra réserver de la place pour un tableau ; la ligne suivante avec le DIM lui donne la taille. Les structures LOCAL se font de la même manière :


      REM Structure LOCAL
      PROC_A
      END
 
      DEF PROC_A
      LOCAL MaStruct{}
      DIM MaStruct{a%,b,c$}
      REM Faire quelque chose...
      ENDPROC
    


Variables PRIVATE


Une fois que vous êtes familiarisé avec les variables LOCAL, les variables PRIVATE deviennent faciles à comprendre. Une variable PRIVATE se déclare de la même façon qu'une variable LOCAL, mais elle utilise le mot-clé PRIVATE pour sa définition. Elle est valide au cours de l'exécution d'une routine, mais pas à l'extérieur, tout comme une variable LOCAL. La différence, c'est qu'une variable PRIVATE n'est pas oubliée lorsqu'une procédure se termine : sa valeur est maintenue en mémoire et réutilisée la prochaine fois que la routine est appelée.


      REM Variable PRIVATE
      PRINT "Premier appel"
      PROC_A
      PRINT "Second appel"
      PROC_A
      END
 
      DEF PROC_A
      PRIVATE MonEnt%
      PRINT "Valeur de MonEnt% = ";MonEnt%
      MonEnt%=MonEnt% + 100
      ENDPROC
    

Au premier passage, l'entier MonEnt% est créé et mis à zéro ; la valeur est affichée pour le contrôle. MonEnt% est ensuite augmenté de 100. Au deuxième appel de PROC_A, MonEnt% a une valeur retenue de l'appel précédent, et ceci est révélé par le nouvel affichage de la valeur par la PROC.



Portée (ou « Scope »)


Jusqu'à la rencontre de variables locales et privées, toutes les variables étaient accessibles n'importe où à l'intérieur du programme : on les appelle variables « globales ». On peut accéder aux variables globales à tout endroit du programme, même après avoir fini de le découper en sections plus faciles à gérer avec PROC et FN. Si vous déclarez une variable dans une routine sans d'abord dire au BASIC si elle sera locale ou privée, cette variable sera globale, comme toutes les autres. Les programmeurs (auxquels vous appartenez maintenant) appellent « portée » (ou, comme en anglais, « scope ») cette « visibilité d'une variable », probablement parce que c'est plus facile à dire. Lorsqu'une variable n'est pas visible, on dit qu'elle est « hors de portée » (« out of scope »).




Exercices


16.1
Modifiez la PROC_NouvelEcran pour qu'elle accepte une couleur d'arrière-plan et une couleur de premier plan.

16.2
Écrivez et testez PROC_PlusGrand(A%,B%) qui compare A% et B%.
• Si A% > B%, ne faites rien ;
• si B% > A%, échangez les deux variables en vous servant d'une variable locale. Il vous faudra passer par référence pour que le programme d'appel puisse afficher les résultats.



Fin du Chapitre 16





Haut de Page  •  [Top of Page]

Page suivante (Ch. 17)  •  [Next Page (Ch. 17)]

Page précédente (Ch. 15)  •  [Previous Page (Ch. 15)]

Page d'entrée : BASIC, BBC BASIC et BB4W  •  [BASIC, BBC BASIC and BB4W  Entry Page]

Début du Guide pratique du BBC BASIC  •  [The Beginning of the BBC BASIC Tutorial]

Autres sujets  •  [Other subjects]