Découvrir FBSL - gedd123.free.frgedd123.free.fr/Fbsl/Tutoriel.pdf · Chapitre 1. Les bases Ce...

62
Découvrir FBSL Découvrir FBSL par un débutant pour les débutants par un débutant pour les débutants FBSL (Freestyle Basic Script Language) © 2001-2008 by Gerome GUILLEMIN, Mehdi BOUAZIZ and Mike LOBANOVSKY Sommaire Introduction 1. Les bases Premiers pas Calculer avec FBSL 2. Données et variables Affectation ou assignation Afficher la valeur d'une variable Ré-affectation Affectations multiples Opérateurs et expressions Composition Déclaration des variables 3. Contrôle de l'exécution Exécution conditionnelle Répétitions en boucle 4. Principaux types de données Les nombres Les chaînes de caractères Les tableaux 5. Les procédures et les fonctions Les procédures Les variables locales et les variables globales Les fonctions Valeurs par défaut pour les paramètres Paramètres optionnels Passage des arguments par valeur ou par référence 6, Les interfaces graphiques (GUI) Afficher une boîte de message Dialoguer avec l'ordinateur Ouvrir une fenêtre Un exemple d'application basique 7. Les fichiers Utilité des fichiers Travailler avec des fichiers Les fichiers inclus Les espaces de noms 8. Les types et les classes Définition d'un type de donnée élémentaire Un type peut en cacher un autre Les classes et les méthodes Héritage Similitude et unicité La surcharge des opérateurs 9. Les métadirectives Les définitions (#Define) Les déclarations (Declare) Les macros 10. Créer des exécutables Conclusion Addenda La méta-directive #Uses Les tables de hachage ou hash tables - 1-

Transcript of Découvrir FBSL - gedd123.free.frgedd123.free.fr/Fbsl/Tutoriel.pdf · Chapitre 1. Les bases Ce...

Découvrir FBSLDécouvrir FBSLpar un débutant pour les débutantspar un débutant pour les débutants

FBSL (Freestyle Basic Script Language)© 2001-2008 by Gerome GUILLEMIN, Mehdi BOUAZIZ and Mike LOBANOVSKY

SommaireIntroduction1. Les bases

Premiers pasCalculer avec FBSL

2. Données et variablesAffectation ou assignationAfficher la valeur d'une variableRé-affectationAffectations multiplesOpérateurs et expressionsCompositionDéclaration des variables

3. Contrôle de l'exécutionExécution conditionnelleRépétitions en boucle

4. Principaux types de donnéesLes nombresLes chaînes de caractèresLes tableaux

5. Les procédures et les fonctions Les procédures

Les variables locales et les variables globalesLes fonctionsValeurs par défaut pour les paramètresParamètres optionnelsPassage des arguments par valeur ou par référence

6, Les interfaces graphiques (GUI)Afficher une boîte de messageDialoguer avec l'ordinateurOuvrir une fenêtreUn exemple d'application basique

7. Les fichiers Utilité des fichiers Travailler avec des fichiers Les fichiers inclus Les espaces de noms8. Les types et les classes

Définition d'un type de donnée élémentaireUn type peut en cacher un autreLes classes et les méthodesHéritageSimilitude et unicitéLa surcharge des opérateurs

9. Les métadirectives Les définitions (#Define) Les déclarations (Declare) Les macros10. Créer des exécutablesConclusionAddenda La méta-directive #Uses Les tables de hachage ou hash tables

- 1-

Introduction

Ce didacticiel a pour objectif de vous faire découvrir FBSL. Il est avant tout destiné aux débutants qui pourront, sans posséder aucune connaissance au préalable, se familiariser avec les bases du langage pour aborder ensuite toutes les subtilités de ce sympathique et puissant langage de programmation.

FBSL signifie « Freestyle Basic Script Language ». Comme beaucoup d'autres langages de programmation modernes, FBSL est inspiré de Visual Basic, QBasic, PHP, Pascal et C++. Il s'agit d'une sorte de langage hybride d'où le « Freestyle » au début de son nom. Il est surtout destiné aux plate-formes win32 (de Windows 95 SR2 à Windows VISTA), mais il est aussi compatible, et complètement fonctionnel sous LINUX Wine.

N'hésitez pas à télécharger la dernière version de FBSL. Et rejoignez le forum si vous avez des questions, des suggestion au sujet de FBSL, ou même des critiques... à propos de ce document.

Remarques sur la présentation du document :

Les cadres avec un fond jaune pâle contiennent des scripts complets que l'on peut copier/coller dans un éditeur de texte et sauvegarder avec l'extension .fbs avant de les exécuter par un double-clic sur l'icône du fichier ou directement depuis l'éditeur si celui-ci le permet.

Les cadres avec un fond bleu pâle contiennent des morceaux de code extraits destinés à être analysés et/ou insérés dans des scripts complets pour pouvoir les tester.

Les cadres avec un fond noir (et une bordure bleue) représente le résultat du script tel qu'il s'affiche dans la console.

- 2-

Chapitre 1. Les bases

Ce chapitre développe les bases fondamentales nécessaires afin que vous puissiez écrire votre premier programme en FBSL.

Premiers pasNous allons commencer notre exploration de FBSL en utilisant le mode 'Console'. Pour cela, il vous faudra utiliser un éditeur de texte, comme le Bloc-Notes de Windows (notepad.exe) par exemple. Mais FBSL, dans sa distribution vous propose d'autres éditeurs plus spécialisés et plus pratiques que vous pourrez trouver dans le répertoire des 'Samples' : Menu Démarrer/Freestyle Basic Script Language/ Samples/GUI, sélectionnez les dossiers commençant par IDE.

Vous pouvez aussi lancer 'FBSLv3 Editor (Eclecta Editor)' depuis Menu Démarrer/Freestyle Basic Script Language. Cliquez ensuite sur File/New ou sur dans la barre d'icône :

A la première ligne tapez : #apptype console pour signaler à FBSL que l'on va utiliser le mode console, puis tapez : pause, pour empêcher la console de se refermer .

Ce premier script ne fait rien de particulier si ce n'est qu'ouvrir une console.

- 3-

Cliquez maintenant sur Compile et Run Script ou tapez simplement sur la touche <F5> , vous obtenez la fenêtre suivante :

Tapez <Entrée>, la console se ferme.

Le mode Console permet, entre autre de tester rapidement des commandes ou des instructions, des petits bouts de programme. A partir de maintenant vous allez utiliser la console de façon intensive. Dans tous les cas vous saisirez votre code entre l'instruction #AppType Console et la commande Pause.

- 4-

Entrez votre code ici

Calculer avec FBSL

FBSL est capable d'évaluer toutes les opérations arithmétiques de base.

Symbole Effet + addition - soustraction * multiplication / division ^ exposant

Retournez maintenant dans l'éditeur et essayez ceci:

N'oubliez pas d'insérer ces lignes entre #AppType Console et Pause.

La commande print a pour effet d'afficher ce qui la suit dans la console.

Notez que les espaces sont optionnels entre les chiffres et les opérateurs (l'éditeur ajoute automatiquement des espaces pour rendre le code plus lisible ) mais l'espace est indispensable entre la commande print et ce qui suit.

Cliquez sur Compile/Run Script ou tapez sur <F5> , vous obtenez la fenêtre suivante :

- 5-

print 5+3print 2–9print 7 + 3 * 4print (7+3) * 4print 20/3

Voici un exemple de ce script commenté :

Notez les commentaires qui apparaissent après l'apostrophe (') et dont FBSL ne tient pas compte lors de l'exécution du programme. Ils permettent d'expliquer en langage clair ce que font les instructions et contribuent aussi à la lisibilité du script en séparant les différentes sections du programme.

Les commentaires peuvent aussi être précédés d'une double barre oblique // au lieu de l'apostrophe. On peut aussi écrire des commentaires sur plusieurs lignes, qui formeront un bloc encadré par /* au début et */ à la fin.

On peut aussi « aérer » le code en passant des lignes blanches entre les lignes d'instructions.

Il est possible d'écrire plusieurs instructions sur la même ligne en les séparant par des : (deux-points).

- 6-

FBSL respecte la hiérarchie des opérations mathématiques. A titre d'information, pour mémoriser les règles de priorité, il existe un « truc » mnémotechnique, l'acronyme PEMDAS :

● P pour parenthèses. Ce sont elles qui ont la plus haute priorité. Elles permettent de « forcer » l'évaluation d'une expression dans l'ordre souhaité.

2*(3-1) = 2*2 = 4 FBSL → ? 2 * (3 – 1)(1+1)^(5-2) = 2^3 = 8 FBSL → ? (1 + 1)^(5 – 2)

● E pour exposants. Ceux-ci sont évalués ensuite avant les autres opérations

2^1+1 = (2^1) + 1 = 3 et non 4 FBSL → ? 2 ^ 1 + 13*1^10 = 3 * (1^10) = 3 et non 59049 FBSL → ? 3 * 1 ^ 10

● M et D pour multiplication et division, qui ont la même priorité.2*3-1 = 5 et non 4 FBSL → ? 2 * 3 - 12/3-1 = -0.3333 FBSL → ? 2 / 3 – 1

● A et S pour addition et soustraction, qui sont effectuées en dernier lieu.

● Si deux opérateurs ont la même priorité, l'évaluation se fait de gauche à droite.59*100/60 = 5900/60 = 98.3333 FBSL → ? 59 * 100 / 60

? est un raccourci pour print. Il existe également un autre synonyme de print: echo qui fait la même chose.

Une des richesses de FBSL est sa souplesse syntaxique qui facilite le passage en douceur d'autres langages de programmation vers FBSL mais aussi de FBSL vers d'autres langages de programmation.

Chapitre 2. Données et variables

Un programme d'ordinateur manipule essentiellement des données. Le programme accède à ces données en utilisant des variables de différents types. Une variable consiste généralement en un nom de variable souvent quelconque qui, pour l'ordinateur, sert de référence indiquant une adresse mémoire, c'est-à-dire un emplacement précis dans la mémoire vive.

A cette adresse une valeur est stockée, il s'agit de la donnée proprement dite. Cela peut-être un nombre entier ou réel, une chaîne de caractère, un tableau, etc.

Vous pouvez choisir librement les noms des variables mais préférez des noms à la fois courts et explicites de manière à exprimer clairement le type d'information contenu dans l'objet. Par exemple, age est préférable à a, ou nom plutôt que x.

Vous pouvez quand même choisir des noms de variable composés de plus d'un mot. Mais il faut s'assurer que le nom de la variable soit lisible.

Imaginez que vous désirez utiliser une variable pour enregistrer le nom de naissance. Il existe deux conventions:

• nomNaissance• nom_naissance

Evitez si possible : nomnaissance, moins lisible.

- 7-

Affectation ou assignation

Après avoir choisi judicieusement un nom de variable, il faut maintenant lui « affecter » ou « assigner » une valeur, c'est-à-dire établir un lien entre le nom de la variable et son contenu (ou sa valeur).

L'opération d'affectation est représenté par le signe égal (=) :

Il existe aussi une autre manière de faire, qui permet à la fois de créer une (ou des) variable(s) et de lui(leur) assigner ou non un contenu :

Cela permet de « réserver » des noms de variables avant qu'ils ne prennent une valeur précise.

ATTENTION ! depuis la version 3.31.6 de FBSL, Explicit est l'option par défaut , il faut donc déclarer obligatoirement les variables avec Dim pour éviter toute erreur, ou préciser #Option Implicit en tête de script si l'on ne veut pas déclarer les variables. Voir le chapître sur la Déclaration des variables

Afficher la valeur d'une variable

Pour afficher la valeur d'une variable dans la console, on utilise bien entendu la commande print ou un de ses synonymes.

Essayez :

N.B. : Vous pouvez copier/coller les lignes de code ci-dessus dans l'éditeur. Puis faites éventuellement un Format/Check Syntax avant de lancer le script afin de vérifier qu'il n'y ait pas d'erreur de syntaxe ou de fautes de frappe.

- 8-

Dim nombre, messagenombre = 7 'donne à nombre la valeur 7message = "Bonjour" ' affecte la valeur "Bonjour" à message

Dim nombre = 7, message = "Bonjour"

#Option Implicit#AppType Console

n = 7msg = "Bonjour"Print nPrint msg

Pause

Ré-affectation

On peut bien sûr ré-affecter une nouvelle valeur à une même variable autant de fois qu'on le souhaite. La nouvelle valeur remplace alors l'ancienne valeur :

Il existe heureusement une autre manière d'assigner une valeur à une variable dont on voudrait protéger le contenu. Il suffit de déclarer cette « variable » avec la commande const (pour constante).

Essayez :

Vous devriez obtenir ce résultat :

La variable C, déclarée comme une constante est protégée. Sa valeur ne peut être modifiée.

Pour repérer facilement les constantes dans un programme on a coutume de taper leur nom en majuscule. Ce n'est pas une obligation.

- 9-

#Option Implicit#AppType Console

distance = 320print distancedistance = 375print distance

Pause

#AppType Console

Const C = 100Print C

C = 1Print C

Pause

100[SV] Var protected : 'c' <-- 1100Type Enter key to continue...

Affectations multiples

Avec FBSL on peut assigner une valeur à plusieurs variables en même temps grâce à l'opérateur Let. Exemple :

On peut aussi assigner une liste de variables en une seule opération :

La liste entre les accolades { } correspond à ce qu'on appelle un tableau. Chaque élément du tableau est affecté en tant que valeur au nom de variable correspondant de la commande Liste.

Cette fonctionnalité de FBSL est plus intéressante qu'elle n'y paraît. Par exemple, on affecte les valeurs 3, 4, 5 et 7 à a, b, c et d :

et on veut maintenant échanger les valeurs de variables a et c et celles de b et d:

On aurait pu faire aussi :

Swap() permet d'échanger les valeurs de deux variables, avec List() et les tableaux on peut échanger les valeurs de plusieurs variables.

- 10-

#Option Implicit#AppType Console

Let(x, y) = 7? x? y

Pause

#Option Implicit#AppType Console

List(a, b) ={4, 8.33}? a? b

Pause

List(a, b, c, d) ={3, 4, 5, 7}

List(a, b, c, d) ={c, d, a, b}

Swap(a, c)Swap(b, d)

Opérateurs et expressions

Il est possible de manipuler les variables et leur valeur en les combinant avec des opérateurs pour former ainsi des expressions :

Après avoir affecté les valeurs 7.3 et 12 aux variables a et b, on affecte à une nouvelle variable y le résultat d'une expression qui combine les opérateurs *, + et / aux opérandes a, b, 3 et 5.

Composition

En combinant les variables, les expressions et les instructions on va pouvoir programmer des algorithmes plus ou moins complexes de façon claire et concise.

Déclaration des variables

FBSL, à l'instar des autres langages Basic, est convivial. C'est pourquoi il permet de créer des variables simplement sans avoir à les déclarer explicitement. Autrement dit, une variable existe à partir du moment où vous l'intégrez dans le code (voir, pour exemple, le paragraphe « Opérateurs et expressions » ci-dessus).

Toutefois la déclaration implicite des variables n'est pas une bonne habitude de programmation car cela peut amener à introduire involontairement de nouvelles variables en faisant, par exemple une faute de frappe. Au lieu de générer un message d'erreur, FBSL semble ignorer cette « nouvelle » variable, ce qui peut produire des résultats inattendus. Ce genre d'erreur peut être assez difficile à repérer dans le code.

Pour éviter cela, FBSL propose la directive #Option Explicit par défaut qui oblige à déclarer les variables à l'aide Dim. De cette manière, un message d'erreur sera édité lorsqu'une variable non déclarée est utilisée.

Essayez :

puis effacez, juste avant #AppType Console, la directive #Option Implicit.

- 11-

a = 7.3b = 12y = 3 * a + b / 3

List(h, m, s) ={15, 27, 34}Print "Nombre de secondes écoulées depuis minuit = ", h*360 + m*60 + s

#Option Implicit#AppType Console

variable = 5Print varaible

Pause

Vous devriez obtenir alors les messages suivants :

La forme la plus simple pour la déclaration explicite est la suivante :

Ici la variable de nom variable est déclarée. Le type de cette variable est « variant » . Une variable variante est une variable universelle pouvant contenir tout type de valeur : un nombre entier ou à virgule flottante, une chaîne de caractère, etc.

Exemple :

La variable déclarée dans l'exemple ci-dessus peut être employée pour contenir différents types de variables à l'intérieur d'un même programme. Même si ce dernier point procure une grande souplesse, mieux vaut restreindre une variable à un type unique.

A titre d'information, pour déclarer une variable associée à un type particulier, utilisez la syntaxe suivante :

● variable entière (integer) → Dim var As Integer ou Dim %var● variable simple (single) → Dim var As Single ou Dim !var● variable double (double) → Dim var As Double ou Dim #var● variable chaîne (string) → Dim var As String ou Dim $var● etc.

L'instruction Dim peut être utilisée pour la déclaration de plusieurs variables : Dim var1, var2, var3

RAPPEL : depuis la version 3.31.6 de FBSL, Explicit est l'option par défaut et ne doit plus être obligatoirement précisée. On peut toutefois préciser #Option Strict pour obtenir un meilleur contrôle sur les variables.

- 12-

[000004] Missing variable name 'variable'![000005] Missing variable name 'varaible'!

Type Enter key to continue...

#AppType Console

Dim variable

Pause

#AppType Console

Dim variable

variable = 5Print variable

variable = "Bonjour"Print variable

Pause

Chapitre 3. Contrôle de l'exécution

FBSL exécute normalement les instructions de la première ligne à la dernière, sauf quand il rencontre une instruction conditionnelle comme l'instruction if par exemple. Ce genre d'instructon va permettre au programme de suivre différents chemins selon les circonstances.

Exécution conditionnelle

Afin de pouvoir aiguiller le programme le déroulement du programme dans différentes directions, il est nécessaire de disposer d'instructions capables de tester une certaine condition et de modifier le comportement du programme en conséquence.

La plus simple de ces instructions conditionnelles est l'instruction if ... then ... (si ... alors ...).

La première commande déclare la variable entière a et lui affecte la valeur 150.L'expression qui suit if est ce qu'on appelle une condition. Si la condition est vraie, alors l'instruction qui suit le then est exécutée. Si la condition est fausse, rien ne se passe.

Essayez le même exemple avec Dim %a = 20 pour vérifier.

Notez que l'on a écrit l'instruction if ... then d'une manière toute différente, sous la forme d'un bloc d'instruction. Un bloc commence toujours par une commande comme if par exemple, ou begin ou d'autres commandes que nous verrons plus tard et se termine souvent par End (suivi du nom de la commande initiale). Entre le début et la fin du bloc chaque instruction est écrite sur une ligne et peut être indentée pour améliorer la lisibilité du code.

- 13-

#AppType Console

Dim %a = 150

If a > 100 Then Print "a est plus grand que 100"

Pause

#AppType Console

Dim %a = 20

If a > 100 Then Print "a est plus grand que 100"

End If

Pause

Poursuivons notre exploration des instructions conditionnelles en ajoutant deux lignes à l'exemple précédent:

L'instruction else (« sinon » en anglais) permet de programmer une exécution alternative. Le programme a le ici le choix entre deux possibilités. Mais on on peut encore faire mieux en utilisant l'instruction elseif (qui peut se contracter en elsif ou même elif).

FBSL étant un langage à la fois très souple et très riche, on peut aussi écrire des instructions conditionnelles sous la forme de fonctions :

Iif(expr, vrai, faux)est un opérateur qui évalue une expression comme étant vraie ou fausse et retourne la valeur correspondant à l'évaluation. expr correspond à l'expression à évaluer, vrai est la valeur retournée si l'expression est vraie, faux est la valeur retournée si l'expression est fausse. Dans l'exemple ci-dessus, Print affichera ici la valeur retournée par Iif.

- 14-

#AppType Console

Dim %a = 20

If a > 100 Then Print "a est plus grand que 100"Else Print "a est plus petit que 100"End If

Pause

#AppType Console

Dim %a = 0

If a > 0 Then Print "a est positif"ElseIf a < 0 Then Print "a est negatif"Else Print "a est nul"End If

Pause

#AppType Console

Dim %a = 0

Print IIf(a > 150, "a depasse la centaine", "a ne depasse pas cent")

Pause

Autre exemple :

L'instruction Switch(expr-1, val-1, expr-2, val-2, ..., expr-n, val-n) évalue les expression expr et retournela valeur val vraie d'une liste de conditions.

Notez la virgule après la commande print qui permet l'affichage séquentielle d'expressions ou de valeurs.

La condition évaluée après une instruction conditionnelle peut contenir les opérateurs de comparaison suivants :

Opérateur de comparaison Relation Expression

= égalité X = Y<> inégalité X <> Y< inférieur à X < Y> supérieur à X > Y

<= inférieur ou égal X <= Y>= supérieur ou égal X >= Y

Il est possible d'imbriquer plusieurs instructions composées (comme les instructions conditionnelles) les unes dans les autres de manière à réaliser des structures de décisions complexes :

Exemple tiré de « Apprendre à programmer avec Python » , par Gérard Swinnen

- 15-

#AppType Console

Dim %a = 0

Print "a est ", Switch(a > 0, "positif", a < 0, "negatif", "nul")

Pause

If embranchement = "vertébrés" Then 1 If classe = "mammifères" Then 2 If ordre = "carnivores" Then 3 If famille = "félins" Then 4 Print "c'est peut-être un chat" 5 End If 6 End If 7 Print "c'est en tous cas un mammifère" 8 End If 9ElIf classe = "oiseaux" Then 10 Print "c'est peut-être un canari" 11End If 12

13Print "la classification des animaux est complexe" 14

La phrase « c'est peut-être un chat » ne peut être afficher que si les quatre premières conditions testées sont vraies.

Pour que la phrase « c'est en tous cas un mammifère » soit affichée, il suffit que les deux premières conditions soient vraies. L'instruction d'affichage de cette phrase se trouve d'ailleurs au même niveau d'indentation que l'instruction If ordre = "carnivores" Then ... End If. Les deux font partie d'un même bloc qui est entièrement exécuté si les conditions testées aux deux premières lignes sont vraies.

Pour que la phrase « c'est peut-être un canari » soit affichée, il faut que la variable embranchement contienne « vertébrés », et que la variable classe contienne « oiseaux ».

La phrase de la ligne 14 est affichée dans tous les cas car elle fait partie du même bloc que la ligne 1.

D'où l'intérêt d'écrire un code clair et bien indenté.

On peut aussi utiliser la commande conditionnelle : select case

Essayez cet exemple avec différentes valeurs pour c.

Répétitions en boucle

Ce qu'un ordinateur peut faire de mieux, c'est la répétition de tâches identiques, sans fatigue (quoique) et sans erreurs. Il existe plusieurs méthodes pour programmer ce genre de tâches répétitives. Commençons par la plus simple : Do ... Loop

- 16-

#AppType Console

Print "Boucle : DO...LOOP"Dim %a = 0Do

a = a + 1If a = 7 Then Exit DoPrint a, " ";

Loop

Print:Pause

#AppType Console

Dim a = 10, b = -10, c

c = 10

Select Case c Case a Print "c = a = ", a Case b Print "c = b = ", b Case Else Print "c = ", cEnd Select

Print: Pause

Que se passe-t-il ? Do (faire) introduit un bloc qui va se terminer avec Loop (boucler ). A l'intérieur de ce bloc se trouve:

● l'instruction a = a + 1 qui augmente d'une unité le contenu de la variable a● l'instruction if qui teste la valeur contenue dans la variable a. Si celle-ci atteint 7 alors l'instruction

exit do fait sortir de la boucle et le programme se termine.● sinon on affiche le contenu de a puis un espace " " sans retour à la ligne (grâce au point-virgule ;

qui termine l'instruction print)● puis la commande loop renvoie à do au début du bloc pour recommencer la séquence

d'instructions qui suit.

Il existe une autre manière de programmer cette boucle, plus élégante et plus concise :

Ici do boucle jusqu'à ce que (until) a = 7. Lorsque la valeur de a atteint 7 on sort de la boucle (loop).

La commande while (tant que) est un peu l'inverse de la précédente :

Tant que a reste inférieur à 8, le bloc entre while et wend (= while end) est exécuté.

Avec repeat on évite de tester une condition quelconque, en imposant d'emblée le nombre de répétition :

- 17-

#AppType Console

Print "Boucle : DO...LOOP UNTIL"Dim %a = 0Do a = a + 1 Print a, " ";Loop Until a = 7

Print:Pause

#AppType Console

Dim %a

While a < 8 a = a + 1 print a, " ";Wend

Print: Pause

#AppType Console

Dim %a = 0

Repeat 7 a = a + 1 Print a, " ";End Repeat

Print: Pause

La commande for (pour) fait varier le contenu de la variable entre une valeur de début et une valeur de fin, tout en exécutant ce qui se trouve à l'intérieur du bloc for ... next (suivant).

Exemples d'utilisation des boucles :

Liste des carrés et des cubes des nombres de 1 à 11 :

Affichage des dix premiers termes d'une suite appelée « Suite de Fibonacci » :

Il s'agit d'une suite de nombres dont chaque terme est égal à la somme des deux termes qui le précédent. Notez l'utilisation judicieuse de l'affectation multiple avec list.

- 18-

#AppType Console

Dim %a

For a = 1 To 7 print a, " ";Next

Print:Pause

#AppType Console

Dim %a

For a = 1 To 11 Print a, " ", a ^ 2, " ", a ^ 3Next

Pause

#AppType Console

Dim %a = 1, %b = 1, %c

For c = 1 To 10 Print b, " "; List(a, b) ={b, a + b}Next

Pause

Chapitre 4. Principaux types de données

Les nombres

FBSL possède une fonction qui retourne le type de donnée contenue dans une variable : GetTypeName()

Résultat :

On voit que FBSL reconnaît les nombres entiers (integer) et les nombres à virgule flottante en double précision (double). Mais il reconnaît également les nombres à virgule flottante en simple précision (single).

Les chaînes de caractères

Il existe bien entendu d'autres types de données parmi lesquelles les chaînes de caractères (ou string en anglais). Il s'agit d'une suite quelconque de caractères délimitée par des guillemets.

Exemple :

- 19-

#AppType Console

Dim r, sr = 12s = PI * r ^ 2

Print "r = 12"Print "s = PI * r^2 = ", sPrintPrint "r est de type <", GetTypeName(r), ">"Print "s est de type <", GetTypeName(s), ">"Print "PI est de type <", GetTypeName(PI), ">"Print

Pause

r = 12s = PI * r^2 = 452.38934211693r est de type <Integer>s est de type <Double>PI est de type <Double>Type Enter key to continue...

#AppType Console

phrase1 = "les oeufs durs."phrase2 = """Oui"", dit-il, "phrase3 = "j'aime bien "Print phrase2, phrase3, phrase1Print: Pause

Remarquez l'utilisation de doubles guillemets dans la variable phrase2 afin de pouvoir inclure dans la chaîne les guillemets à afficher lors du print.

Le caractère spécial « \ » (antislash ou backslash en anglais) permet d'insérer un certain nombres de codes spéciaux : retour en arrière (\b), saut à la ligne(\n ou \r), tabulation (\t), etc.) mais il faut prévenir FBSL de son utilisation en insérant la ou les chaînes concernées entre les métadirectives #EscapeChars On et #EscapeChars Off.

Pour accéder aux caractères individuels d'une chaîne, il existe un certain nombre de fonctions dont les plus connues sont : Left(), Right() et Mid().

A la 5ème ligne on aurait pu également écrire : Print ch{1}, ch{11}, ch{17}, ch{24}.

On peut aussi assembler plusieurs petites chaînes pour en construire une plus grande. Cette opération s'appelle la concaténation et se réalise à l'aide de l'opérateur & :

Pour déterminer la longueur d'une chaîne, on fera appel à la fonction StrLen() qui retourne le nombre de caractères d'une chaîne, à ne pas confondre avec la fonction Len()qui calcule la longueur réelle d'une variable assignée.

A ce stade il n'est pas inutile, et il est même fortement recommandé de consulter le manuel de FBSL (en anglais) qui est une mine d'informations pratiques, accompagnées d'exemples simples, à propos de toutes les commandes, instructions et fonctions du langage.

- 20-

#AppType Console

#EscapeChars OnDim $ch = "Ceci est une chaine de caracteres\nplutot longue\ncontenant plusieurs lignes de texte." Print ch#EscapeChars Off

Print: Pause

#AppType Console

Dim $ch = "Freestyle Basic Script Language"Print Left(ch, 1), Mid(ch, 11, 1), Mid(ch, 17, 1), Mid(ch, 24, 1)Print Right(ch, 8)

Print: Pause

#AppType Console

Dim $a, $b, $ca = "Petit poisson "b = "deviendra grand"c = a & bPrint c

Print: Pause

Les tableaux

Les tableaux sont des collections d'éléments séparés par des virgules et encadrés par des accolades {}. FBSL reconnaît deux types de tableau :

● les tableaux statiques (static array) que l'on doit déclaré avec ses dimensions : Dim tabstat [0 To 4] est un tableau statique aux dimensions fixes réglés de l'index 0 à 4 (5 index en tout) . Une référence à un index inexistant provoquera un message d'alerte.

● les tableaux dynamiques (dynamic array) dont on ne doit pas déclaré les dimensions, puisque ce type de tableau est automatiquement re-dimensionné si l'on fait référence à un index inexistant.

Exemple de tableau dynamique :

Pour afficher les éléments de ce tableau on utilisera la commande ForEach...In (pour chaque...dans) qui va parcourir chaque élément dans jours :

On peut aussi afficher un élément ou des éléments particuliers du tableau :

- 21-

#AppType Console

Dim jours[] ={"lundi", "mardi", "mercredi", 1800, 20.357, "jeudi", "vendredi"}Print "Taille du tableau = ", Count(jours)Print

Print: Pause

#AppType Console

Dim jours[] ={"lundi", "mardi", "mercredi", 1800, 20.357, "jeudi", "vendredi"}

Dim eForEach e In jours Print e, " ";NextPrint

Print: Pause

#AppType Console

Dim jours[] ={"lundi", "mardi", "mercredi", 1800, 20.357, "jeudi", "vendredi"}

Print "jours[2] = ", jours[2]Print "jours[4] = ", jours[4]

Print: Pause

On peut encore modifier, remplacer ou ajouter un élément :

Notez que pour ajouter un élément à un tableau dynamique il suffit d'utiliser un index supérieur à l'index maximum du tableau. Sachant que pour jours l'index mini est 0 (zéro) et l'index maxi est 6 puisqu'il y a 7 éléments en tout, il faut affecter la nouvelle valeur à jours[7], soit la valeur retournée par Count(jours) qui nous donne le nombre d'éléments du tableau. Cette astuce nous permet de ne pas avoir à nous préoccuper du nombre d'éléments contenu dans le tableau.

Il existe d'autres fonctions utiles pour gérer et manipuler les tableaux parmi lesquelles Lbound() et Ubound() qui retournent respectivement le plus petit et le plus grand index du tableau spécifié entre les parenthèses.

Voir le manuel de FBSL : FBSL Language → ARRAY Functions pour découvrir d'autres fonctions et tester les exemples.

N'hésitez pas non plus à explorer le répertoire des nombreux exemples fournis dans la distribution de FBSL (dossier <Samples>). Ils sont, pour la plupart très courts et faciles à comprendre.

- 22-

#AppType Console

Dim jours[] ={"lundi", "mardi", "mercredi", 1800, 20.357, "jeudi", "vendredi"}, e

' Modification du 4ème élément du tableau <jours> :Print "jours[3] = jours[3] + 47"jours[3] = jours[3] + 47' Affichage le tableau pour voir la modification :ForEach e In jours Print e, " ";NextPrint: Print

' Remplacement du 4ème élément du tableau <jours> :Print "jours[3] = juillet"jours[3] = "juillet"' Affichage le tableau pour voir la modification :ForEach e In jours Print e, " ";NextPrint: Print

'Ajout d'un élément au tableau <jours> Print "Ajouter un element au tableau 'jours :'"Print "jours[Count(jours)] = ""samedi"""jours[Count(jours)] = "samedi"' Affichage le tableau pour voir la modification :ForEach e In jours Print e, " ";NextPrint: PrintPrint "Taille du tableau = ", Count(jours)

Print: Pause

Chapitre 5. Les procédures et les fonctions

Par procédure on entend les sous-programmes ou routines qui permettent de décomposer un programme complexe en unités plus simples, pouvant être à leur tour décomposées en fragments plus petits. D'autre part les fonctions peuvent être aussi réutilisables dans un même programme ou dans d'autres programmes.

Dans le dernier exemple du chapitre précédent, on aurait pu créer une routine d'affichage d'un tableau au lieu de ré-écrire plusieurs fois la boucle ForEach.

La commande GoSub dirige le flux du programme vers une étiquette désignée par deux-points et un nom, ici :affiche_jours, et exécute les commandes qui suivent jusqu'à la commande Return qui renvoie le programme à la ligne qui suit la commande GoSub <étiquette>.

Vous avez déjà rencontré des fonctions intégrées au langage lui-même : Len() qui calcule la longueur réelle d'une variable ou StrLen() qui retourne le nombre de caractères d'une chaîne ou encore Count() qui compte le nombre d'éléments d'un tableau.

- 23-

#AppType Console

Dim jours[] ={"lundi", "mardi", "mercredi", 1800, 20.357, "jeudi", "vendredi"}

' Modification du 4ème élément du tableau <jours> :Print "jours[3] = jours[3] + 47"jours[3] = jours[3] + 47' Affichage le tableau pour voir la modification :GoSub affiche_joursPrint

' Remplacement du 4ème élément du tableau <jours> :Print "jours[3] = juillet"jours[3] = "juillet"' Affichage le tableau pour voir la modification :GoSub affiche_joursPrint

'Ajout d'un élément au tableau <jours> Print "Ajouter un element au tableau 'jours :'"Print "jours[Count(jours)] = ""samedi"""jours[Count(jours)] = "samedi"' Affichage le tableau pour voir la modification :GoSub affiche_joursPrint

Print "Taille du tableau = ", Count(jours)

Print: Pause

' Routine pour afficher le tableau <jours> :affiche_joursDim jPrint "jours = ";ForEach j In jours Print j, " ";NextPrintReturn

Il est bien sûr difficile et même inutile d'intégrer toutes les fonctions possible et imaginables dans le corps standard de FBSL car leur nombre est infini. Seules les fonctions susceptibles d'être utilisées fréquemment ont vocation d'être intégrées au langage, les autres pourront être créées par l'utilisateur et éventuellement regroupées dans des fichiers spéciaux (fichiers auxiliaires avec l'extension .inc). Ceux-ci pourront ensuite être chargés ou inclus dans des scripts grâce à la commande #Include.

Il faut noter que contrairement à une procédure (ou une routine) qui se contente de réaliser un bout de programme (un sous-programme), une fonction doit renvoyer une valeur. Une vraie fonction peut donc s'utiliser à la droite du signe égale dans des expressions comme y = Sin(PI) par exemple. Ici la fonction Sin() retourne une valeur (le sinus de l'argument PI) qui est affectée à la variable y.

Les procédures

On peut définir une procédure d'une manière plus « élégante » que dans l'exemple précédent à l'aide de la commande Sub qui permet, en plus d'inclure une liste de paramètres spécifiant quelles informations on doit fournir à la procédure lors e son utilisation (cette liste peut rester vide si aucun argument n'est requis). Cette procédure peut ensuite être utilisée comme n'importe quelle instruction FBSL: l'appel du sous-programme est constitué du nom de la procédure suivi de parenthèses entourant zéro, un ou plusieurs arguments.

Exemple :

On peut utiliser cette procédure dans la définition d'une autre procédure :

- 24-

#AppType Console

Sub Table7() Dim %n For n = 1 To 10 print n * 7, " "; Next

PrintEnd Sub

Table7()

Print: Pause

#AppType Console

Table7_Triple()

Print: Pause

Sub Table7() Dim %n For n = 1 To 10 print n * 7, " "; Next PrintEnd Sub

Sub Table7_Triple() Print "La table de 7 en triple exemplaire :" Repeat 3: Table7(): End RepeatEnd Sub

Si nous voulons maintenant afficher la table de 9, nous avons le choix entre ré-écrire entièrement la procédure précédente ou définir une nouvelle procédure qui puisse afficher n'importe quelle table à la demande. Il faudra donc indiquer à cette procédure quelle table nous voulons afficher. Cette information qui sera transmise à la procédure au moment où nous l'appellerons s'appelle un argument.

Dans la définition de la procédure on devra prévoir une variable particulière qui recevra l'argument transmis. Cette variable est appelé un paramètre. Il s'agit d'un nom de variable qui sera placé entre les parenthèses qui accompagnent la définition de la fonction.

Exemple:

La procédure Table() utilise le paramètre base pour calculer les dix premiers termes de la table de multiplication correspondante. La valeur indiquée entre parenthèses lors de l'appel de la procédure est automatiquement affectée au paramètre base. Dans le corps de la procédure, base joue le même rôle que n'importe quelle autre variable.

L'argument utilisé dans l'appel d'une procédure peut être aussi une variable :

Dans cet exemple, l'argument passé à la procédure Table() est le contenu de la variable a. A l'intérieur de la procédure cet argument est assigné au paramètre base qui est une autre variable. Le nom d'une variable passée comme argument n'a rien à voir avec le nom du paramètre correspondant de la procédure ou de la fonction.

- 25-

#AppType Console

Table(9)Table(13)

Print: Pause

Sub Table(base) Dim %n For n = 1 To 10 Print n * base, " "; Next PrintEnd Sub

#AppType Console

Dim %aFor a = 1 To 20 Table(a)Next

Print: Pause

Sub Table(base) Dim %n For n = 1 To 10 Print n * base, " "; Next PrintEnd Sub

On peut encore améliorer la procédure Table() en lui ajoutant des paramètres supplémentaires pour afficher plus ou moins de dix termes :

Les variables locales et les variables globales

Les variables définies à l'intérieur de la procédure ne sont accessibles qu'à la procédure elle-même. On dit qu'il s'agit de variables locales. C'est le cas des variables base, debut, fin de l'exemple précédent mais encore de n parce que déclaré (avec Dim) au sein de la procédure.

Si l'on tape print base juste après l'appel de la procédure TableMulti() on obtiendra un message : [n° ligne] Missing variable name 'base'!

En revanche les variables définies à l'extérieur d'une procédure ou d'une fonction sont des variable globales. Elles sont « visibles » partout même à l'intérieur d'une procédure.

Exemple:

Résultat:

- 26-

#AppType Console

TableMulti(8, 13, 17)

Print: Pause

Sub TableMulti(base, debut, fin) Dim %n Print "Fragment de la table de multiplication par ", base, " :" For n = debut To fin Print n, " X ", base, " = ", n * base NextEnd Sub

#AppType Console

Dim p = 15, q = 38Masque()Print p, " ", q

Print: Pause

Sub Masque() Dim p = 20 Print p, " ", qEnd Sub

20 3815 38Type Enter key to continue...

Deux variables p et q sont définies avec les valeurs 15 et 38. Ce sont des variables globales parce qu'elles ont été définies au niveau principal, en dehors de toute procédure.

Dans la procédure Masque() on définit une variable p avec pour valeur 20. Il s'agit d'une variable locale à la procédure puisqu'elle a été définie à l'intérieur de celle-ci.

Le même nom de variable p a été utilisé deux fois pour définir deux variables différentes, l'une globale et l'autre locale. L'exemple précédent montre bien qu'il s'agit de variables distinctes et indépendantes, obéissant de plus à une règle de priorité qui veut qu'à l'intérieur d'une procédure ce sont les variables définies localement qui sont prioritaires (ce qui permet d'éviter tout conflit entre ces variables).

Lorsqu'on appelle la procédure Masque(), la variable q y est accessible puisque sa valeur est correctement affichée. Mais c'est la valeur locale de p qui est affichée. Cependant la procédure Masque() n'a pas modifié le contenu de la variable globale p. L'instruction suivante le montre en affichant la valeur initiale de la variable globale p.

Dans l'exemple suivant la variable a utilisée à l'intérieur de la procédure Augmenter() est accessible et modifiable parce qu'il s'agit d'une variable globale (la déclaration de la variable est faite au niveau global).

Les fonctions

Comme cela a été dit au début de ce chapitre, une fonction doit renvoyer un résultat :

La commande return indique la valeur qui doit être renvoyée par la fonction. Celle-ci se construit comme une procédure mais en utilisant le mot function au lieu du mot sub.

- 27-

#AppType Console

Dim a = 15Augmenter()Augmenter()

Print: Pause

Sub Augmenter() a = a + 1 Print aEnd Sub

#AppType Console

Dim %bb = Cube(9)Print b

Print: Pause

Function Cube(n) Return n * n * nEnd Function

Voici comment on pourrait modifier la procédure Table(), définie précédemment, en une fonction afin qu'elle retourne une valeur :

Cet exemple nous permet à la fois de revoir les tableaux et de comprendre comment on peut utiliser la valeur retournée par une fonction. Ici on affecte à la variable tab9 la valeur (result) renvoyée par la fonction Table(), il s'agit d'un tableau comprenant les 10 premiers termes de la table de multiplication de 9.

On peut aussi afficher ou manipuler les éléments de ce tableau individuellement :

- 28-

#AppType Console

Dim tab9, item

tab9 = Table(9)

ForEach item In tab9 print item, " ";Next

Print: Pause

Function Table(base) Dim result[] ={}, %n For n = 1 To 10 result[Count(result)] = n * base Next Return resultEnd Function

#AppType Console

Dim tab9, %i

tab9 = Table(9)

Print tab9[0]Print tab9[3]

For i = 2 To 4 print tab9[i], " ";Next

Print: Pause

Function Table(base) Dim result[] ={}, %n For n = 1 To 10 result[Count(result)] = n * base Next Return resultEnd Function

Valeurs par défaut pour les paramètres

Dans la définition d'une procédure ou d'une fonction, il est possible de définir un argument par défaut pour chacun des paramètres. On peut ainsi appeler la fonction avec une partie seulement des arguments attendus.

N.B.: On peut définir une valeur par défaut pour tous les paramètres ou seulement une partie d'entre eux. Dans ce cas les paramètres sans valeur par défaut doivent précéder les autres dans la liste.

Paramètres optionnels

ParamArray permet de passer un nombre quelconque d'arguments (jusqu'à 1024) à une fonction ou une procédure (voir le fichier d'aide FBSL v3, ARRAY Functions) :

Dans la définition de la procédure pa correspond au tableau de paramètres qui est passé à la procédure TestPA(). Dans ce tableau on retrouve les arguments inscrits entre parenthèses lors de l'appel de la procédure.

Passage des arguments par valeur ou par référence

Les paramètres d'une fonction ou d'une procédure, qui sont donc des variables locales à cette fonction/procédure peuvent passer les arguments, définis lors de l'appel de la fonction/procédure, par référence ou par valeur.

Dans le premier cas, le paramètre de la fonction/procédure fera référence à la même valeur contenue dans la variable donnée en argument à la fonction/procédure. Si la fonction/procédure modifie la valeur de son paramètre, elle modifiera aussi la variable passée en argument.

- 29-

#AppType Console

Print Salutations("Dupont")Print Salutations("Dubois", "Madame")

Print: Pause

Function Salutations(nom, titre = "Monsieur") Return "Veuillez agreer, " & titre & " " & nom & ", mes salutations distinguees."End Function

#AppType Console

Sub TestPA(ParamArray pa) Dim e ForEach e In pa Print e NextEnd Sub

TestPA(1, 2, 3, 4, "Hello", "FBSL!")

Pause

Résultat:

Ici i est l'argument de Test() dont le paramètre x prend la valeur de i par référence (commande ByRef dans la définition de la procédure). Les variables i et x pointent sur la même valeur. Si l'on modifie la valeur à l'aide de l'une des variables, l'autre variable pointera alors sur cette nouvelle valeur.

Dans le deuxième cas, la paramètre de la fonction/procédure fera une copie de la valeur de la variable donnée en argument à la fonction/procédure et celle-ci ne pourra pas être modifiée au sein de la fonction/procédure.

- 30-

'==========================' ByVal : par valeur'==========================#AppType Console

Dim %i = 10

Print "i = ", iTest(i)Print "i = ", i

Print: Pause

Sub Test(ByVal %x) x = x + 2 Print "x = ", xEnd Sub

'===========================' ByRef : par référence'===========================#AppType Console

Dim %i = 10

Print "i = ", iTest(i)Print "Maintenant i = ", i

Print: Pause

Sub Test(ByRef %x) x = x + 2 Print "Dans Test() x = ", xEnd Sub

i = 10x = 12i = 12Type Enter key to continue...

Résultat :

Ici le paramètre x de Test() copie la valeur de i (commande ByVal dans la définition de la procédure). La variable globale i et la variable locale x sont distinctes bien qu'elles contiennent la même valeur ou plutôt une valeur équivalente. Si l'on modifie la valeur de l'une des variables, l'autre variable n'en sera pas affectée puisqu'il s'agit d'une copie.

N.B.: par défaut les arguments des procédures/fonctions sont passés par référence.

Chapitre 6. Les interfaces graphiques (GUI)

Afficher une boîte de message

Voici peut-être le plus petit script écrit en FBSL :

qui donne ce résultat :

La fonction MsgBox() crée et affiche une boîte de message. Elle comprend 4 paramètres :● Le premier paramètre permet d'identifier la fenêtre parente, celle qui va contenir la boîte de

message. Si ce paramètre est NULL ou 0 (zéro), cela signifie que la boîte de message n'a pas de fenêtre parente.

● Le second paramètre contient le texte du message sous la forme d'une chaîne de caractères ou d'une variable contenant une chaîne de caractères.

● Le troisième paramètre est le titre de la boîte de message qui s'affichera donc dans la barre de titre de la fenêtre. Il s'agit aussi d'une chaîne de caractères.

● Le quatrième paramètre va déterminer le contenu et comportement de la boîte de message : l'affichage ou non de certains boutons et icônes.

Le quatrième paramètre de MsgBox doit être un nombre ou une combinaison de nombres dont la liste se trouve ci-dessous. Heureusement FBSL a intégré ces nombres sous la forme de constantes plus faciles à comprendre et à mémoriser.

- 31-

i = 10x = 12i = 10Type Enter key to continue...

MsgBox(0, "Bonjour tout le monde", "Exemple 1", 0)

Types de message Affiche Constantes FBSL

intégrées0 bouton [OK] MB_OK1 boutons [OK] et [Annuler] MB_OKCANCEL2 boutons [Abandonner], [Recommencer] et [Ignorer] MB_ABORTRETRYIGNORE3 boutons [Oui], [Non] et [Annuler] MB_YESNOCANCEL 4 boutons [Oui] et [Non] MB_YESNO5 boutons [Recommencer] et [Annuler] MB_RETRYCANCEL16 icône d'erreur critique MB_ICONERROR 32 icône de question MB_ICONQUESTION48 icône d'avertissement MB_ICONEXCLAMATION64 icône d'information MB_ICONINFORMATION0 le bouton 1 comme bouton par défaut MB_DEFBUTTON1

256 le bouton 2 comme bouton par défaut MB_DEFBUTTON2512 le bouton 3 comme bouton par défaut MB_DEFBUTTON3

MsgBox()étant une fonction, elle retourne une valeur qui indique quel bouton a été cliqué :

Valeur retournée

Bouton correspondant

Constantes FBSL

1 [OK] IDOK2 [Annuler] IDCANCEL3 [Abandonner] IDABORT4 [Recommencer] IDRETRY5 [Ignorer] IDIGNORE6 [Oui] IDYES7 [Non] IDNO

Exemple :

- 32-

Do Dim %r = MsgBox(0, "Voici un message", "Exemple 2", 3 + 64) 'ou plus clairement: MB_YESNOCANCEL + MB_ICONEXCLAMATION au lieu de 3 + 64 Select Case r Case IDCANCEL MsgBox(0, "Vous avez cliqué ANNULER !", "Exemple 2", 1): Exit Loop Case IDYES MsgBox(0, "Vous avez cliqué OUI !", "Exemple 2", 1) Case IDNO MsgBox(0, "Vous avez cliqué NON !", "Exemple 2", 1) End SelectLoop

Dialoguer avec l'ordinateur

Le pendant de MsgBox() est InputBox() qui affiche une boîte de dialogue invitant l'utilisateur à entrer du texte dans la zone d'édition et/ou à cliquer un bouton pour retourner le contenu de la zone d'édition sous la forme d'une chaîne de caractères.

Le paramètres de InputBox() sont :● Le titre de la fenêtre● L'invite située au-dessus de la zone de saisie● et un argument optionnel : la réponse par défaut qui est insérée dans la zone d'édition

Voici l'exemple tiré du fichier d'aide de FBSL :

ou autrement :

Évidemment FBSL ne se contente pas de ces deux fonctions pour construire des interfaces graphiques. Il est possible de bâtir une interface dans ses moindres détails à l'aide de quelques commandes et fonctions dont vous trouverez la description dans le fichier d'aide : FBSL Language/GUI Functions.

Ouvrir une fenêtre

Pour vous faire une idée de la facilité avec laquelle on peut créer une simple fenêtre avec FBSL, voici un exemple de base :

Ces quelques lignes de code ouvre une fenêtre vide de tout contenu. ME représente la fenêtre par défaut de FBSL, créée au lancement de FBSL. Show() est la fonction qui permet d'afficher une fenêtre ou un « contrôle ».

La boucle Begin Events ... End Events va permettre à FBSL de « scruter » les événements en relation avec l'interface graphique et de récupérer les messages correspondant afin de réagir en conséquence. Si elle n'est pas n'est pas activée, la fenêtre ne pourra s'afficher normalement. On peut faire un rapprochement entre Begin Events ... End Events et la commande Pause en mode console, sauf que le réceptionnaire d'événements est beaucoup plus sophistiqué.

N.B.: la directive #AppType GUI est facultative car FBSL reconnaît automatiquement si le type d'application est graphique.

- 33-

Msgbox( 0, _ InputBox( "Entrez un jour, s.v.p.", "Jour :", "Mercredi" ),_ "Nous sommes:", MB_OK)

Dim $message = InputBox("Entrez un jour, s.v.p.", "Jour :", "Mercredi")MsgBox(NULL, message, "Nous sommes :", MB_OK)

#AppType GUI

Show(ME)

Begin EventsEnd Events

On peut aussi régler ou modifier la position et la taille de la fenêtre :

ou centrer la fenêtre sur l'écran tout simplement :

Pour fermer les fenêtres ainsi créées et terminer le programme, il faut cliquer sur l'icône de fermeture [X] située en haut à droite de la fenêtre dans la barre de titre. FBSL gère automatiquement et de manière implicite cet événement. Toutefois il est possible d' « attraper » cet événement, afin de le contrôler manuellement, dans la boucle réceptrice d'événements.

L'événement est capturé dans la variable-système CBMSG (CallBack Message = message de rappel). S'il correspond à l'événement dont la valeur est stockée dans WM_CLOSE (constante intégrée à FBSL) alors on ferme la fenêtre et sort du programme par ExitProgram(0).

On peut profiter de l'occasion pour contrôler l'événement en demandant une confirmation :

- 34-

#AppType GUI

Resize(ME, 100, 100, 600, 500)Show(ME)

Begin EventsEnd Events

#AppType GUI

Center(ME)Show(ME)

Begin EventsEnd Events

#AppType GUI

Center(ME)Show(ME)

Begin Events If CBMSG = WM_CLOSE Then ExitProgram(0)End Events

#AppType GUI

Center(ME)Show(ME)

Begin Events If CBMSG = WM_CLOSE Then Dim %r = MsgBox(ME, "Voulez-vous vraiment sortir ?", "Question", MB_YESNO) If r = 6 Then ExitProgram(0) ' r = 6 = [Oui] End IfEnd Events

Un exemple d'application basique

On utilise souvent le programme « Bonjour tout le monde » comme première introduction à un langage de programmation. La seule chose que fait ce programme est d'afficher : Bonjour tout le monde !

Voici donc la traduction de l'excellent tutoriel qui fait partie du fichier d'aide de FBSL : Tutorials/tuto_GUI/A basic Hello World (de SideShowBob)

Pour illustrer quelques uns des principes de base de la programmation d'une interface graphique, on ajoutera au fameux programme Hello World (Bonjour tout le monde) quelques instructions supplémentaires:

Les premières lignes sont assez simples et vous connaissez déjà la signification de #Option Explicit, de Dim et de Const.

On déclare une variable de type entier ayant pour nom hBonjour. Nous verrons plus loin quel sera son rôle. Notez le petit h mis devant le nom de la variable qui nous rappellera qu'il s'agit d'un handle, c'est-à-dire en quelque sorte une « poignée » avec laquelle on pourra manipuler le contenu de cette variable.

On déclare ensuite une constante ayant pour nom IDB_BONJOUR et pour valeur 1000. Cette constante représente le bouton sur lequel on va cliquer pour afficher « Bonjour tout le monde ». Si nous avions plusieurs boutons chacun d'eux auraient besoin d'un identifiant (ID) afin que l'interpréteur FBSL puisse reconnaître de quel bouton on parle. Notez que l'on utilise une sorte de préfixe : IDB_ pour se rappeler qu'il s'agit d'un identifiant de bouton. L'autre partie du nom permet de désigner un bouton en particulier.

On aurait pu utiliser simplement le nombre 1000, ou même n'importe quel autre nombre, mais il sera plus facile de s'en souvenir si on lui donne un nom. Notez que l'on a pas utiliser ici le signe % car FBSL sait qu'il s'agit ici d'un nombre entier.

La ligne suivante :

affiche un titre en haut de la fenêtre. Vous pouvez essayer de mettre quelque chose entre les guillemets pour voir ce qui se passe.

ME, comme vous le savez maintenant, est le nom de la fenêtre principale. Il s'agit aussi d'un handle.

- 35-

#Option Explicit

Dim %hBonjour

Const IDB_BONJOUR = 1000

Fbsl_SetText(ME, "")Fbsl_Control("Button", ME, "Bonjour", IDB_BONJOUR, 10, 10, 75, 23, 0, 0)hBonjour = Fbsl_Control("Static", ME, "", 0, 0, 50, 300, 150, 0, 0)Fbsl_SetFont(hBonjour, "Verdana", 32, 0, 0, 0, 0)Show(ME)

Begin EventsIf CBMSG = WM_CLOSE Then ExitProgram(0)

If CBMSG = WM_COMMAND And CBCTL = IDB_BONJOUR Then EvenementBonjour()End Events

Sub EvenementBonjour()Fbsl_SetText(hBonjour, "Bonjour tout le monde")

End Sub

Fbsl_SetText(ME, "")

La ligne suivante :

définit le bouton. Fbsl_Control() est une fonction très importante dans la programmation de GUI, il est donc essentiel de bien comprendre chacun de ses paramètres :

● "Button" désigne le type ou la classe de contrôle. D'autres classes comprennent "Static" (qu'on verra sur la ligne suivante), "Edit", "ComboBox", etc.

● ME correspond à la fenêtre parente, celle où sera collé le bouton. D'autres contrôles peuvent aussi être des parents mais ce n'est pas le cas dans cet exemple.

● "Bonjour" est le texte qui apparaît sur le bouton. Vous pouvez essayer de le changer pour voir ce qu'il advient.

● IDB_BONJOUR est l'ID (identifiant) qu'on utilise lorsqu'on veut signaler à FBSL ce qu'il doit faire quand on clique sur le bouton correspondant. Cela deviendra plus clair quand nous examinerons la boucle réceptrice d'événements.

● 10 et 10 indiquent la position du bouton, selon des coordonnées x, y relatives au coin supérieur gauche de la fenêtre. Essayez de modifier ces coordonnées pour voir ce que cela change, (mais évitez de mettre des valeurs trop importantes sinon vous ne pourrez plus voir le bouton).

● 75 et 23 correspondent à la largeur et la hauteur du bouton en pixels. N'hésitez pas à changer ces valeurs pour voir ce qui se passe.

● 0 et 0 désignent le style et le style étendu du contrôle. Il s'agit d'un vaste sujet en soi mais on n'a pas à s'en inquiéter dans cet exemple. Vous en apprendrez plus à mesure que vous découvrirez les autres classes de contrôle.

La ligne suivante :

est un autre contrôle. Cette fois on crée un contrôle "Static", qui est juste une étiquette. C'est sur celle-ci qu'on écrira le texte « Bonjour tout le monde », mais on la laisse vierge pour le moment car on veut pouvoir utiliser le bouton pour affciher le texte.

Il faut remarquer comment on a utilisé ici notre variable hBonjour. La fonction Fbsl_Control() retourne un handle, qui n'est qu'un nombre et que l'on stocke dans une variable afin de pouvoir le réutiliser plus tard, en particulier à la ligne suivante :

qui règle la police de caractères du contrôle. On utilise la poignée ou le manche (handle) du contrôle pour indiquer à FBSL de quel contrôle il s'agit. (Si on avait assigné le handle du bouton à une variable, par exemple hBouton, on aurait pu modifier aussi la police du texte du bouton).

● hBonjour est donc le handle.● "Verdana" est le nom de la police de caractères. Vous pouvez mettre le nom de n'importe quelle

police installée sur votre ordinateur. Essayez "Courier New" ou "Times New Roman".

● 32 est la taille de la police. Essayez de changer et voyez ce qui se passe.● 0 permet de régler l'épaisseur des caractères. La valeur doit être entre 0 et 900. Essayez 700 ou

FW_BOLD.● 0, 0 et 0 permettent de régler les styles italiques, soulignés et barrés. Vous pouvez essayer de

régler un ou plusieurs de ces paramètres sur 1 et voir ce qu'il advient.

La ligne suivante :

affiche la fenêtre principale, comme vous le savez déjà.

- 36-

Fbsl_Control("Button", ME, "Bonjour", IDB_BONJOUR, 10, 10, 75, 23, 0, 0)

hBonjour =("Static", ME, "", 0, 0, 50, 300, 150, 0, 0)

Fbsl_SetFont(hBonjour, "Verdana", 32, 0, 0, 0, 0)

Show(ME)

La partie qui suit est la boucle des événements où se situe toute l'action du script :

Tout ce qui se trouve entre Begin Events et End Events est exécuté continuellement jusqu'à ce qu'on ferme le programme.

Cette ligne ferme le programme :

CBMSG est une variable interne. Elle contient un message que Windows envoie à notre programme lorsque l'on clique sur un bouton, etc. Il y a des tas et des tas de messages en provenance de Windows, mais on ne s'attachera ici qu'à deux d 'entre eux.

WM_CLOSE est le message qui est envoyé quand on clique sur le bouton 'Fermer' dans le coin supérieur gauche d'une fenêtre. En d 'autres termes la ligne ci-dessus dit : « Si on clique sur le bouton 'Fermer', alors on sort du programme ».

Examinons ensuite la ligne qui va afficher « Bonjour tout le monde » :

Cette fois on teste la variable CBMSG pour voir si elle contient le message WM_COMMAND, qui recouvre beaucoup de choses, y compris les clics de souris.

On veut aussi tester une autre variable interne CBCTL pour découvrir ce qui se passe précisément. Si CBCTL contient IDB_BONJOUR, c'est qu'on a cliqué sur le bouton 'Bonjour'. La ligne dit donc : « Si on reçoit un message de commande et si ce message provient du bouton 'Bonjour', alors il faut exécuter le sous-programme EvenementBonjour() ».

Et enfin, voici le sous-programme :

dont la ligne principale donne le texte "Bonjour tout le monde" au contrôle ayant pour handle hBonjour.

On avait déjà utilisé la même fonction Fbsl_SetText() pour fixer le titre de la fenêtre principale. On pourrait donc faire la même chose ici en modifiant le handle de hBonjour en ME. Ou bien on aurait pu donner au handle du bouton un nom, comme hBouton et modifier ainsi le texte du bouton.

Maintenant que vous êtes familiarisé avec les principes de base de la programmation de GUI, il ne vous reste plus qu'à tester d'autres contrôles en laissant libre cours à votre imagination. Poursuivez ce tutoriel dans sa version originale qui propose d'autres expérimentations et jetez un oeil sur les autres tuto_GUI du fichier d'aide.

N'hésitez pas non plus à tester, éditer et modifier les exemples du répertoire Samples/GUI, fourni avec la distribution de FBSL.

- 37-

Begin EventsIf CBMSG = WM_CLOSE Then ExitProgram(0)

If CBMSG = WM_COMMAND And CBCTL = IDB_BONJOUR Then EvenementBonjour()End Events

If CBMSG = WM_CLOSE Then ExitProgram(0)

If CBMSG = WM_COMMAND And CBCTL = IDB_BONJOUR Then EvenementBonjour()

Sub EvenementBonjour()Fbsl_SetText(hBonjour, "Bonjour tout le monde")

End Sub

Chapitre 7. Les fichiersUtilité des fichiers

Lorsque les programmes ne contiennent qu'un petit nombre de données, celles-ci peuvent être incluses dans le corps du programme lui-même (par exemple dans des constantes, des variables, des tableaux, etc.). Mais cela devient inadéquant lorsque l'on traite une quantité d'information plus importante.

Prenons comme exemple un programme qui gère des questions à choix multiple, avec traitement automatique des réponses de l'utilisateur. Comment faire pour mémoriser le texte des questions elles-mêmes ?

On peut placer chaque texte ion dans une variable, au début du programme, avec des instructions d'affectation du genre :

Cela paraît simple à première vue. Mais ça risque de se compliquer quand il faudra élaborer la suite du programme, en écrivant les instructions qui permettront de sélectionner au hasard l'une ou l'autre de ces questions pour les présenter à l'utilisateur. On peut employer une suite d'instructions if ... elseif ... etc. ou même select case ... case ... etc. :

mais si l'on veut traiter un très grand nombre de questions il est préférable de s'orienter vers d'autres solutions, comme l'utilisation d'un tableau par exemple :

- 38-

#AppType Console

Dim a, b, c

a = "Quelle est la capitale du Guatémala ?"b = "Qui a succédé à Henri IV ?"c = "Combien font 26 x 34 ?"' etc.

Pause

Select Case choixCase 1

selection = aCase 2

selection = bCase 3

selection = c' etc.

#AppType Console

Dim liste ={"Qui a vaincu Napoléon à Waterloo", _"Comment traduit-on ""informatique"" en anglais ?", _"Quelle est la formule chimique du méthane ?", _}

' On peut extraire n'importe quel élément du tableau à l'aide son indice :Print liste[2]

Pause

REMARQUE : le caractère de soulignement _ (touche <8> du clavier) vu à la fin des premières lignes du script précédent permet de scinder des lignes trop longues en plusieurs morceaux qui font toujours partie de la même ligne. Ceci permet d'améliorer la lisibilité du programme.

Cependant d'autres problèmes risquent d'apparaitre malgré tout :● la lisibilité du programme va se détériorer lorsque le nombre de questions deviendra encore plus

important,● l'ajout de nouvelles questions ou la modification des question existantes vont obliger à rouvrir le

code source du programme à chaque fois et le code sera vite encombré de lignes supplémentaires,● l'échange de données avec d'autres programmes risque d'être difficile, voire impossible, puisque ces

données font partie du programme lui-même.

La solution est alors de séparer les données et les programmes qui les traitent dans des fichiers différents. FBSL possède un jeu d'instructions plus ou moins sophistiquées qui permet de créer des fichiers, d'y envoyer des données et de les récupérer ensuite.

Il ne s'agit pas ici d'élaborer une base de données relationnelles, bien que cela soit tout à fait possible avec FBSL qui peut dialoguer avec des systèmes spécialisés en la matière (comme SQLite par exemple, voir le dossier Samples). Contentons-nous pour le moment d'utiliser les commandes simples de FBSL pour enregistrer des données dans un fichier de taille moyenne et les relire ensuite.

Travailler avec des fichiers

L'utilisation d'un fichier ressemble beaucoup à l'utilisation d'un livre. Pour utiliser un livre, il faut d'abord le trouver (grâce à son titre) puis l'ouvrir. Lorsqu'on a fini de l'utiliser, on le referme. Tant qu'il est ouvert, on peut y lire les informations qu'il contient et on peut aussi y écrire des annotations mais on évite généralement de faire les deux choses à la fois. Pour se retrouver à l'intérieur du livre on peut s'aider des numéros de pages. La plupart du temps on lit le livre en suivant l'ordre normal des pages mais on peut aussi décider de consulter n'importe quel chapitre dans le désordre.

Tout cela peut s'appliquer également aux fichiers informatiques. Un fichier se compose de données enregistrées sur le disque dur, sur une disquette, un CD-ROM ou tout autre support. On y accède grâce à son nom (accompagné parfois du chemin d'accès : nom du lecteur, nom du répertoire, etc.) Le contenu du fichier peut être considéré comme une suite de caractères que l'on pourra traiter à l'aide des fonctions qui servent à traiter les chaînes de caractères.

Il vous sera facile de comprendre les script suivants, qui illustrent quelques fonctions relatives aux fichiers, sans avoir besoin de grandes explications :

Ecriture séquentielle dans un fichier

- 39-

#AppType Console

Dim fichier, texte

' Ouverture en écriture d'un fichier texte nommé 'monfichier.txt'fichier = FileOpen("monfichier.txt", OUTPUT)

' Ecriture d'une chaîne dans le fichierFilePrint(fichier, "Bonjour, fichier !")

' Fermeture du fichierFileClose(fichier)

Pause

La fonction FileOpen() renvoie une valeur (un nombre entier) que l'on stocke dans une variable (nommé ici fichier), c'est en quelque sorte l'identifiant du fichier que l'on va créer. On peut ensuite manipuler ce fichier avec d'autres fonctions de gestion de fichier comme FilePrint() et FileClose() dans l'exemple précédent.

Lecture séquentielle d' un fichier

On note ici que la fonction FileOpen()sert aussi bien à l'écriture qu'à la lecture d'un fichier le mode devant être précisé lors de l'ouverture : OUTPUT pour l'écriture, INPUT pour la lecture. Il existe d'autres modes comme APPEND pour l'ajout de données à partir de la fin du fichier, ou BINARY et BINARY_INPUT pour l'ouverture d'un fichier en mode binaire (écriture et lecture respectivement). Consultez le fichier d'aide de FBSL à FILES Functions pour découvrir les différentes fonctions relatives aux fichiers et tester un peu les exemples proposés.

Les fichiers inclus

FBSL permet d'inclure, ou d'importer des fichiers dans un script lors de son exécution. On reconnaît ces fichiers grâce à leur extension .inc. Ils permettent de modifier ou d'étendre les fonctionnalités de FBSL . Ils contiennent en général des constantes, des fonctions, des classes, des macros, des définitions ou des déclarations.

La distribution de FBSL offre un certain nombre de fichiers inclus (extension .inc) qui se trouvent dans le répertoire Include du dossier FBSLv3 (chemin complet : C:\Program Files\FBSLv3\Include).

Pour inclure ces fichiers dans un script, on utilise la commande #Include suivi du chemin d'accès et du ou des noms de fichiers « .inc » souhaités.

- 40-

#AppType Console

Dim fichier, texte

' Ouverture en lecture du fichier 'monfichier.txt'fichier = FileOpen("monfichier.txt", INPUT)

' Récupération de la première ligne du fichier dans une variabletexte = FileInput(fichier)Print texte

' Fermeture du fichierFileClose(fichier)

Print: Pause

#AppType Console#Include <Include\Fbsl.inc> 'chemin relatif à l'endroit où se trouve FBSL.exe

Dim $phrase = "Comment écrire dans la console des chaînes de caractères composées d'accents ?"

Print phrasePrint AFXACCENTS(phrase)

Pause

A la ligne 2 du script précédent on aurait aussi pu écrire :

si on voulait préciser le chemin complet du fichier à inclure.

Dans le cas d'un chemin relatif, celui ici est encadré par des <>, sinon si le chemin est absolu ou complet, il sera encadré par des guillemets "". En général on place le fcihier .inc dans le même répertoire que le fichier script (.fbs) dans lequel on aura écrit dès les premières lignes :

On peut créer ses propres fichiers inclus et les incorporer à des programmes de le même manière. L'idée est d'améliorer la lisibilité du programme en le désencombrant d'une longue liste de constantes par exemple, ou de créer de nouvelles fonctions qui pourraient être utilsées aussi dans d'autres programmes. Cependant il faut tenir compte du fait que les noms des identificateurs des scripts inclus peuvent entrer en conflit avec les identificateurs du script principal. Pour éviter ce genre d'incident il peut être utile, et même indispensable d'utiliser des espaces de noms dans les modules inclus.

REMARQUE : Un identificateur est un nom symbolique donné à un élément d'information afin d'éviter de le désigner par son adresse mémoire, par exemple un nom de variable ou de constante.

Les espaces de noms

Les espaces de noms, ou namespaces, sont par définition des conteneurs d'éléments (ou "noms"), servant principalement à fournir un contexte, c'est-à-dire distinguer les noms identiques, mais appartenant à un autre contexte - donc logiquement, se trouvant un autre espace de noms. On peut les comparer aux répertoires ou dossiers d'un ordinateur ou plutôt de son système d'exploitation : ils permettent de structurer les données (ou fichiers) et donc d'en améliorer la gestion en créant des modules, appelés aussi parfois bibliothéques. Un module est un espace de nommage qui peut exporter ou importer certains symboles comme des variables, des fonctions ou des classes. FBSL utilise une métadirective NameSpace pour créer des espaces de nom sous la forme de blocs de code contenant des déclarations, des fonctions, des variables, des macros, etc.

Chaque élément de l'espace de noms doit avoir un nom unique. On accède à ces noms depuis l'extérieur de l'espace de noms comme on accèderait aux fichiers d'un répertoire : les noms de fichier correspondant aux noms locaux des éléments de l'espace de noms et le nom du chemin + un nom de fichier correspondant à la façon dont on accède à un élément de l'espace de noms depuis l'extérieur de cette espace.

- 41-

#Include "C:\Program Files\FBSLv3\Include\Fbsl.inc"

#Include ".\nom_du_fichier.inc"

#AppType Console

NameSpace EspaceDim aa = 33End NameSpace

Dim aa = 12Print aa, " ", Espace.aa ' => 12 33Dim essai = Espaceessai.aa = 67Print aa, " ", Espace.aa, " ", essai.aa ' => 12 67 67

Print: Pause

L'exemple ci-dessus montre que les deux variables aa, appartenant chacune à deux espaces de noms différents gardent leur valeur respective dans tous les cas. On peut voir aussi qu'il est possible d'importer des modifications dans l'espace de noms en réaffectant une nouvelle valeur à une de ses variables par exemple. La variable essai fait ici référence à l'espace de noms Espace et ne crée pas un nouvel espace de noms indépendant, contrairement à une instance d'objet comme onpourra le voir dans le chapître suivant.

Exemple tiré du fichier d'aide (META Directives/NameSpace) :

On remarquera la commande Choose()qui retourne une valeur depuis la liste de choix en fonction de la valeur de l'indice.

Les espaces de noms facilitent la programmation modulaire. On peut dire que la programmation modulaire succède à la programmation fonctionnelle et précède la programmation orientée objet.

- 42-

#AppType Console

Dim DefaultName = "FBSL"

NameSpace NSEnFunction SayHello($name = DefaultName)

? "Hello ", nameEnd Function

End NameSpace

NameSpace NSFrFunction SayHello($name = DefaultName)

? "Bonjour ", nameEnd Function

End NameSpace

NameSpace NSDeFunction SayHello($name = DefaultName)

? "Guten Tag ", nameEnd Function

End NameSpace

Dim i, NSLang

For i = 1 To 3NSLang = Choose(i, NSEn, NSFr, NSDe)NSLang.SayHello()

Next

Print: Pause

Chapitre 8. Les types et les classesLes classes sont les principaux outils de la programmation orientée objet (Object Oriented Programing ou OOP). Ce type de programmation permet de structurer des programmes complexes en les organisant comme des ensembles d'objets qui interagissent entre eux. Ces objets peuvent être construits indépendamment les uns des autres sans qu'il y ait risque d'interférence. En effet la fonctionnalité interne de l'objet et les variables qu'il utilise pour effectuer son travail sont en quelque sorte enfermés dans l'objet lui-même et on ne peut y avoir accès qu'à travers des procédures bien définies.

Les types de donnée sont déjà des objets rudimentaires. En dehors des types de données intégrés à FBSL, il est possible de créer de nouveaux types composites : les UDT ou User Defined Type (= type défini par l'utilisateur).

Définition d'un type de donnée élémentaire

Définissons un type Coor qui correspondant à la notion de « point » mathématique. Dans un espace à deux dimensions, un point est caractérisé par deux nombres : ses coordonnées x et y. En notation mathématique, un point est représenté par ses deux coordonnées x et y insérées entre parenthèses (x, y). Pour représenter ce point sous FBSL, on utilisera pour les coordonnées deux valeurs de type double :

Nous venons de définir un nouveau type de donnée : Coor, qu'on peut utiliser immédiatement.

- 43-

#AppType Console

Type Coorx As Doubley As Double

End Type

Pause

#AppType Console

Type Coor x As Double y As DoubleEnd Type

Dim p As Coor

p.x = 3p.y = 4

Print p.x, " ", p.yPrint p.x ^ 2 + p.y ^ 2

Print GetTypeName(p)

Pause

Un type peut en cacher un autre

On crée un nouveau type : Rectangle. Et pour spécifier le coin supérieur gauche on utilise le type déjà défini : Coor.

Cet exemple montre qu'une fonction peut utiliser un type comme paramètre et également transmettre un type comme valeur de retour. Ici la fonction TrouveCentre()est appelée avec un argument de type Rectangle et retourne un type Coor contenant les coordonnées du centre du rectangle.

Notez comment, depuis le début on assigne des valeurs aux variables des types en utilisant le système de qualification des noms par points, exemple : boite.largeur. Pour accéder à un type qui se trouve dans un autre type on utilise la qualification des noms hiérarchisée toujours à l'aide des points, exemple : boite.coin.x qui signifie en quelque sorte : aller vers le type référencé dans la variable boite, repérer la variable coin et aller vers le type qu'elle référence, et une fois ce type trouvé sélectionner sa variable x.

- 44-

#AppType Console

Type Coor x As Double y As DoubleEnd Type

Type Rectangle largeur As Double hauteur As Double coin As CoorEnd Type

Dim boite As Rectangleboite.largeur = 50boite.hauteur = 35boite.coin.x = 12boite.coin.y = 27

Print"largeur = ", boite.largeur, ", hauteur = ", boite.hauteurPrint "coordonnees du coin superieur gauche: x = ", boite.coin.x, ", y = ", boite.coin.y

Dim centre = TrouveCentre(boite)Print "coordonnees du centre: x = ", centre.x, ", y = ", centre.y

Print: Pause

Function TrouveCentre(figure) Dim p As Coor p.x = figure.coin.x + figure.largeur / 2 p.y = figure.coin.y + figure.hauteur / 2 Return pEnd Function

Les classes et les méthodes

Les types de données ne définissent en fait que des types de variables sans contenu ayant certaines choses en commun. Les classes, par contre définissent des variables qui peuvent avoir des valeurs par défaut et qu'on appelle parfois des attributs, elles définissent aussi des fonctions ou des procédures destinées à traiter ces données et qu'on appelle le plus souvent des méthodes.Les classes sont donc des sortes de modèles composées d'attributs et de méthodes (de variables et de procédures/fonctions) qui permettent de définir des objets qui seront des instances de cette classe. Il s'agit en fait de variables qui contiennent une nouvelle référence à la classe elle-même.

Par exemple, après avoir défini une classe Temps avec les attributs heure, minute, seconde, on crée un objet instant et on affecte des valeurs à ses variables d'instance. Puis, à l'aide d'une procédure AfficheTemps(), on visualise le contenu de l'objet sous la forme « heure:minute:seconde » :

Dans la mesure où l'on risque d'utiliser souvent des objets de la classe Temps, il serait plus pratique d'encapsuler la procédure AfficheHeure() dans la classe elle-même afin qu'elle soit disponible à chaque fois que l'on manipule des objet Temps.

Voici donc la nouvelle classe Temps avec sa méthode AfficheHeure() :

Remarquez comment on appelle la méthode AfficheHeure().

- 45-

#AppType Console

Class Temps heure, minute, secondeEnd Class

Dim instant As New Tempsinstant.heure = 11instant.minute = 34instant.seconde = 25

AfficheHeure(instant)

Pause

Sub AfficheHeure(t) Print t.heure, ":", t.minute, ":", t.secondeEnd Sub

#AppType Console

Class Temps heure, minute, seconde Method AfficheHeure() Print heure, ":", minute, ":", seconde End MethodEnd Class

Dim instant As New Temps

instant.AfficheHeure()

Pause

Notez également le résultat obtenu dans ce dernier exemple:

En effet, nous avons oublié d'affecter des valeurs aux attributs d'instance comme cela avait été fait dans le premier exemple. On peut éviter ce genre de problème en définissant des valeurs par défaut pour les variables d'instance à l'intérieur même de la classe.

C'est ici qu'une méthode particulière, qu'on appelle communément un constructeur, va nous être très utile. Cette méthode constructeur est une procédure qui est exécutée automatiquement lorsqu'on crée un nouvel objet à partir de la classe. On peut y placer tout ce qui est nécessaire pour initialiser automatiquement l'objet que l'on crée. La méthode constructeur doit s 'appeler obligatoirement Initialize.

On peut voir ici l'intérêt de cette technique. La méthode Initialize peut être dotée de paramètres comme n'importe quelle procédure/fonction. Ceux-ci permettent de créer une nouvelle instance et d'initialiser dans le même temps les variables d'instance. Si l'on veut transmettre à l'objet d'autres valeurs , il suffit de placer ces arguments dans les parenthèses qui accompagnent le nom de la classe lorsqu'on crée l'instance du nouvel objet. N.B. : il ne faut pas oublier l'opérateur New lors de l'instanciation, sinon le contenu de l'objet risque de ne pas être correctement initialisé.

Héritage

L'un des principaux avantages de la programmation orientée objet est que l'on peut se servir d'une classe déjà définie pour en créer une nouvelle qui possède des fonctionnalités différentes ou supplémentaires. Ce procédé, appelé dérivation, permet de créer toute une hiérarchie de classe allant du général au particulier.

- 46-

::Type Enter key to continue...

#AppType Console

Class Temps heure, minute, seconde Method Initialize(hh = 0, mm = 0, ss = 0) heure = hh minute = mm seconde = ss End Method

Method AfficheHeure() Print heure, ":", minute, ":", seconde End MethodEnd Class

Dim instant As New Temps(11, 15, 20)instant.AfficheHeure()

Dim moment As New Temps(8, 10)moment.AfficheHeure()

Pause

Par exemple, on définit d'abord une classe Mammifere qui contient un ensemble de caractéristiques propre à cette classe d'animaux. A partir de cette classe on dérive une classe Carnivore (et/ou Primate, Rongeur, etc.) qui hérite les caractéristiques de la classe Mammifere, en y ajoutant ses spécificités. En partant de la classe Carnivore, on peut dériver une classe Chien (et/ou Chat, Loup, etc.) qui hérite des caractéristiques de la classe parente avant d'y ajouter les siennes.

Dans cet exemple on peut voir comment l'objet mirza, qui est une instance de la classe Chien, hérite non seulement de l'attribut défini pour cette classe mais également des attributs définis pour les classes parentes (ou super-classes).

On voit aussi comment il faut procéder pour dériver une classe à partir d'une classe parente : dans chaque classe dérivée, on crée une instance de la classe parente (que l'on nommera ici super pour « super-classe »).

On peut noter encore que les attributs utilisés dans l'exemple sont les attributs des classes et non des attributs d'instance. L'instance mirza peut accéder à ces attributs, mais pas les modifier. Lorsqu'on modifie caract2 pour mirza, on ne modifie pas l'attribut caract2 de la classe Carnivore. On vérifie d 'ailleurs cela en créant une nouvelle instance fido, et en affichant le caract2 de fido.

En fait mirza peut accéder aux variables situées dans son propre espace de noms, mais aussi à celles qui sont situées dans les espaces de noms de toutes les classes parentes. S'il existe des variables aux noms identiques dans plusieurs de ces espaces, FBSL utilise une règle de priorité très simple. Quand on lui

- 47-

#AppType Console

' Héritage :Class Mammifere caract1 = "il allaite ses petits ; "End Class

Class Carnivore super = New Mammifere ' super = super-classe ou classe parente caract1 = super.caract1 caract2 = "il se nourrit de la chair de ses proies ; "End Class

Class Chien super = New Carnivore caract1 = super.caract1 caract2 = super.caract2 caract3 = "son cri s'appelle aboiement ; "End Class

Dim mirza As New ChienPrint mirza.caract1Print mirza.caract2Print mirza.caract3Print

' Modification de 'caract2' pour Mirza :mirza.caract2 = "son corps est couvert de poil ; "Print "MIRZA - caract2 = ", mirza.caract2

Dim fido As New ChienPrint "FIDO - caract2 = ", fido.caract2

Print: Pause

demande d'utiliser la valeur d'une variable nommée x, par exemple, il commence par rechercher ce nom dans l'espace local. Si une variable x est trouvée dans l'espace local, c'est elle qui sera utilisée et la recherche s'arrête. Sinon FBSL examine l'espace de la structure parente et ainsi de suite jusqu'au niveau principal. Voilà pourquoi mirza.caract2 et fido.carat2 sont différents à la fin de l'exemple précédent.Autre exemple, avec des attributs et des méthodes hérités :

- 48-

#AppType Console

Class Rectangle longueur, largeur, nom Method Initialize(_long = 30, _larg = 15, _nom = "rectangle") longueur = _long largeur = _larg nom = _nom End Method Method perimetre() Return(longueur + largeur) * 2 End Method Method surface() Return(longueur * largeur) End Method Method mesures() Print Print "Un ", nom, " de ", longueur, " sur ", largeur Print "a une surface de ", surface(), " et un perimetre de ", perimetre() Print End MethodEnd Class

Class Carre ' Un carre est un rectangle spécial cote, nom, super ' super = super-classe ou classe parente Method Initialize(_cote = 10, _nom = "carre") cote = _cote nom = _nom super = New Rectangle(cote, cote, nom) End Method Method mesures() super.mesures() End MethodEnd Class

Dim fig1 = New Rectangle(27, 12)fig1.mesures()

Dim fig2 = New Carre(13)fig2.mesures()Pause

Similitude et unicité

Dans le langage parlé, un même mot peut avoir des significations différentes selon le contexte dans lequel on l'utilise. Une expression utilisant ce mot peuvent être comprise de plusieurs manières différentes, on dit qu'il s'agit d'une expression ambiguë. Par exemple le mot « même » a un sens différent dans les phrases : « Charles et moi avons la même voiture » et « Charles et moi avons la même mère ». Dans la première phrase, la voiture de Charles et la mienne sont du même modèle, mais il y a bien deux voitures distinctes. Dans la deuxième phrase, la mère de Charles et la mienne constituent en fait une seule et unique personne.On peut rencontrer la même ambiguïté lorsqu'il s'agit d'objets (logiciels). Par exemple si l'on parle d'égalité de deux objets Coor(), est-ce que cela veut dire que ces deux objets contiennent les mêmes données ou attributs, ou bien cela veut-il dire qu'il s'agit de deux références à un même et unique objet ?

Examinons l'exemple suivant :

On crée ici deux objets p1 et p2 qui sont distincts, même si leur contenu est similaire. Lorsque l'on teste l'égalité de ces deux objets (signe =), le résultat est 1, soit TRUE (vrai), ce qui signifie que les deux variables ont un même contenu. Cependant en utilisant l'opérateur Is, qui permet de comparer deux instances d'objet, le résultat est 0 (FALSE = faux), ce qui indique que les deux objets sont distincts.

Maintenant si on fait :

on assigne le contenu de p1 à p2. Les deux variables référencent le même objet. Le test d'égalité renvoie 1 parce que p1 et p2 ont le même contenu. L'opérateur Is indique ici qu'il s'agit du même objet.N.B. : On peut utiliser ici la fonction GetTypeName(), que l'on a vu au chapitre 4, par exemple : GetTypeName(p1) qui retournera ici le nom de la classe (ou du type) originale, soit Coor.

- 49-

#AppType Console

Class Coorx, yMethod Initialize(_x = 0, _y = 0)

x = _xy = _y

End MethodEnd Class

Dim p1 As New Coor(3, 4)Dim p2 As New coor(3, 4)Print p1 = p2 ' => 1 (=TRUE)Print p1 Is p2 ' => 0 (=FALSE)

Pause

#AppType Console

Class Coorx, yMethod Initialize(_x = 0, _y = 0)

x = _xy = _y

End MethodEnd Class

Dim p1 As New Coor(3, 4)Dim p2 = p1Print p1 = p2 ' => 1 (=TRUE)Print p1 Is p2 ' => 1 (=TRUE)

Pause

La surcharge des opérateurs

Qu'est-ce que c'est ? C'est une technique qui permet de réaliser des opérations mathématiques intelligentes entre des objets lorsqu'on utilise dans un programme des symboles comme +, -, *, etc. Les opérateurs surchargés remplacent avantageusement les appels de fonction, ils rendent le code plus court et plus clair, donc plus lisible.

FBSL utilise l'opérateur Operator pour surcharger les opérateurs suivant : + - * / = <= >= AND OR NOT XOR.

Pour illustrer le principe, on va d'abord créer une nouvelle classe, similaire à la classe Temps défini plus haut, mais qu'on appellera Duree. Le but étant de pouvoir additionner deux durées au format heure minute seconde (exemple tiré du Site du Zéro).

On pourrait évidemment créer une fonction Additionner(duree1, duree2) qui retournerait une valeur correspondant à la somme de duree1 et duree2.

Mais, pour être plus lisible, on veut pouvoir écrire :

comme si les objets duree étaient de simples nombres. Les objets étant plus complexes que les nombres, il va falloir expliquer à l'ordinateur les détails de l'opération.

Voici la première partie du script qui définit la classe Duree et les deux objets duree1 et duree2 :

Nous sommes maintenant prêt à aborder la surcharge des opérateurs. Pour pouvoir utiliser le symbole + entre deux objets, il faut créer une méthode ayant précisément pour nom Operator+().

- 50-

Resultat = Additionner(duree1, duree2)

Resultat = duree1 + duree2

#AppType Console

Class Dureeheure, minute, secondeMethod Initialize(hh = 0, mm = 0, ss = 0)

heure = hhminute = mmseconde = ss

End MethodMethod Affiche()

Print heure, "h", minute, "m", seconde, "s"End Method

End Class

Dim duree1 As New Duree(0, 10, 28), duree2 As New Duree(0, 15, 2)duree1.Affiche()duree2.Affiche()

Pause

Ce script n'est qu'une ébauche dont le but est d'expliquer sommairement comment on peut réaliser la surcharge des opérateurs avec FBSL. Quelques améliorations pourraient, et devraient, y être apportées. Par exemple :

● le contrôle des attributs de la classe Duree elle-même, et notamment les champs minute et seconde dont les valeurs doivent être calculées pour ne pas dépasser 59. Par exemple : Duree(9, 69, 70) devrait afficher 10h10m10s.

● le contrôle de l'opérateur + qui ne devrait accepter que des objets Duree, ou éventuellement un nombre entier que l'on pourrait ajouter au nombre de secondes. Dans les autres cas il renverrait un message d'erreur.

- 51-

#AppType Console

Class Dureeheure, minute, secondeMethod Initialize(%hh = 0, %mm = 0, %ss = 0)

heure = hhminute = mmseconde = ss

End Method

Method Affiche()Print heure, "h", minute, "m", seconde, "s"

End Method

Operator+(obj)' (1) Ajout des secondes :seconde = seconde + obj.seconde'Si le nombre de secondes dépasse 60, on rajoute des minutes 'et on met un nombre de secondes inférieur à 60minute = minute + seconde / 60seconde = seconde Mod 60' (2) Ajout des minutes :minute = minute + obj.minute'Si le nombre de minutes dépasse 60, on rajoute des heures'et on met un nombre de minutes inférieur à 60heure = heure + minute / 60minute = minute Mod 60' (3) Ajout des heures :heure = heure + obj.heure' Retour du résultat :Return New Duree(heure, minute, seconde)

End OperatorEnd Class

Dim duree1 As New Duree(0, 10, 28), duree2 As New Duree(0, 15, 2)duree1.Affiche()Print "+"duree2.Affiche()Print "="

Dim resultat = duree1 + duree2resultat.Affiche()

Print: Pause

Voici un exemple de correction du script précédent :

Il faut remarquer aussi l'opérateur $ qui remplace avantageusement la méthode Affiche() du premier script.

- 52-

#AppType Console

Class Dureeheure, minute, secondeMethod Initialize(%hh = 0, %mm = 0, %ss = 0)

heure = hhminute = mmseconde = ssminute = minute + seconde/60seconde = seconde Mod 60heure = heure + minute/60minute = minute Mod 60

End Method

Operator$()Return %heure & "h" & %minute & "m" & %seconde & "s"

End Operator

Operator+(obj)If obj Is Duree Then

' (1) Ajout des secondes :seconde = seconde + obj.secondeminute = minute + seconde/60seconde = seconde Mod 60' (2) Ajout des minutes :minute = minute + obj.minuteheure = heure + minute/60minute = minute Mod 60' (3) Ajout des heures :heure = heure + obj.heureReturn New Duree(heure, minute, seconde)

ElseIf GetType(obj) = FBVT_INTEGER Thenseconde = seconde + objminute = minute + seconde/60seconde = seconde Mod 60heure = heure + minute/60minute = minute Mod 60Return New Duree(heure, minute, seconde)

ElsePrint obj, " n'est pas un objet <Duree> ou un entier"

End IfEnd Operator

End Class

Dim chrono As New Duree(9, 69, 70)Print $chronoPrint "+"Print "80"Print "="

Dim resultat = chrono + 80Print $resultat

Print: Pause

La définition de la classe elle-même peut paraître compliquée mais son utilisation rend les choses plus agréables au niveau du code principal. On peut dire que la surcharge des opérateurs facilite surtout la vie des utilisateurs d'une classe mais peut-être moins celle du développeur de la classe ;-)

Maintenant que l'on a vu en détail le cas d'un opérateur (celui d'addition), il ne sera pas trop difficile de programmer la surcharge d'autres opérateurs dans la mesure où ils sont compatibles avec le type d'objet défini. Si les opérateurs * et / ne semblent pas avoir leur place ici, en revanche on peut tenter de surcharger l'opérateur – (soustraction).

L'exemple, plus complet, qui se trouve dans le fichier d'aide de FBSL (OPERATORS/Operator) sera utile pour donner quelques pistes en ce sens.

Chapitre 9. Les méta-directives Une directive est une instruction destinée au préprocesseur. Un préprocesseur est un programme qui procède à des transformations sur un code source, avant l'étape de compilation ou d'interprétation proprement dite. Le préfixe méta introduit une idée de réflexion ou d'auto-référencement, une méta-directive est donc une sorte de directive de directive ... Autrement dit tout ce qui sera déclaré à l'aide de directives pourra être considéré comme faisant partie du langage FBSL avant que celui-ci n'interprète le reste du script.

C'est beaucoup moins compliqué qu'il n'y paraît, d'autant plus que depuis le début de cette exploration de FBSL nous en avons déjà rencontrées, et même utilisées couramment, quelques-unes : #AppType, #Option, #EscapeChars et NameSpace.

Voici trois autres directives non moins intéressantes et aux possibilités étonnantes.

Les définitions

#Define permet de définir un identificateur comme équivalent au texte qui le suit. L'identificateur est un nom symbolique, comme un nom de variable par exemple, et le texte qui le suit immédiatement doit correspondre à une constante littérale comme un nombre, une chaîne de caractères, un autre identificateur ou même un mot-clé.

Exemple :

Dans cet exemple on s'apperçoit que #Define se comporte un peu comme Const . Cependant Const crée une nouvelle variable (protégée) et la stocke en mémoire alors qu'avec #Define, toutes ses occurrences sont remplacées directement dans le code par le préprocesseur. Il en résulte une plus grande rapidité du code et une moindre consommation de mémoire à l'exécution du programme. Il faudra donc préférer #Define à Const le plus souvent possible.

- 53-

#AppType Console

#Define HELLO "Bonjour, tout le monde !"Print HELLO

HELLO = "Salut"Print HELLO

Pause

#Define permet aussi de changer le nom des mots-clés et de certaines commandes de FBSL :

On pourrait ainsi traduire toutes les commandes de FBSL en français en créant un fichier inclus composé de toutes les définitions nécessaires. Cette propriété a un intérêt certain lorsqu'on souhaite transcrire un programme vers FBSL depuis un autre langage de programmation.

#Undef permet de supprimer l'identificateur défini précédemment par #Define :

Les déclarations

Dans le même ordre d'idée, Declare permet de créer le synonyme d'un nom de fonction existante. Il s'agit d'une nouvelle référence à ce nom. Son utilité est aussi le portage d'un script depuis un autre langage de programmation vers FBSL.

Declare fait à peu prés la même chose que #Define, mais seulement en ce qui concerne le renommage de fonction.

- 54-

#AppType Console

#Define ECRIS Print#Define SI If#Define ALORS Then#Define FIN End

Dim a = 1

SI a ALORSECRIS "a = ", a

FIN SI

Pause

#AppType Console

#Define HELLO "Bonjour, tout le monde !"Print HELLO

#Undef HELLO

Dim HELLO = "Salut"Print HELLO

Pause

#AppType Console

Declare Droite As Right? Droite("Bonjour", 4)'le synonyme? Right("Bonjour", 4) 'l'original

Pause

Les macros

Macro est un peu plus sophistiqué et permet de créer des pseudo-fonctions, en tant que méta-directive, donc différentes des fonctions et procédures définies avec Function et Sub. En fait on crée une nouvelle fonction, avec ses paramètres, à partir d'autres fonctions existantes et leurs paramètres.

Des exemples utiles se trouvent dans le fichier Fbsl.inc ( C:\Program Files\FBSLv3\Include\Fbsl.inc) :

qui permet d'afficher les accents dans la console.

permet de programmer plus facilement et plus rapidement une boîte de message.

Les macros permettent donc de simplifier ou de personnaliser des fonctions complexes, parfois peu lisibles du fait de leur imbrication l'une dans l'autre ou parce qu'elles sont importées depuis d'autres programmes ou de bibliothèques à la syntaxe moins claire, comme dans le deuxième exemple.

Ce petit programme illustre l'utilité des macros :

(bougez la souris dans la fenêtre qui s'affiche et observez la barre de titre)

Chapitre 10. Créer des exécutablesUn script FBSL a la capacité de s'auto-compiler en un fichier exécutable (extension .exe) 100% autonome. Il s'agit d'un fichier-programme qui ne dépend pas de l'installation de FBSL pour s'exécuter.

En fait, l'exécutable en question « emballe » d'une certaine manière une copie de FBSL.exe, du fichier script (.fbs) et des fichiers inclus (.inc) éventuels qui lui sont associés pour former un seul fichier (.exe), exécutable même sur une machine où FBSL n'est pas installé.

On peut compiler un script de plusieurs manières:

● directement depuis Eclecta Editor (Compile/Compile script ou touche F9), mais il semble que cette façon de faire génére des exécutables d'un peu plus de 400ko.

● par le menu contextuel (clic droit sur un fichier .fbs). Les exécutables produits sont plus légers (moins de 150ko) car les fichiers sont compressés

● en utilisant le programme FBSL Compiler fourni avec la distribution, qui permet en plus de choisir une icône personnalisée pour le programme, et la compression du fichier .exe comme ci-dessus.

- 55-

MACRO AFXACCENTS(s) = WideToAnsi( AnsiToWide(s, CP_ACP), CP_OEMCP )

MACRO Alert(msg, titre) = Apicall( "MessageBoxA", "user32", Null, msg, titre, MB_OK + MB_ICONINFORMATION )

Macro MouseXY(fen) = Fbsl_SetText(fen, "X=" & Lpad(LoWord(CBLPARAM), 4, "0") & " Y=" & Lpad(HiWord(CBLPARAM), 4, "0"))

Resize(ME, 0, 0, 250, 250): Center(ME): Show(ME)

Begin EventsIf CBMSG = WM_MOUSEMOVE Then

MouseXY(ME)End If

End Events

Conclusion

Ainsi s'achève ce bref aperçu de FBSL. Bref car il ne fait que survoler une toute petite partie des possibilités de ce langage de programmation, chacun des domaines abordés pouvant faire l'objet d 'un tutoriel plus approfondi. Par ailleurs un certain nombre de caractéristiques, et non des moindres n'ont pas été évoquées dans ces pages, soit pour ne pas encombrer un tutoriel qui se veut d'abord une découverte en douceur de FBSL, soit parce que mon expérience et mes compétences actuelles, provisoirement limitées, ne me permettent pas d'aller plus loin dans le partage de mes découvertes personnelles.

Le fichier d'aide qui accompagne la distribution de FBSL est assez complet et permet de comprendre, grâce à ses nombreux exemples, la plupart des fonctions et commandes du langage.

Les meilleurs tutoriels sont les exemples simples et précis que l'on peut trouver dans le fichier d'aide mais aussi dans le dossier Samples. Tester, explorer, décortiquer et aussi (et surtout) modifier ces exemples est très utile dans la compréhension des fonction et des « mécanismes » de FBSL, très enrichissant dans l'apprentissage de la programmation en général.

Une autre source d'aide conviviale, riche, vivante et dynamique est le forum FBSL où l'on peut poser des questions, trouver des réponses, découvrir des trucs et astuces diverses, proposer des scripts, ou simplement échanger avec les auteurs et les utilisateurs de FBSL. N'hésitez pas à rejoindre le forum même si vous ne maîtrisez pas tout à fait l'anglais (langue officielle du forum); un exemple concret et quelques mots suffisent parfois à faire passer le message ou bien contacter en message privé un utilisateur francophone ;)

Expérimentez, testez, programmez et surtout amusez-vous avec FBSL !

« Découvrir FBSL », version 2.2

Novembre 2008

Bertrand Carette alias Taobert

~Merci à Gerome et à Mehdi pour leurs conseils avisés et pour les indispensables corrections~

La reproduction partielle ou totale de ce document est autorisée uniquement pour un usage privé et/ou didactique. Toute modification, amélioration ou traduction est également autorisée à la condition que les conditions d'utilisation sus-citées soient respectées et mentionnées sur le nouveau document.

- 56-

Addenda

La méta-directive : #Uses

La méta-directive #Uses a été introduite dans la version 3.3.4.2 de FBSL (juin 2008). Elle permet d'inclure un ou plusieurs fichiers dans le script courant lors de l'exécution. Si un des fichiers en question n'existe pas, un avertissement est donné.

Il s'agit en fait de fichiers XML qui doivent ressembler à ceci :

Chaque balise <content> doit contenir des données encodées en Base64.

Par ailleurs, il faut désormais écrire la ligne #Uses "@|WIN32" en haut de chaque script FBSL censé utiliser des define comme WM_CLOSE, WS_CHILD, IDYES, etc., etc., afin de pouvoir indiquer à FBSL qu'il doit charger et remplacer toutes les définitions WIN32 à la fois. Ainsi le script est prêt à fonctionner.

On peut également inclure d'autres « bibliothèques » en fonction des besoins du script :

Lorsqu'on crée un nouveau fichier dans Eclecta Editor, la ligne précédente est automatiquement affichée. Il suffit de faire son choix en commentant ou dé-commentant (ou en effaçant) les options souhaitées. La plupart du temps, si l'on projette de programmer une interface graphique, il vaudra mieux conserver la toute première partie de la ligne, qui concerne les définitions WIN32.

Les tables de hachage ou hash tables

Qu'est-ce que c'est ?

Il s'agit d'une structure de données permettant une association clé-valeur, une sorte de tableau associatif, appelé aussi table d'associations ou dictionnaire.

N.B. : Une structure de données est une structure logique destinée à contenir des données, afin de leur donner une organisation permettant de simplifier leur traitement.

A partie de la version 3.3.5.8 FBSL introduit de nouvelles fonctions permettant de gérer ces tableaux particuliers très pratiques lorsqu'on doit traiter un très grand nombres d'éléments.

- 57-

<?xml version='1.0'?><database name='FBSLLIB' description='' version='1.0'>

<elements><content id='TEST1' lz='0'>PyAiSGVsbG8xIg==</content><content id='TEST2' lz='0'>PyAiSGVsbG8yIg0K=</content><content id='TEST3' lz='0'>PyAiSGVsbG8zIg0K</content>

</elements></database>

#Uses "@|WIN32" '|COLLECTION|CONTROLS|QUEUE|REGISTRY|STACK|STRINGCOLLECTION

Voici quelques exemples basiques permettant de mieux comprendre l'utilité et le fonctionnement des hash tables, appelées ici table ou dictionnaire pour plus de commodité.

Création d'un dictionnaire de langue pour la traduction des termes informatiques anglais en français.

On commence par créer un dictionnaire en indiquant le nombre approximatif d'éléments (clé + valeur) qui le composeront. On pourra toujours par la suite « retailler » ou redimensionner ce dictionnaire.

On parcourt le dictionnaire à l'aide d'une simple boucle de type For...Next, de 1 jusqu'au nombre d'éléments réels (ou noeuds/nodes) du dictionnaire, en invoquant Hash_GetKey pour retrouver les clés et Hash_GetData pour obtenir les valeurs.

La fonction Hash_Get permet de retrouver une valeur en « interrogeant » directement la clé à laquelle elle est associée.

Si l'on a besoin de parcourir fréquemment un dictionnaire, on créera une procédure générique d'affichage :

La fonction Hash_Count retourne le nombre d'éléments ayant été insérés dans la table, et non pas sa capacité totale, définie avec Hash_Create ou modifiée avec Hash_Resize. Pour obtenir la capacité totale de la table on utilisera la fonction Hash_Capacity.

- 58-

#AppType Console#Option Strict

'' Création d'un dictionnaireDim dico, i

dico = Hash_Create(10)Hash_Insert(dico, "computer", "ordinateur")Hash_Insert(dico, "mouse", "souris")Hash_Insert(dico, "keyboard", "clavier")

Print "dico => ";For i = 1 To Hash_Count(dico)

Print Hash_GetKey(dico, i), ": ", Hash_GetData(dico, i), " ";NextPrint: Print

Print Hash_Get(dico, "mouse")

Pause

Sub Hash_Print(table)Dim iFor i = 1 To Hash_Count(table)

Print Hash_GetKey(table, i), ": ", Hash_GetData(table, i), " ";NextPrint

End Sub

Les exemples suivants décrivent quelques opérations courantes réalisées sur les tables ou dictionnaires : insertion ou suppression d'éléments, redimensionnement d'une table, copie d'une table, etc.

- 59-

#AppType Console#Option Strict

'' Opérations sur les dictionnairesDim invent = Hash_Create(10)

Hash_Insert(invent, "pommes", "430")Hash_Insert(invent, "bananes", "312")Hash_Insert(invent, "oranges", "274")Hash_Insert(invent, "poires", "137")

Print "invent => ";Hash_Print(invent)Print: Print

' enleve le noeud associatif 'pommes'Hash_Remove(invent, "pommes") ' On efface l'espace laisser vide en redimensionnant la tableHash_Resize(invent, Hash_Count(invent) - 1)

Print "invent => ";Hash_Print(invent)Print: Print

If Hash_Get(invent, "pommes") <> "" ThenPrint "Nous avons des pommes"

ElsePrint "Desole, pas de pommes"

End IfPrint: Print

Pause

Sub Hash_Print(table)Dim iFor i = 1 To Hash_Count(table)

Print Hash_GetKey(table, i), ": ", Hash_GetData(table, i), " ";NextPrint

End Sub

- 60-

#AppType Console#Option Strict

Dim invent = Hash_Create(10)

Hash_Insert(invent, "pommes", "430")Hash_Insert(invent, "bananes", "312")Hash_Insert(invent, "oranges", "274")Hash_Insert(invent, "poires", "137")

'' Copier une tableDim stock = inventPrint "stock => ";Hash_Print(stock)Print: Print

' si on modifie 'invent', alors 'stock' aussi est modifié (et vice-versa)Hash_Remove(invent, "bananes")Hash_Resize(invent, Hash_Count(invent) - 1)

Print "stock => ";Hash_Print(stock)Print: Print

' pour obtenir une vraie copie (indépendante) d'une table préexistante :Dim magasin = Hash_Create(Hash_Count(stock) + 1), iFor i = 1 To Hash_Count(stock)

Hash_Insert(magasin, Hash_GetKey(stock, i), Hash_GetData(stock, i))Next

Hash_Insert(magasin, "prunes", "561")

Print "magasin => ";Hash_Print(magasin)Print: Print

Print "stock => ";Hash_Print(stock)Print: Print

Print "invent => ";Hash_Print(invent)Print: Print

Pause

Sub Hash_Print(table)Dim iFor i = 1 To Hash_Count(table)

Print Hash_GetKey(table, i), ": ", Hash_GetData(table, i), " ";NextPrint

End Sub

Encore un autre exemple dans lequel les éléments d'une table sont d'abord stockés dans un tableau dynamique puis insérés dans la table à l'aide d'une procédure.

La table foret est dimensionnée à 1 lors de sa création. Elle est ensuite redimensionnée par la procédure Hash_AddItems après chaque insertion d'un élément ou noeud (clé+valeur) depuis le tableau dynamique arbres.

La procédure Hash_AddItems parcoure le tableau arbres par pas de deux et insère chaque item par paire dans la table d'associations foret. Le premier élément de chaque paire est la clé, le second est la valeur ou la donnée.

- 61-

#AppType Console#Option Strict

Dim foret = Hash_Create(1)Dim arbres ={"1x2", "peuplier", "3x4", "platane", "6x5", "palmier", "5x1", "cycas", "7x3", "sapin"}

Hash_AddItems(foret, arbres)

Hash_Print(foret)

Print "Quel arbre est en 1x2 -> ", Hash_Get(foret, "1x2") ' peuplierPrint "Quel arbre est en 2x1 -> ", Hash_Get(foret, "2x1") ' aucun (vide)

Pause

Sub Hash_AddItems(table, items)'' Construit une table depuis un tableauDim iFor i = 0 To(Count(items) - 1) Step 2

Hash_Insert(table, items[i], items[i + 1])Hash_Resize(table, Hash_Count(table) + 2)

Next iEnd Sub

Sub Hash_Print(table)'' Affiche le contenu d'une tableDim iFor i = 1 To Hash_Count(table)

Print Hash_GetKey(table, i), ": ", Hash_GetData(table, i)NextPrint

End Sub

Un dernier exemple qui utilise deux nouvelles fonctions : Hash_ContainsKey qui permet de tester si la table contient ou non la clé spécifiée et Hash_SetData qui met à jour le contenu (la valeur) d'une clé existante.

- 62-

#AppType Console#Option Strict

Dim texte = "freestyle basic script language"Dim lettres = Hash_Create(StrLen(texte))

Dim k, v, i

For i = 1 To StrLen(texte)k = texte{i}If Hash_ContainsKey(lettres, k) Then

v = Val(Hash_Get(lettres, k)) + 1Hash_Setdata(lettres, k, $v)

Elsev = 1Hash_Insert(lettres, k, $v)

End IfNext

Print "texte = ", textePrintPrint "lettres :"For i = 1 To Hash_Count(lettres)

Print "'", Hash_GetKey(lettres, i), "': ", Hash_GetData(lettres, i)NextPrint

Pause