Bienvenue
Présentation
SBASIC est un interpréteur très rapide et très complet. Il s’utilise comme la plupart des BASIC interprétés :
- En mode immédiat, il exécute directement les ordres entrés au clavier, ce qui permet de l’utiliser interactivement comme un calculateur.
- En mode programme, les lignes, entrées au clavier, permettent de construire le programme qui sera par la suite lancé au moyen de la commande RUN.
Nous recommandons à l’utilisateur de lire l’ensemble du présent manuel avant de travailler sous SBASIC. Nous y avons inclus de nombreux exemples afin de le rendre plus accessible à la majorité des lecteurs.
SBASIC diffère d’un BASIC ordinaire par l’adjonction d’un certain nombre de mots-clés et de commandes qui en font un outil puissant de programmation. Citons par exemple, l’usage des procédures, du mode trace, de la renumérotation partielle, de l’édition de la table des variables, etc.
SBASIC apporte ainsi une dimension et un confort nouveaux à la programmation en BASIC.
Concepts généraux
SBASIC autorise la manipulation de trois types d’objets différents. Des entiers, des réels et des chaînes de caractères. Les deux premiers types permettent de représenter des nombres alors que le troisième permet de travailler sur du texte. Tous ces objets sont stockés en mémoire à l’aide d’octets (groupes de 8 bits), chacun d’entre eux pouvant représenter un nombre compris entre 0 et 255 inclus.
Types
Type entier
Le type Entier
permet de stocker des nombres entiers signés pouvant être codés sur quatre octets, c’est à dire des nombres entiers compris entre -2147483648 et 2147483647. Ils sont représentés en complément à deux, sur 4 octets consécutifs de la mémoire centrale, mais il faut prendre garde au fait que l’ordre dans lequel ces derniers sont utilisés dépend de la machine et même du système utilisé.
Type réel
Le type Réel
permet de stocker toutes les autres valeurs numériques. Cette méthode de codage est aussi appelée représentation en virgule flottante. Elle utilise 8 octets par valeur (6,5 pour la mantisse et 1,5 pour l’exposant) et permet de représenter des nombres approximativement compris entre 10-300 et 10300.
Type chaîne de caractères
Le type Chaîne de caractères
permet de stocker du texte dont l’utilisateur aura besoin pour documenter les résultats d’un programme de calcul ou sur lequel il aura envie de travailler avant de l’éditer. Chaque caractère de texte est alors codé sur un octet (codage ASCII international).
Ce type est souvent appelé type Chaîne
, ou encore type Alphanumérique
.
Constantes, Variables, Tableaux
Constantes
Une valeur utilisée sous forme de Constante doit être décrite lors de chacune de ses utilisations. Cette description doit respecter les règles suivantes :
Constantes de type entier
Pour une constante de type Entier la valeur doit être écrite en décimal et représenter un nombre entier compris entre -2147483648 et 2147483647. Les seuls symboles permis sont donc les chiffres de 0 à 9, l’espace et le signe + ou le signe - (placés en tête).
L’utilisation du point décimal provoque un codage en virgule flottante, même s’il n’est suivi d’aucun chiffre.
Les descriptions suivantes de constantes entières sont correctes :
12
+15
31000
-57
-2545
Les descriptions suivantes sont incorrectes :
12. # codage en virgule flottante à cause du point décimal
10000000000 # entier supérieur à 2147483647
Constante de type réel
Pour une constante de type Réel la valeur peut, au gré de l’utilisateur, être décrite sous forme décimale ou sous forme scientifique.
Sous forme décimale on utilisera donc les chiffres de 0 à 9, l’espace, le signe + ou le signe - et le point décimal exactement comme dans la vie courante (anglo-saxonne !).
L’écriture sous forme scientifique est recommandée pour des nombres très grands ou très petits en valeur absolue, mais elle peut être utilisée pour toute valeur numérique. En plus des symboles précédents elle tolère la lettre E (majuscule ou minuscule) qui permet de séparer la mantisse de l’exposant. Une constante de type réel doit être comprise entre 10-127 et 10+127.
Les descriptions suivantes de constantes réelles sont correctes :
3.14159
-6.25
+12.
6.02E 23
1 E 27
Les deux dernières valeurs sont respectivement égales à : 6.02 x 10^23 et 10^27
Les descriptions suivantes sont incorrectes :
12,5 # utilisation de la virgule
5.23E10+2 # utilisation du signe + dans l’exposant
Constantes de type chaîne de caractères
La description d’une constante de type Chaîne de caractères peut utiliser tous les caractères obtenus à partir du clavier, mais elle doit débuter et se terminer par des guillemets (ou des apostrophes) ; ces signes ne font pas partie de la chaîne, ils permettent simplement de la délimiter.
Dans une constante chaîne on peut trouver une ou plusieurs occurrences de guillemets ; une telle constante doit alors être délimitée par des apostrophes et ne peut contenir aucune apostrophe. De même il est possible d’y placer des apostrophes, à condition de la délimiter par des guillemets, mais on ne peut alors y trouver aucun guillemet.
Les descriptions suivantes de constantes chaînes sont correctes :
"Vive le SBASIC"
"La lettre 'E' "
'Dites "Bonjour"'
Les descriptions suivantes sont incorrectes :
"A bas le SBASIC
'lettre"
'la lettre "A" et l'apostrophe'
Variables
On utilise une variable pour manipuler des valeurs qu’on ne veut pas ou qu’on ne peut pas décrire lors de chacune de ses utilisations. Ce peut être parce que la valeur est longue et donc fastidieuse à décrire, ou parce qu’elle dépend du cheminement suivi lors de l’exécution du programme et que le programmeur n’est pas capable de la décrire lors de l’écriture de ce dernier.
Dans ce cas la valeur en cause est manipulée par l’intermédiaire d’un identificateur appelé « nom de variable ». Le programmeur se trouve dans la situation d’un manutentionnaire qui travaille sur des boîtes dont il ne connaît pas vraiment le contenu, mais qu’il repère par un nom ou un numéro écrit sur cette dernière (nom de variable) et qui seul lui permet de distinguer une boîte d’une autre. Ce qui se trouve dans la boîte y a été mis par quelqu’un d’autre à un autre moment (affectation de la variable).
Pour pouvoir utiliser des variables, il faut connaître les règles qui régissent la formation de leurs noms et la façon de leur affecter une valeur.
Noms de variables
Un nom de variable se construit en respectant les règles suivantes :
- Un nom de variable doit être une suite d’au plus 255 caractères pris parmi les lettres de l’alphabet, le caractère souligné « _ », les chiffres et les symboles réservés « % » et « $ ».
- Le premier caractère doit être une lettre de l’alphabet, les suivants peuvent être des lettres, « _ » ou des chiffres, seul le dernier peut être « % » ou « $ ».
- Deux suites différentes permettent de gérer des variables différentes. Tous les caractères sont discriminatoires. Si des lettres minuscules sont utilisées lors de la saisie, elles sont automatiquement converties en majuscules. La chasse des lettres n’est donc pas discriminatoire.
- Un nom de variable ne doit pas commencer par un mot réservé du SBASIC. Voir la liste des mots réservés se trouvant en « Annexe 2 : Liste des codes d’erreurs réservés ».
- Les variables dont le nom se termine par le symbole « % » ne pourront être utilisées que pour contenir des valeurs de type entier.
- Celles dont le nom se termine par « $ » devront avoir un contenu de type chaîne de caractères.
- Les autres variables permettent de manipuler les valeurs réelles.
Exemples de noms de variables syntaxiquement corrects :
-
Variables de type entier :
KILO% N% NOMBRE_PAR_KILO%
-
Variables de type réel :
VITESSE X POIDS_AU_LITRE
-
Variables de type chaîne :
TXT$ A$ LIGNE_COURANTE$
Exemples de noms de variables incorrects :
1AB, $, événement # ne commence pas par une lettre majuscule
A%B$, A/B # comporte des symboles interdits
TOTAL%, TABLEAU # commence par un mot réservé, « TAB » ou « TO »
Affectation
La première chose à faire lorsque l’on utilise une variable est de lui Affecter une valeur, c’est à dire, en poursuivant la comparaison entre variables et boîtes, de mettre quelque chose dans la boîte sur laquelle est inscrit le nom de la variable.
Une telle opération se fait à l’aide d’une instruction d’affectation qui peut être effectuée par l’un des mots réservés LET, INPUT ou READ entièrement décrits dans la suite de ce manuel. Toutefois, on peut dès à présent brièvement décrire l’utilisation de LET et de INPUT.
LET var
= exp
permet d’affecter à la variable de nom-var
la valeur de l’expression exp qui doit être de même type.
Par exemple :
LET A=1 # affecte à la variable A la valeur 1
LET NOM$="toto" # affecte à la variable A$ la valeur "toto"
LET VI=12.5 # affecte à la variable réelle VI la valeur 12,5
Nous rencontrons ici le premier exemple de la syntaxe que nous utiliserons tout au long de cet ouvrage pour décrire les différentes instructions de SBASIC. La mise en avant
permet de représenter un objet SBASIC que l’utilisateur devra remplacer lors de l’écriture d’un programme par un objet correspondant à cette description.
Ici, nous avons utilisé var
qui doit être remplacé par un nom de variable SBASIC syntaxiquement correct. De même exp
devra, lui, être remplacé par une expression quelconque dont l’exemple le plus simple est une constante.
Il est possible, dans les instructions précédentes, d’omettre le mot réservé LET et d’écrire respectivement pour chacune des trois affectations précédentes :
A=1
NOM$="toto"
VI=12.5
Nous verrons ultérieurement que l’on peut, à droite du signe « = » utiliser des expressions plus complexes que de simples constantes, mais à gauche de ce signe on doit uniquement trouver un nom de variable.
Par exemple, l’instruction :
LET A+1 = 10
est tout à fait incorrecte et ne permet pas d’affecter à la variable A la valeur 9 comme inciterait à le penser toute allusion à l’équation algébrique « x +1= 10 ».
Autre exemple :
num-ligne
INPUT var
Cette instruction arrête l’exécution du programme, affiche dans la fenêtre SBASIC un point d’interrogation et attend que l’utilisateur frappe une entrée au clavier. La ligne entrée par l’utilisateur est alors interprétée par SBASIC et la valeur correspondante affectée à la variable var.
Si la variable var
est de type numérique (entier ou réel) et que l’utilisateur frappe des caractères qui ne peuvent intervenir dans la définition d’une constante de ce type, le programme signale une erreur.
Par exemple le programme :
10 PRINT "Quel est votre nom ? ";
20 INPUT NOM$
30 PRINT "Bonjour ";NOM$
permet à l’utilisateur de cette machine de se faire saluer très poliment par son ordinateur préféré ; il lui suffit d’entrer ces quelques lignes, puis de les exécuter en frappant au clavier la commande RUN.
Signalons que l’entrée au clavier doit se terminer par la frappe d’un caractère Retour-Chariot
.
Tableaux
Lorsqu’un programme nécessite l’utilisation d’une liste de variables de même type et que chacune d’entre elles peut être repérée par son rang dans la liste, il est pratique et souvent indispensable de se servir d’un Tableau, encore appelé variable indicée.
Notion de tableau à une dimension
Par exemple un enseignant qui désire travailler sur les notes obtenues par ses élèves lors d’une composition utilisera une liste, un tableau, dont chacun des éléments contiendra la note d’un élève. La liste de classe étant supposée, ce qui est fréquent, écrite dans l’ordre alphabétique, chaque élève sera simplement repéré par son rang dans cette liste.
En supposant avoir une classe de 5 élèves ayant les noms suivants :
ANDRE
JACQUES
JEAN
PAUL
PIERRE
La note de l’élève n° 1 (ANDRE) correspondra à l’élément 1 du tableau,
la note de l’élève n° 2 (JACQUES) correspondra à l’élément 2 du tableau,
la note de l’élève n° 3 (JEAN) correspondra à l’élément 2 du tableau
et ainsi de suite
Dimensionnement d’un tableau à une dimension
Avant toute utilisation d’un tableau à une dimension permettant de gérer une liste de variables de même type, il faut déclarer ce tableau en indiquant son nom et en le dimensionnant. Cette opération permet à SBASIC de se préparer à la gestion d’une telle liste.
Pour dimensionner un tableau on utilise l’instruction DIM, décrite complètement dans la suite de ce manuel, mais dont on peut donner ici brièvement la syntaxe.
DIM var
(exp-num
)
var
est le nom du tableau. La construction de ce nom obéit aux mêmes règles que celles régissant la construction d’un nom de variable.
Si chaque élément du tableau est destiné à contenir une valeur de type entier, le nom var
doit de terminer par le symbole réservé %
.
Si chaque élément du tableau est destiné à contenir du texte, le nom var
doit se terminer par le symbole réservé $
.
exp-num
est un entier indiquant le nombre maximum d’éléments que l’on désire ranger dans le tableau.
Aucune opération globale d’affectation ou d’édition ne peut être faite en utilisant le nom du tableau. Mais chacun de ses éléments peut être manipulé exactement comme une variable de type correspondant.
Utilisation d’un tableau a une dimension
En reprenant l’exemple de la classe de 5 élèves, il est possible d’utiliser deux tableaux parallèles, l’un permettant de ranger les noms des élèves, l’autre contenant leurs notes.
Ces tableaux sont dimensionnés de la façon suivante :
10 N%=5
20 DIM NOM$(N%)
30 DIM NOTE(N%)
Pour entrer les noms et les notes des différents élèves de la classe il suffit d’exécuter les lignes suivantes :
100 FOR I%=1 TO N%
110 REM
120 REM Affectation d’un contenu à la variable NOM$(l%)
130 PRINT "Nom de l'élève ";I% ;
140 INPUT NOM$(I%)
150 REM
160 REM Affectation d'une note à l'élève de rang I%
170 PRINT "Note de l'élève ";NOM$(I%);
180 INPUT NOTE(I%)
190 NEXT I%
Pour obtenir maintenant une édition de ces notes dans l’ordre alphabétique il suffit d’exécuter les instructions suivantes :
200 FOR I%=1 TO N%
210 PRINT NOM$(I%); " a pour note "; NOTE(I%)
220 NEXT I%
Pour ce petit programme on aurait évidemment pu utiliser 5 variables de type chaîne de caractères destinées à contenir les noms N1$, N2$, N3$, N4$, N5$ ainsi que 5 variables de type réel destinées à contenir les notes, N1, N2, N3, N4, N5.
Toutefois la méthode utilisée présente deux avantages. Tout d’abord elle évite d’écrire 5 fois chacune des lignes mettant en jeu les éléments NOM$(I%) et NOTE(I%), à savoir les lignes 110, 120, 130, 210. Ensuite elle donne un programme aisément modifiable et adaptable à une classe plus conforme à la réalité. Il suffit par exemple de modifier l’affectation de la ligne 10, en la remplaçant par :
10 N%=25
on obtient alors un programme valable pour une classe de 25 élèves.
Notion de tableau à deux dimensions
Si le même enseignant désire travailler sur l’ensemble des notes de ses élèves pour un mois donné, il devra disposer, pour chacune des quatre interrogations du mois, de la liste des notes de ses élèves.
Il pourrait évidemment utiliser un tableau pour chacune des listes de notes :
NOTE1(*) contenant les notes de tous les élèves pour la première interrogation,
NOTE2(*) contenant les notes de tous les élèves pour la deuxième interrogation,
et ainsi de suite.
Mais on retombe alors dans le double travers signalé à la fin du paragraphe précédent concernant la concision d’écriture du programme et les possibilités d’adaptation à d’autres cas de figure semblables.
Il est préférable d’utiliser un tableau à deux dimensions, qui permettra, comme la page d’un cahier de notes, de stocker l’ensemble des notes du mois. L’un des indices permettra de repérer le nom de l’élève concerné (la ligne du cahier) et l’autre d’indiquer de quelle interrogation il s’agit (la colonne du cahier).
Dimensionnement et utilisation d’un tableau double
Un tableau double se déclare par une instruction de dimensionnement semblable à celle utilisée pour un tableau à une dimension :
DIM var
(exp-num-1
,exp-num-2
)
var
est le nom du tableau qui doit être construit comme celui d’un tableau à une dimension en fonction du type de valeurs que l’on désire y stocker.
exp-num-1
est le nombre maximum de lignes du tableau.
exp-num-2
est le nombre maximum de colonnes du tableau.
L’utilisation du tableau nécessaire à la gestion de l’ensemble des notes de l’exemple précédemment décrit imposera la déclaration d’un tableau de notes doublement indicé grâce à l’instruction :
50 DIM NOTE_MOIS(5,4)
Dans ce tableau :
NOTE_MOIS(2,3) est la note obtenue par JACQUES à l’interrogation 3,
NOTE_MOIS(4,1) est la note obtenue par PAUL à l’interrogation 1.
Il faudra utiliser une double boucle pour entrer tous les éléments du tableau, mais l’utilisateur aura ensuite la possibilité de d’établir, pour chaque élève, la moyenne des notes du mois et de calculer pour chacune des interrogations la moyenne des notes de la classe.
De même que pour les tableaux à une dimension, aucune opération (affectation, édition, …) ne peut être faite globalement en invoquant seulement le nom du tableau, mais chacun de ses éléments peut être utilisé dans les mêmes conditions qu’une variable de type correspondant.
SBASIC supporte un nombre quelconque de dimensions à condition que le nombre total d’éléments ne dépasse pas 536870911.
Operateurs et expressions
Ayant défini précédemment les objets élémentaires (constantes et variables) sur lesquels travaillait SBASIC, nous allons maintenant définir les opérateurs qui permettent de construire d’autres objets plus complexes, les expressions dont la valeur peut être un nombre ou une chaîne de caractères, ainsi que des relations entre ces objets.
Par exemple :
A désignant une variable numérique et A$ une variable chaîne, on pourra être amené dans le cours d’un programme à utiliser les expressions :
12 + EXP(A)
PI + LEN(A$)
que l’on pourra désigner respectivement par exp-num-1
et exp-num-2
. En appliquant à ces mêmes expressions les règles de remplacement que nous avons vues au sujet des variables, nous voyons que la première, par exemple, est obtenue à partir de l’expression formelle :
const-num
+ EXP(var-num
)
en y remplaçant respectivement :
const-num
par 12
var-num
par A
De même, les expressions prenant des valeurs de type chaîne de caractères seront désignées par exp chaîne éventuellement suivie d’un chiffre, ce qui pourra donner exp chaîne 1 ou exp chaîne 2 lorsque l’on désirera utiliser deux éléments de ce type.
On parlera, par exemple, de l’expression formelle :
var-chaîne
= MID$(const-chaîne
,var-num-1
,const-num
)
qui pourra devenir pour une utilisation particulière :
EXTRAIT$ = MID$("SIROS SBASIC",I%,3)
Opérateurs
Trois catégories d’opérateurs sont disponibles.
Les premiers opèrent sur des objets (expressions numériques ou alphanumériques) et permettent de construire d’autres objets plus complexes, c’est-à-dire d’autres expressions plus complexes. Ce sont les Opérateurs arithmétiques et l’Opérateur de concaténation de chaînes.
Les seconds opèrent sur des objets et permettent de former des relations entre ces objets. Ce sont les Opérateurs de relations.
Enfin, la dernière catégorie est celle des Opérateurs logiques qui peuvent opérer sur des relations pour donner d’autres relations, et qui peuvent opérer sur des valeurs numériques pour donner d’autres valeurs numériques.
Operateurs arithmétiques
La première catégorie d’opérateurs, avec laquelle nous sommes le plus familiarisés, est celle des opérateurs arithmétiques. Ces opérateurs permettent de relier deux expressions numériques, pour former des expressions numériques de plus en plus complexes.
Ce sont :
Nom | Symbole | Exemple | Explication |
---|---|---|---|
Addition | + | X+Y | Ajoute X à Y |
Soustraction | - | X-Y | Soustrait Y de X |
Multiplication | * | X*Y | Multiplie X par Y |
Division | / | X/Y | Divise X par Y |
Exponentiation | ** | X**Y | Elève X à la puissance Y |
Modulo | MOD | X MOD Y | Calcule X modulo Y |
Dans chacune des phrases précédentes il faut évidemment lire contenu de X et contenu de Y au lieu de X et de Y. Ce n’est que pour des questions de présentation que nous nous sommes permis ce raccourci.
De plus on pourra évidemment remplacer chacune des variables X et Y par une variable entière ou même par une expression numérique quelconque exp-num-1
ou exp-num-2
.
Lorsque deux valeurs de type différent sont concernées, un entier et un flottant (nombre réel) par exemple, l’entier est d’abord converti en flottant et l’opération est effectuée. Seul l’opérateur d’exponentiation fait exception à cette règle.
Operateur de concaténation de chaînes
De même que les opérateurs précédents permettent de construire des expressions dont la valeur est de type numérique, il existe un opérateur permettant de construire des expressions alphanumériques plus complexes.
Cet opérateur, représenté par le signe +
, permet de relier deux expressions de type chaîne de caractères pour en obtenir une troisième du même type. L’expression suivante :
exp-chaîne-1
+ exp-chaîne-2
aura pour valeur la chaîne obtenue en concaténant (mettant bout à bout) les deux chaînes dans l’ordre donné.
Attention : contrairement à l’opération que ce symbole +
, représente lorsqu’il agit sur des expressions numériques, la concaténation de chaînes n’est pas commutative. Les valeurs de exp-chaîne-1
+ exp-chaîne-2
et de exp-chaîne-2
+ exp-chaîne-1
ne sont en général pas égales.
Par exemple si A$ et B$ contiennent respectivement "Sbasic " et "SIROS ", la valeur de A$+B$ est "Sbasic SIROS ", alors que celle de B$+A$ est "SIROS Sbasic ".
Operateurs de relation
Les opérateurs de relation permettent de construire des expressions logiques élémentaires qui pourront être utilisées par exemple dans un test introduit par le mot réservé IF.
Les expressions logiques élémentaires se construisent en comparant, à l’aide de ces opérateurs, des expressions de même type, numérique ou alphanumérique. Les six symboles de relation reconnus par SBASIC sont :
Symbole | Exemple | Signification |
---|---|---|
= | exp 1 = exp 2 | exp 1 égal à exp 2 |
<> | exp 1 <> exp 2 | exp 1 différent de exp 2 |
< | exp 1 < exp 2 | exp 1 inférieur à exp 2 |
> | exp 1 > exp 2 | exp 1 supérieur à exp 2 |
<= | exp 1 <= exp 2 | exp 1 supérieur ou égal à exp 2 |
>= | exp 1 >= exp 2 | exp 1 inférieur ou égal à exp 2 |
Lorsqu’il s’agit d’expressions numériques, l’interprétation ne pose aucun problème. Pour les expressions de type alphanumérique, la relation d’ordre utilisée est l’ordre alphabétique des chaînes de caractères. La valeur de l’expression alphanumérique exp-chaîne-1
est supérieure à celle de l’expression alphanumérique exp-chaîne-2
si la chaîne correspondant à la première s’écrit après la chaîne correspondant à la seconde dans le grand dictionnaire des chaînes alphanumériques.
Par exemple, si A$ contient « SIROS », la relation A$ <= "SBASIC" est une relation fausse, car dans l’ordre alphabétique « SIROS » vient après « SBASIC ».
Ces relations logiques élémentaires sont souvent combinées entre elles grâce aux opérateurs logiques (Voir le paragraphe « Operateurs logiques ») pour donner des expressions logiques plus complexes qui seront désignées génériquement dans la suite par exp logique.
Operateurs logiques
La dernière classe d’opérateurs est celle des opérateurs logiques (AND, OR, NOT). Ils permettent de relier des valeurs de type entier ou des expressions logiques.
Operateurs logiques entre valeurs de type entier
Lorsqu’ils relient des valeurs de type entier, les opérateurs logiques permettent de réaliser des opérations bit à bit, afin de former des expressions de type numérique.
Si, par exemple, A% et B% contiennent respectivement les quantités binaires suivantes :
A% contient 11001011111101101100101111110110 (soit -873018378 en décimal)
B% contient 01110101111001000111010111100100 (soit 1977906660 en décimal)
Alors :
A% AND B% a pour valeur 01000001111001000100000111100100 (1105478116)
A% OR B% a pour valeur 11111111111101101111111111110110 (-589834)
NOT A% a pour valeur 00110100000010010011010000001001 (873018377)
De façon plus générale, les effets des opérateurs logiques sont décrits ci-dessous :
Opérateur | Exemple | Action |
---|---|---|
NOT | NOT X% | Cet opérateur transforme la valeur de chaque bit en son complément (les 1 sont remplacés par des 0 et les 0 par des 1). |
AND | X% AND Y% | Le résultat de cette opération est d’affecter, à chaque bit du résultat, un 1 si chacun des bits de même rang vaut 1 dans X% et Y%. |
OR | X% OR Y% | L’opération met à 1 chaque bit du résultat si l’un ou l’autre des bits de même rang dans X% ou Y% vaut 1. |
On peut évidemment, dans chacun des trois exemples précédents, remplacer l’une ou l’autres des variables X% et Y% par une expression numérique.
Dans la mesure où ces opérateurs sont définis par leur effet sur des quantités entières, la représentation interne en virgule flottante de certaines variables et constantes doit d’abord être convertie en entiers. Cette conversion est réalisée automatiquement par l’interpréteur SBASIC.
Ces opérateurs peuvent s’utiliser conjointement aux opérateurs arithmétiques dans des expressions numériques.
Si l’on veut par exemple, pour le contenu d’une variable A% faire la somme de son quotient par 16 et de son reste modulo 16, puis affecter la valeur correspondante à la variable B%, on pourra écrire :
B% = (A%/16) + (A% AND 15)
Remarque : Pour l’extraction d’un modulo, on ne peut utiliser la formule var-num
AND exp-num
que si la valeur de exp-num
est de 2n -1, n étant un entier compris entre 1 et 31.
Operateurs logiques entre expressions
Les opérateurs logiques AND, OR, NOT peuvent aussi, et c’est en fait leur utilisation la plus fréquente, opérer sur des expressions logiques. Ils permettent alors de former des expressions logiques plus complexes, qui seront le plus souvent testées grâce à l’instruction IF.
Si exp-logique-1
et exp-logique-2
représentent des expressions logiques, on peut former :
Opération | Résultat NOT exp-logique-1 | Vrai si et seulement si exp-logique-1 est fausse. exp-logique-1 AND exp-logique-2 | Vrai si et seulement si exp-logique-1 et exp-logique-2 sont simultanément vraies. exp-logique-1 OR exp-logique-2 | Vrai dès que l’une au moins des deux expressions exp-logique-1 ou exp-logique-2 est vraie.
Dans l’exemple :
40 IF (A$="FIN" AND I%=10) THEN GOTO 100
le programme se branchera à la ligne 100 si la variable A$ contient la valeur « FIN » et si I% contient la valeur 10. Les parenthèses ne sont pas obligatoires, elles ont simplement été placées pour mieux mettre en évidence l’expression logique testée.
Toutefois les deux utilisations des opérateurs logiques peuvent être combinées, car à chaque expression logique on peut, à un instant donné, associer une valeur numérique entière qui vaut 0 si sa valeur logique est FAUX et -1 si elle est VRAI.
On pourra donc par exemple écrire :
var-num
= exp-logique-1
AND exp-logique-2
ce qui permettra d’affecter à var-num
la valeurs -1 si exp-logique-1
et exp-logique-2
sont toutes deux vraies. L’expression précédente permet évidemment de remplacer avantageusement :
IF exp-logique-1
=exp-logique-2
THEN var-num
=-1 ELSE var-num
=0,
mais exp-logique-1
AND exp-logique-2
peut aussi s’utiliser de la même façon que n’importe quelle autre expression de type numérique.
Priorité entre les operateurs
Quand SBASIC évalue une expression contenant un mélange d’opérateurs mathématiques, il effectue d’abord l’exponentiation, prend en compte ensuite tous les signes moins unaires (comme -3.4 ou -A). Il effectue ensuite les multiplications et divisions, et enfin les additions et soustractions. Lorsque des opérateurs de priorité égale sont rencontrés, c’est celui situé le plus à gauche qui est d’abord exécuté, car SBASIC évalue les expressions de gauche à droite.
L’ordre peut toutefois être modifié par l’utilisation de parenthèses. SBASIC évalue d’abord les quantités entre les parenthèses les plus internes. Les parenthèses doivent être utilisées à chaque fois qu’il y a un doute au sujet de l’évaluation de l’expression.
Lorsque deux valeurs de même type sont concernées, l’opérateur approprié est appelé. Par exemple, lorsque l’on multiplie deux entiers, la routine de multiplication d’entiers est appelée. Si deux nombres en virgule flottante doivent être soustraits, la routine de soustraction en virgule flottante est appelée.
Les priorités entre opérateurs sont indiquées dans le tableau ci-dessous. Les opérateurs sont listés par ordre de priorité décroissante. Les opérateurs de même priorité sont évalués de gauche à droite.
Opérateur | Priorité |
---|---|
( ) | Expressions placées entre parenthèses |
** | Exponentiation |
- | Signe moins (unaire) |
* / | Multiplication et division |
MOD | Modulo |
+- | Addition et soustraction |
<> = >= <= | Opérateurs de relation |
NOT | Opérateur NOT |
AND | Opérateur AND |
OR | Opérateur OR |
Il faut toutefois se rappeler que si, en plus de ces opérateurs, des fonctions interviennent dans l’expression à évaluer, ces dernières ont une priorité encore plus élevée que les parenthèses.
Utilisation de SBASIC en mode direct et en mode programme
Instructions
L’interpréteur SBASIC permet d’analyser et d’exécuter des instructions qui sont construites à partir des mots réservés dont le mode d’emploi détaillé est donné dans la deuxième partie de ce manuel.
A titre d’exemple on peut donner des instructions d’affectation :
LET A = 12 * PI
B = (A + 5) * 12.5
TITRES = "Documentation SBASIC"
ou des instructions d’impression :
PRINT "Dernier chapitre"
PRINT "Page numéro "; NP%
Mode direct
Ces instructions peuvent s’utiliser en MODE DIRECT, c’est à dire telles que nous les avons écrites ci-dessus ; elles sont alors directement analysées et exécutées par SBASIC. On dit alors qu’il s’agit de Commandes.
Si l’on tape au clavier l’avant dernier exemple donné plus haut, suivi d’un Retour-Chariot
indiquant à SBASIC que l’on a terminé d’entrer une commande, ce dernier l’exécutera immédiatement : il affichera la chaîne de caractères « Dernier chapitre » dans la fenêtre SBASIC.
Il est possible d’entrer en une seule fois plusieurs commandes que SBASIC exécutera les unes après les autres, il suffit de les séparer par le signe deux points :
. Il faut évidemment finir par un Retour-Chariot
indiquant à SBASIC que l’utilisateur a terminé sa ligne de commandes. Par exemple on peut taper :
NP%=10 : PRINT "Page "; NP%
ce qui affecte la valeur 10 à la variable entière NP%, puis affiche dans la fenêtre SBASIC le libellé « Page 10 ».
Mode programme
On peut également entrer des instructions que SBASIC n’exécute pas immédiatement, mais qu’il mémorise sous forme de lignes de programme qui seront exécutées ultérieurement. C’est ce que l’on appelle le mode programme.
Avant tout travail dans ce mode, il est conseillé d’exécuter la commande NEW (ne pas oublier le Retour-Chariot
final) qui efface toute ligne de programme qui aurait pu être entrée accidentellement par l’utilisateur courant de la machine, ou sciemment par un utilisateur antérieur.
Il est par exemple possible d’entrer le programme suivant :
10 PRINT "Quel est votre nom "
20 INPUT NOM$
30 PRINT "Bonjour "; NOM$
Pour ce faire il suffit à l’utilisateur de frapper au clavier les lignes telles qu’elles sont écrites, en les terminant toujours par un Retour-Chariot
. S’il commet une erreur lors de l’entrée de l’une d’entre elles, il lui suffit de la frapper à nouveau.
Contrairement à ce qui s’est passé dans l’exemple précédent, aucun message ne s’affiche lorsque l’utilisateur frappe le Retour-Chariot
terminant la première et la dernière ligne. C’est que l’on vient de créer 3 lignes de programme. Pour Exécuter ce programme, l’utilisateur doit frapper au clavier la commande RUN (suivi d’un Retour-Chariot
) qui débutera l’exécution du programme.
Ce dernier commencera par demander le nom de l’utilisateur puis le saluera poliment. Si l’utilisateur ne se lasse pas de cette politesse et qu’il désire un nouveau salut, il lui sera inutile de réécrire les lignes de programmes, il lui suffira de frapper à nouveau la commande RUN, c’est ce qui fait tout l’intérêt du mode programme.
Sauvegarde et chargement d’un programme
Malheureusement ce programme phénoménal se trouve dans la mémoire centrale de la machine qui est constituée de mémoire vive (RAM) dans laquelle on peut écrire facilement, mais qui s’efface tout aussi facilement à la moindre coupure de courant. Si l’utilisateur veut conserver son programme, il lui suffit de l’enregistrer sur disque en utilisant la commande :
SAVE "PREMIER"
qui lui permettra de le sauvegarder sur disque dans un fichier nommé « PREMIER ». En fait le nom complet du fichier, tel qu’il pourra apparaître dans un répertoire de fichiers, sera « PREMIER.BAS », mais l’extension .BAS
est gérée automatiquement par le système et l’utilisateur n’a pas à s’en préoccuper pour l’instant.
Après une interruption du courant ou même l’utilisation de la commande NEW, l’utilisateur pourra recharger les trois lignes du programme précédent en tapant la commande :
LOAD "PREMIER"
S’il utilise alors la commande :
LIST
qui permet de LISTer le programme se trouvant en mémoire centrale, il pourra vérifier qu’il a effectivement retrouvé le programme initial.
Utilisation conjointe du mode programme et du mode direct
Il est possible de panacher les deux modes d’utilisation de l’interpréteur SBASIC. Même après l’exécution du programme précédent la variable NOM$ n’a pas « perdu » son contenu et l’utilisateur peut taper l’ordre :
PRINT NOM$
qui permettra de vérifier son contenu. Cette dernière possibilité, dans laquelle réside une grande partie de l’intérêt des langages interprétés, offre de grandes facilités lors de la mise au point et le dépannage des programmes écrits en SBASIC. Elle est aussi utilisable lorsque le programme a été interrompu par une instruction STOP, l’appui simultané sur les touches Ctrl
et C
(notée Ctrl-C
dans la suite de ce manuel) ou la survenue d’une erreur.
Description d’une ligne de programme SBASIC
Chaque ligne de programme BASIC commence par un numéro de ligne. La ligne peut contenir une ou plusieurs instructions séparées par le caractère « : » et s’achève par un Retour-Chariot
.
La longueur d’une ligne ne peut dépasser 255 caractères. Les lignes peuvent être numérotées de 1 à 2147483647 et chacune d’entre elles a un numéro unique. Lorsque SBASIC exécute un programme, il interprète les lignes dans l’ordre croissant de leurs numéros.
Lorsque l’on écrit un programme, il est conseillé de numéroter les lignes de 10 en 10, ou de 20 en 20 afin de pouvoir, éventuellement par la suite, en insérer facilement de nouvelles.
On peut aussi laisser des espaces pour rendre plus aisée la lecture d’un programme. Dans les exemples suivants, les instructions 30 et 40 sont identiques, mais la ligne 40 est plus facile à lire. Il est recommandé de mettre un espace entre un mot clé et un nom de variable. Un espace est obligatoire entre un nom de variable de type virgule flottante et un mot clé.
Exemples d’utilisation d’espaces :
30X=32*X/3+7.3*X/2+6.54*X-.1
40 X= 32*X/3 + 7.3*X/2 + 6.54*X - .1
Exemple de ligne où un espace est obligatoire :
100 IF IND=0 THEN PRINT VITESSE ELSE PRINT TEMPS
le seul espace obligatoire est celui placé entre VITESSE et ELSE ; les autres sont facultatifs.
Exemple comportant plusieurs instructions par ligne :
120 INPUT "VITESSE, TEMPS"; V,T : D = V*T : PRINT "DISTANCE ="; D
Restrictions sur l’utilisation en modes direct et programme
La majeure partie des instructions du SBASIC peut s’utiliser en mode direct et en mode programme. Toutefois, certaines d’entre elles ne peuvent s’utiliser que dans l’un des deux modes.
Les commandes pures
Voici la liste des commandes ne pouvant s’utiliser qu’en mode direct. Elles ne peuvent donc figurer dans les lignes d’un programme.
Commande | Action |
---|---|
BREAK ON | Valide la possibilité d’arrêter un programme en cours de traitement au moyen de la combinaison de touches Ctrl-C . Cette option est prise par défaut au chargement du SBASIC. |
BREAK OFF | Invalide l’action Ctrl-C . |
CONT ou CONTINUE | La commande CONTinue est utilisée pour faire redémarrer un programme arrêté par une instruction STOP ou un appui sur Ctrl-C . |
EDIT | Pour modifier une ligne de programme, il suffit de taper EDIT suivi du numéro de la ligne à modifier. |
LIST | Commande permettant de donner la liste, dans la fenêtre SBASIC, de tout ou partie du programme se trouvant en mémoire centrale. |
NEW | Efface le programme se trouvant en mémoire centrale. |
PLIST | Identique a la commande LIST, mais avec édition dans le tampon d’impression. |
RENUM ou RENUMBER | Effectue la renumérotation totale ou partielle du programme en mémoire. |
RUN | La commande RUN indique à SBASIC de démarrer l’exécution du programme se trouvant en mémoire centrale. |
SAVE | Cette commande est utilisée pour stocker sur disque, sous forme source (sous forme texte), tout ou partie du programme SBASIC se trouvant en mémoire centrale. |
STACK | Affiche la pile d’exécution du programme arrêté par une instruction STOP, un appui sur Ctrl-C ou la détection d’une erreur. |
STEP | Relance, pour une seule ligne, l’exécution du programme arrêté par une instruction STOP ou un appui sur Ctrl-C . |
SYSTEM ou EXIT | La commande SYSTEM est utilisée pour quitter SBASIC. |
TRACE ON | Active la fonction TRACE. |
TRACE OFF | Désactive la fonction TRACE. |
Mots réservés ne pouvant pas être utilisés en mode direct
L’instruction READ et le mot réservé DATA ne peuvent s’utiliser qu’en mode programme. Un rapide coup d’œil à leur description détaillée permettra d’en comprendre la raison.
Utilisation des fichiers
Lorsqu’un programme SBASIC doit gérer des données en nombre trop important pour pouvoir être rentrées à chaque fois depuis le clavier, on utilise des fichiers sur disque que le programme peut lire lorsqu’il a besoin de ces données ou sur lesquels il peut écrire pour les mettre à jour.
Les fichiers que l’on peut utiliser sont de 2 types :
- Les Fichiers à accès séquentiel
- Les Fichiers à accès direct
Les premiers doivent s’écrire et se lire séquentiellement à l’instar d’une bande de magnétophone ou de magnétoscope alors que pour les seconds il est possible d’accéder directement à un enregistrement donné et de le modifier, ce qui correspond au fonctionnement d’un disque.
Fichier séquentiel d’entrée-sortie
La forme la plus simple d’utilisation des fichiers de données est la forme séquentielle dans laquelle les données sont écrites les unes derrière les autres, séparées par des Retour-Chariot
ou par des virgules.
Ouverture en écriture d’un fichier séquentiel
Avant d’écrire dans un fichier sous SBASIC, il est nécessaire de « l’ouvrir ». C’est l’ordre OPEN qui est utilisé pour cette opération. Il permet d’affecter un canal au fichier concerné et de lui réserver en mémoire centrale une zone de mémoire tampon d’entrées-sorties ou simplement tampon (ou buffer), par laquelle transiteront les échanges avec le disque.
Imaginons que l’on veuille constituer un fichier contenant les 6 premiers entiers ainsi que leurs carrés avec quelques explications, à savoir :
- le libellé « Liste des 6 premiers entiers »,
- puis les 6 premiers entiers « 1 », « 2 », …, « 6 »,
- puis le libellé « leurs carrés »,
- enfin les 6 carrés « 1 », « 4 », …, « 36 ».
On commence par ouvrir un « nouveau » fichier au moyen de l’instruction :
100 OPEN NEW "CARRE" AS 1
qui indique que l’on veut ouvrir sur le canal 1 un fichier qui aura pour nom sur le disque, « CARRE », en fait « CARRE.DAT », car, par défaut, SBASIC utilise l’extension .DAT
pour les fichiers de données.
Si un fichier de ce nom existait déjà sur le disque il est détruit sans avertissement, c’est en ce sens que tout fichier séquentiel ouvert en écriture est forcément un « nouveau » fichier.
Ecriture dans un fichier séquentiel
Pour écrire dans le fichier séquentiel précédemment ouvert sur le canal 1, il suffit d’utiliser une version légèrement modifiée de l’ordre PRINT.
La ligne :
110 PRINT #1 "Liste des 5 premiers entiers"
permet d’écrire, dans le fichier ouvert sur le canal 1, le libellé « Liste des 5 premiers entiers ».
De même la ligne :
120 FOR I%=1 TO 6: PRINT #1 I%: NEXT I%
permet d’y écrire les 6 premiers entiers « 1 », « 2 », …, « 6 ». Chacun étant séparé du précédent par un Retour-Chariot
.
Pour terminer il suffira d’écrire :
130 PRINT #1 "leurs carrés"
140 FOR I%=1 TO 6: PRINT #1 I%*I%: NEXT I%
Toutefois il ne faut pas oublier de fermer le fichier par l’instruction :
200 CLOSE 1
Cette instruction permet tout d’abord de libérer le canal utilisé, ici le canal 1, afin de pouvoir éventuellement le réutiliser pour la lecture ou l’écriture d’un autre fichier.
Mais elle a une autre fonction bien plus importante dans l’exemple qui nous préoccupe : elle écrit effectivement sur disque les données qui peuvent encore se trouver dans le buffer associé au fichier. En effet, dans le but d’accélérer les opérations, l’écriture sur disque ne se produit pas effectivement lors de l’exécution de chaque ordre PRINT #1. Les données sont stockées dans un buffer, une mémoire tampon, dont la taille varie en fonction du système utilisé et qui est recopié sur le disque lorsqu’il est plein. C’est la seconde fonction de l’ordre CLOSE que d’effectuer l’écriture de cette partie résiduelle.
Après l’exécution de ce petit programme on doit trouver sur disque le fichier « CARRE.DAT » qui pourra être listé.
Le programme précédent peut paraître simpliste, mais il illustre la façon d’éviter de saisir à la main les éléments à écrire dans le fichier. Un programme plus général d’écriture en fichier doit comporter 2 phases bien distinctes :
- Une phase de saisie qui permettra à l’utilisateur, grâce à un certain nombre d’ordres INPUT, de rentrer des données en mémoire centrale en les frappant au clavier.
- Une phase d’écriture effective dans le fichier, qui grâce à des ordres PRINT, permettra de faire passer ces données de la mémoire centrale vers le fichier se trouvant sur le disque.
Ouverture d’un fichier en lecture
Après avoir exécuté le programme précédent et l’avoir, le cas échéant, sauvegardé, il est maintenant temps de savoir comment récupérer les données que l’on a écrites dans ce fichier, en vue de leur éventuelle utilisation par un programme SBASIC.
Il faut d’abord « ouvrir » le fichier pour le relire. C’est un fichier qui existe déjà sur le disque, un ancien fichier ; on utilisera donc l’instruction :
100 OPEN OLD "CARRE" AS 2
qui indique à SBASIC que l’on veut ouvrir le fichier « CARRE », en fait « CARRE.DAT », en vue de le lire.
Lecture d’un fichier séquentiel
De même que l’écriture dans un fichier séquentiel utilisait l’ordre PRINT #, la lecture utilise l’ordre symétrique : INPUT #.
On commencera par relire la première chaîne :
110 INPUT #2 A$
puis on pourra retrouver les 6 valeurs numériques que l’on avait écrites, mais il faut, pour ce faire, préparer un tableau NOMBRE pour les stocker en mémoire centrale. On écrira donc :
120 DIM NOMBRE(6): FOR I%=1 TO 6: INPUT #2 NOMBRE(I%): NEXT I%
Pour se convaincre que l’on a bien récupéré les valeurs précédemment écrites dans le fichier, on peut insérer dans cette boucle l’instruction PRINT NOMBRE(I%) ou même réaliser une autre boucle d’impression.
On récupère ensuite les autres valeurs de manière analogue :
130 INPUT #2 B$
140 DIM CARRE(6): FOR I%=1 TO 6: INPUT #2 CARRE(I%): NEXT I%
Enfin il faut fermer le fichier au moyen de l’instruction :
200 CLOSE 2
dont le seul effet, ici, est de libérer le canal utilisé.
Une première remarque s’impose à la lecture de ce programme : il faut connaître la structure logique du fichier pour être en mesure de le relire. Ici, il fallait savoir qu’il contenait un libellé, six valeurs numériques, un autre libellé et les six dernières valeurs numériques. Si l’on avait commis une erreur, par exemple en oubliant de lire le libellé central (omission de la ligne 130), une erreur 30 se serait produite en ligne 140 puisque le programme aurait alors essayé de lire une valeur numérique et que le fichier lui aurait présenté le libellé central, constitué d’une chaîne de caractères.
Toutefois, chaque nombre étant stocké dans un fichier séquentiel sous forme de la chaîne de caractères qui permet de l’écrire, il est toujours possible de relire un fichier séquentiel en considérant tous ses éléments comme des chaînes de caractères.
Après avoir frappé et exécuté une première fois le programme précédent, l’utilisateur peut ajouter l’instruction :
150 INPUT #2 C$
et exécuter le programme ainsi modifié. Lors de l’exécution de la ligne 150, il se produit une erreur 8, (voir « Annexe 1 : Liste des commandes, instructions et fonctions ») qui indique la fin du fichier séquentiel. Cette erreur peut évidemment être gérée sous SBASIC, à condition de l’avoir prévu, en utilisant l’instruction ON ERROR GOTO.
Cette modification permet donc de se rendre compte qu’il n’est pas nécessaire de connaître le nombre exact d’éléments d’un fichier séquentiel. Il suffit dans ce cas de prévoir l’occurrence d’une erreur de fin de fichier dont la prise en compte permettra un branchement vers la suite du traitement.
Correspondance entre les ordres PRINT, PRINT #, INPUT, INPUT #
Pour éviter toute confusion dans l’utilisation des instructions PRINT, PRINT #, INPUT, INPUT #, il est bon de se rappeler que SBASIC opère sur des données qui doivent se trouver en mémoire centrale.
Les instructions INPUT et INPUT # permettent d’introduire ces données en mémoire centrale, qu’elles proviennent du clavier ou d’un fichier disque qui, tous deux, sont des périphériques par rapport à la mémoire centrale. Le fichier fournit des données ASCII tout à fait comme si ces dernières étaient entrées au clavier.
De même, les ordre PRINT et PRINT # permettent de diriger des données vers les périphériques externes que sont l’écran et le disque. Dans le premier cas on écrit sur l’écran dans la fenêtre SBASIC, dans le second on écrit dans un fichier.
Autres séparateurs, cas particuliers
Jusqu’à présent nous avons, dans le fichier, séparé les données par des Retour-Chariot
, mais il est aussi possible de les séparer par des virgules. Il suffit de mettre ces dernières dans la chaîne écrite dans le fichier à l’aide de l’ordre PRINT #.
Lorsqu’on utilise la virgule comme séparateur, il faut se souvenir qu’elle joue un rôle de séparateur aussi bien pour l’instruction INPUT que pour l’instruction INPUT #.
De même les limitations concernant les chaînes vides sont les mêmes que celles relatives à l’instruction INPUT. Donc si certains des éléments d’un fichier sont des chaînes contenant des virgules, voire des chaînes vides, il faudra utiliser l’instruction INPUT LINE # à la place de l’instruction INPUT #.
Il est aussi possible d’utiliser l’instruction PRINT # suivie du symbole « ; », ce qui a pour effet de ne pas introduire de Retour-Chariot
après la donnée concernée par cet ordre. La donnée que l’on écrira ensuite dans le fichier lui sera alors concaténée et lors de la relecture il sera impossible de les dissocier par de simples ordres INPUT. Dans ce cas il ne faut pas oublier que la dernière donnée écrite dans le fichier doit être suivie d’un Retour-Chariot
.
L’utilisation de PRINT # suivie du symbole « , » est autorisée. Elle introduit dans le fichier un nombre d’espaces correspondant à celui des espaces nécessaires à la tabulation liée à la virgule.
Enfin on peut aussi signaler l’instruction INCH$ qui permet de relire un fichier séquentiel caractère par caractère. Pour un fichier ouvert sur le canal 1, l’instruction :
R$=INCH$(1)
permettra d’affecter à la variable R$ le caractère suivant du fichier.
Utilisation du canal 0
Instruction INPUT sur le canal 0
Il est parfois souhaitable de saisir des données au clavier sans voir apparaître le signe « ? » à chaque exécution de l’ordre INPUT. Ceci est possible en utilisant le canal 0.
Exemple :
10 INPUT #0 B$
20 INPUT LINE #0 A$
Les instructions INPUT de cet exemple sont utilisés comme des ordres INPUT normaux.
Instruction PRINT sur le canal 0
Il est souvent nécessaire d’effectuer des sorties SBASIC sur un fichier plutôt que dans la fenêtre SBASIC. Le canal 0 permet d’aiguiller en sortie les ordres PRINT, vers la fenêtre SBASIC ou un fichier.
L’utilisation de l’instruction PRINT #0, sans celle préalable de l’instruction OPEN permet l’affichage direct de données dans la fenêtre SBASIC comme une instruction PRINT ordinaire.
Exemple :
20 PRINT #0 "CECI EST UN TEST"
affiche dans la fenêtre SBASIC « CECI EST UN TEST », comme si « #0 » n’était pas spécifié.
En revanche, l’ouverture du canal 0 permet d’aiguiller les données vers un fichier. L’utilisation de l’instruction OPEN NEW ou OPEN APPEND avec 0 comme numéro de canal 0 demande à SBASIC d’utiliser ce fichier de sortie chaque fois que l’ordre PRINT #0 est utilisé.
Exemple :
10 OPEN NEW "OUTPUT" AS 0
20 PRINT #0 "CECI EST UN TEST"
30 CLOSE 0
Le fichier « OUTPUT.DAT » est créé et contient le texte « CECI EST UN TEST ».
Les ordres PRINT ne spécifiant pas « #0 » continueront à afficher les données dans la fenêtre SBASIC L’ordre CLOSE 0
indiquera à SBASIC d’aiguiller à nouveau, vers la fenêtre SBASIC, toutes les données relatives à des instructions PRINT #0 et ce, jusqu’à l’exécution d’un autre ordre OPEN … AS 0
.
L’exemple suivant illustre l’utilisation de l’instruction PRINT # sur le canal 0. Ce programme permet de choisir la fenêtre SBASIC ou un fichier pour éditer les résultats.
10 INPUT "ECRAN OU FICHIER ? (E / F)"; R$
20 IF R$ ="F" THEN OPEN NEW "OUTPUT" AS 0
30 FOR I=1 TO 10
40 PRINT #0 I, SQR(I)
50 NEXT I
60 IF R$="F" THEN CLOSE 0
70 END
Les tableaux virtuels
Le tableau virtuel est l’exemple le plus simple de fichier à accès direct. Il permet de spécifier qu’un ensemble de données doit résider sur disque plutôt qu’en mémoire centrale. A l’intérieur d’un programme SBASIC, les données virtuelles sont référencées comme des éléments de tableau, ce qui autorise puissance et simplicité d’emploi.
Les deux avantages de ce concept sont que le tableau peut avoir jusqu’à 2147483647 éléments, quelle que soit la taille mémoire centrale disponible, et que les données, dès leur affectation, résident sur le disque. Elles sont donc permanentes et peuvent être réutilisées.
La seule restriction au regard d’un fichier accédé par enregistrement, est que tous les éléments doivent être du même type : entiers, réels ou chaînes de caractères et que, dans ce dernier cas, toutes les chaînes doivent avoir la même longueur.
Le tableau virtuel permet d’accéder directement, en lecture et en écriture, à une donnée quel que soit son emplacement dans le fichier disque.
Ouverture d’un tableau virtuel
Avant d’être référencé, un tableau virtuel doit être ouvert au moyen de l’instruction OPEN, comme dans l’exemple suivant :
100 OPEN "VIRT" AS 1
Cette instruction va permettre d’accéder aux données du fichier « VIRT.DAT ». Mais pour indiquer qu’il s’agit d’un tableau virtuel et non d’un fichier accédé par enregistrement ainsi que pour en préciser le type, il faut dimensionner le tableau qui permettra de manipuler les éléments de ce fichier. On utilise pour cela une forme spéciale de l’instruction DIM.
Imaginons que l’on désire stocker les 10 premiers carrés « 1 », « 4 », …, « 100 ». On peut écrire :
110 DIM #1 NO%(10)
qui indique à SBASIC que le fichier ouvert sur le canal 1 est un tableau virtuel d’entiers pouvant contenir jusqu’à 11 éléments.
Pour ouvrir un fichier virtuel destiné à recevoir des chaînes de caractères, on utiliserait :
500 OPEN "TEXTE" AS 3
510 DIM #3 A$(50)=63
ce qui indiquerait à SBASIC que les données du fichier « TEXTE.DAT » sont les éléments du tableau A$(*) et que toutes ces chaînes ont une longueur de 63 caractères.
On retrouve ici l’une des contraintes signalées au début de ce chapitre : toutes les chaînes utilisées doivent avoir la même longueur pour que SBASIC puisse accéder directement à l’une d’entre elles. Dans l’exemple traité, elle est de 63 caractères.
Si aucune longueur n’est spécifiée, comme dans l’instruction :
510 DIM #3 A$(50)
la longueur prise par défaut est 18.
Si l’on affecte à l’un des éléments d’un tableau virtuel de chaînes de caractères une valeur de type alphanumérique dont la longueur est inférieure à celle des éléments du tableau, SBASIC complète ces valeurs par des espaces de façon à obtenir la longueur spécifiée. Dans le cas contraire, la valeur est tronquée.
Il est aussi possible de considérer les éléments d’un tableau virtuel comme ceux d’une matrice à deux dimensions. Si l’on veut, par exemple, traiter les éléments du fichier « MATRICE » comme ceux d’une matrice de nombre réels de 10 lignes et 5 colonnes, on écrira :
700 OPEN "MATRICE" AS 5
710 DIM #5 N(9,4)
Les tableaux virtuels à deux dimensions peuvent également contenir des entiers, des réels ou des chaînes de caractères ; dans ce dernier cas, il faut aussi spécifier la longueur des chaînes si l’on veut utiliser une longueur différente de la longueur par défaut.
SBASIC supporte un nombre quelconque de dimensions à condition que le nombre total d’éléments ne dépasse pas 2147483647.
Utilisation des tableaux virtuels
Après l’ouverture du fichier et la déclaration au moyen de l’instruction DIM, le tableau virtuel peut être utilisé dans des instructions d’affectation et dans des expressions comme un tableau ordinaire, avec, toutefois, les restrictions suivantes :
- Il ne peut apparaître comme paramètre ou comme élément de la liste d’appel d’un sous-programme (instruction SUB) ;
- Aucun de ses éléments ne peut être modifié au moyen des instructions SET, LSET, RSET et SWAP.
Pour créer le fichier contenant les 10 premiers carrés introduit plus haut, on écrit :
100 OPEN "VIRT" AS 1
110 DIM #1 NO%(10)
120 FOR I%=1 TO 10
130 NO%(I%)= I%* I%
140 NEXT I%
150 CLOSE 1
Dans ce programme, les écritures dans le fichier sont réalisées au moyen des affectations exécutées en ligne 130 ; il ne faut pas, pour un tableau virtuel, utiliser l’instruction PRINT # ; cette dernière est réservée aux fichiers séquentiels.
Toutefois on retrouve le même mécanisme que celui mis en œuvre lors de l’utilisation de fichiers à accès séquentiel : l’écriture effective dans le fichier n’est pas vraiment réalisée lors de l’exécution de la ligne 130. Les données sont seulement stockées dans une mémoire tampon (buffer) de transit qui est périodiquement écrite sur disque. Il faut donc se souvenir que l’instruction CLOSE de la ligne 150 permettra non seulement de libérer le canal utilisé par le tableau virtuel, mais qu’elle provoquera aussi l’écriture sur le fichier de la partie résiduelle des données qui pourrait se trouver encore dans la mémoire tampon.
Pour modifier l’une des valeurs du fichier d’entiers précédemment écrit sur disque sous le nom « VIRT.DAT », il suffit d’écrire :
100 OPEN "VIRT" AS 1
110 DIM #1, NO%(10)
120 INPUT "Rang de la valeur à modifier"; I%
130 IF I%=0 THEN 200
140 PRINT "Valeur courante :"; NO%(I%)
150 INPUT "Nouvelle valeur :"; NO%(I%)
160 GOTO 120
200 CLOSE 1: END
L’utilisation de la valeur NO%(I%), en ligne 140, suffit pour forcer SBASIC à la relire dans le fichier.
L’affectation réalisée grâce à l’instruction INPUT en ligne 150, suffit pour écrire la nouvelle valeur dans le fichier.
Un programme similaire de mise à jour peut aussi être écrit pour un fichier de chaînes.
Remarques sur les tableaux virtuels
Un fichier créé et référencé comme tableau virtuel ne comporte pas d’information sur la dimension du tableau et le type des données qu’il contient.
Un secteur de 512 octets, peut être considéré comme contenant :
- 64 réels (codés sur 8 octets chacun par la fonction CVTF$)
- 256 entiers (codés sur 2 octets chacun par la fonction CVT%$)
- 4 chaînes de 128 caractères
- 16 chaînes de 32 caractères
Une matrice est rangée par lignes, c’est-à-dire en commençant par la ligne 0 au début du fichier, suivie de la ligne 1, etc. Cette disposition est importante pour deux raisons :
- L’accès séquentiel aux éléments d’une matrice est plus rapide lorsqu’il est réalisé ligne par ligne que colonne par colonne. En effet l’accès par ligne réalisera une lecture séquentielle du fichier, secteur après secteur, alors que l’accès par colonne va multiplier le nombre de chargements en mémoire des secteurs.
- La déclaration de dimension d’un tableau virtuel comprend un ou deux indices, alors qu’un fichier est une collection d’objets séquentiels qu’un programme peut exploiter en définissant, de façon externe au fichier, une structure plus élaborée -une matrice- qui n’est d’ailleurs pas forcément figée.
Supposons par exemple qu’un tableau virtuel ait été créé comme une matrice 50x50 par l’instruction :
DIM #1 A(49,49)
Le fichier disque correspondant contient alors 2500 éléments qui pourront par la suite être considérés comme une simple liste dont la dimension peut être inférieure à 2500, certains éléments restant ignorés du programme.
Ce même fichier pourra donc être ultérieurement ouvert en lecture et dimensionné au moyen de l’instruction
DIM #1 B(1000)
ce qui permettra d’accéder aux mille premiers éléments de ce fichier.
Extension d’un tableau virtuel
Lors de sa création, un fichier à accès direct ne contient aucun secteur accessible à l’utilisateur. La référence en lecture à un élément d’un tableau virtuel non écrit provoquera une erreur 24 semblable à une erreur fin de fichier, en lecture d’un fichier séquentiel.
Un fichier à accès direct peut être étendu à tout moment en affectant une valeur à un élément du tableau virtuel extérieur au fichier. Chaque fois qu’une extension est demandée, SBASIC ajoute au fichier, si nécessaire, les enregistrements se trouvant dans le même secteur que 1’enregistrement écrit ; mais ces derniers sont alors remplis de caractères NUL (CHR$(0)).
Exemple :
100 OPEN "DATA" AS 1
120 DIM # 1 A(250)
130 PRINT A(250)
provoquera une erreur 24, car l’élément 250 n’existe pas dans le fichier nouvellement créé. Pour contenir 250 éléments le fichier doit être étendu de la façon suivante :
100 OPEN "DATA" AS 1
120 DIM # 1 A(250)
125 A(250)=0
130 PRINT A(250)
Nous avons décrit jusqu’à présent deux méthodes d’entrée-sortie disque : la méthode séquentielle avec les instructions PRINT # et INPUT #, et la méthode d’accès direct avec les tableaux virtuels. L’accès séquentiel est simple à utiliser, mais restreint les possibilités d’accès aux données contenues dans un fichier. Les tableaux virtuels assurent un accès sélectif rapide, mais ne permettent pas de mélanger différents types de données dans un même fichier.
SBASIC propose une troisième méthode d’entrée-sortie sur disque, la méthode d’accès direct par enregistrement. Les données sont accessibles de façon aléatoire et tous les types (entier, réel, chaîne de caractères) peuvent être présents dans le même fichier. Les fichiers utilisés dans ce cas sont aussi appelés fichiers à accès direct.
Cette méthode repose sur le fait que les données écrites sur disque sont contenues dans des enregistrements physiques de longueur fixe. Chaque enregistrement d’un fichier doit pouvoir être lu ou écrit sur demande, indépendamment des données qu’il contient. Dans chacun des enregistrements on peut mettre des chaînes de caractères aussi bien que des données numériques, entières ou réelles, écrites en binaire, ce qui évite leur conversion lors des opérations d’entrée-sortie. La méthode est donc efficace et rapide pour traiter les données contenues dans un fichier disque.
Dans la suite nous envisagerons le traitement d’un fichier du personnel, contenant pour chaque employé les renseignements suivants :
- Un nom contenant au plus 30 caractères,
- Un prénom contenant au plus 12 caractères,
- Un salaire, nombre réel codé sur 8 caractères par la fonction CVTF$.
On utilisera donc un fichier à accès direct dont chaque enregistrement aura pour longueur 50 octets, somme des longueurs de chacun des trois champs listés ci-dessus.
Ouverture des fichiers accessibles par enregistrement
Les fichiers auxquels on peut accéder par enregistrement sont des fichiers à accès direct semblables à ceux utilisés pour stocker les tableaux virtuels. Ils sont également ouverts au moyen l’instruction OPEN. Il faut noter que toute tentative d’accès direct sur un fichier séquentiel provoquera une erreur.
Si l’on veut créer, mettre à jour ou tout simplement utiliser le fichier à accès direct, « PERSON.DAT », décrit ci-dessus, contenant les noms, les prénoms et les salaires des employés d’une société, il suffit d’exécuter :
100 OPEN "PERSON" AS 1 LEN 50
qui indique a SBASIC de réserver le canal 1 pour communiquer avec le fichier disque « PERSON.DAT », dont chaque enregistrement a pour longueur 50.
Communication entre le disque et la mémoire centrale
Un fichier à accès direct communique avec la mémoire centrale de l’ordinateur par l’intermédiaire d’une zone tampon – la mémoire tampon - dont la longueur est égale à la longueur d’un enregistrement et qui contient l’enregistrement en cours de traitement.
Les instructions GET et PUT, que nous verrons dans la deuxième partie, permettent le transfert des données d’un enregistrement vers la mémoire tampon et inversement, de la mémoire tampon vers un enregistrement du disque. Il faut donc affecter des valeurs aux différents éléments de cette mémoire tampon ou, inversement, lire celles provenant du fichier.
Il convient donc au préalable définir les différentes zones de cette mémoire tampon en lui associant des variables. Cela est réalisé au moyen d’une forme spéciale de l’instruction FIELD ; chaque zone du tampon est alors identifiée par une variable de type chaîne de caractères.
Dans l’exemple qui nous préoccupe, nous utiliserons les variables suivantes :
- NOM$ d’au plus 30 octets pour le nom de l’employé
- PRE$ d’au plus 12 octets pour le prénom de l’employé
- SAL$ pour le salaire de l’employé, codé au moyen de la fonction CVTF$
Il faut alors associer ces variables à la mémoire tampon du fichier ouvert sur le canal 1, ce qui-est réalisé au moyen de l’instruction suivante :
110 FIELD #1, 30 AS NOM$, 12 AS PRE$, 8 AS SAL$
qui découpe le tampon d’entrée-sortie en trois zones associées respectivement aux variables NOM$, PRE$ et SAL$.
Mais on souhaite aussi désigner par NNN$ l’ensemble nom + prénom. Il suffit alors d’exécuter la ligne 115 après la ligne 110 :
115 FIELD #1, 42 AS NNN$
ce qui permettra de disposer de 4 variables de communication entre le programme et la mémoire tampon associée au fichier.
Il faut toutefois prendre garde au fait que les variables NOM$, PRE$, SAL$ et NNN$ sont d’un genre très particulier et qu’il ne faut jamais leur affecter de valeurs au moyen d’une instruction LET - implicite ou explicite -, ce qui aurait pour conséquence d’annuler leur lien avec la mémoire tampon associée au fichier. Il ne faut donc utiliser que les instructions RSET, LSET ou SET lorsque l’on désire affecter directement une valeur à l’une de ces variables.
Il faut aussi se rappeler que le contenu de chacune d’entre elles est modifié chaque fois que l’on change le contenu de la mémoire tampon associée au moyen à l’instruction GET.
De même, il ne faut pas s’étonner que la modification du contenu de PRE$ par exemple, entraîne celle de la valeur de NNN$ dont PRE$ contient en fait les 12 derniers caractères.
On peut écrire dans la mémoire tampon grâce aux instructions suivantes :
200 RSET NOM$="DUPONT"
210 RSET PRE$="Jean"
ce qui donnera, à la variable NNN$, la valeur : DUPONT_____________________Jean____________
où le caractère « _ » représente un espace, les chaînes « DUPONT » et « Jean » ayant été complétées par suffisamment d’espaces pour s’adapter aux longueurs données pour les variables NOM$ et PRE$.
Pour enregistrer, par exemple, le salaire de 8715,25 dans la zone correspondante, il faut utiliser l’instruction :
215 RSET SAL$=CVTF$(8715.25)
qui écrit dans la troisième zone de la mémoire tampon la représentation binaire du nombre réel 8715.25. Cette représentation binaire n’a rien à voir avec la chaîne permettant d’imprimer ce nombre et qui serait obtenue au moyen de la fonction STR$ ; c’est une suite des huit octets permettant de coder ce nombre en mémoire centrale ; elle est illisible pour le commun des mortels, mais présente un double avantage :
- Elle offre un format fixe de 8 octets quelle que soit la valeur du nombre représenté,
- Elle évite les conversions lors de la lecture ou de l’écriture d’un enregistrement.
Si l’on veut enregistrer un nombre entier dans un fichier il faut lui associer, dans la mémoire tampon, une variable de longueur 2 et le coder grâce à la fonction CVT%$, qui permet d’obtenir la chaîne des deux octets représentant ce nombre en mémoire centrale.
Les instructions GET et PUT
L’écriture des données dans la mémoire tampon comme précédemment, il faut transférer le contenu de cette dernière vers le fichier. On réalise cela grâce à l’instruction PUT. Ainsi, l’instruction :
300 PUT #1 RECORD 5
permet d’écrire le contenu la mémoire tampon dans l’enregistrement numéro 5 du fichier : DUPONT________________________Jean_________8715.25
Si l’on exécute ensuite :
400 RSET PRE$="Jacques"
410 PUT #, RECORD 8
on transfère la mémoire tampon, qui vaut alors : DUPONT________________________Jacques_____8715.25
dans l’enregistrement numéro 8 du fichier.
De même :
500 RSET NOM$="DURAND": RSET PRE$="Pierre": RSET SAL$=CVTF$(6123.20)
510 PUT #1 RECORD 12
permet d’écrire le contenu de la mémoire tampon : DURAND________________________Pierre_______6132.20
dans l’enregistrement numéro 12 du fichier ouvert sur le canal 1.
Pour relire les données figurant dans un enregistrement du fichier, il faut commencer par les transférer dans la mémoire tampon au moyen de l’instruction GET, ce qui modifie automatiquement le contenu des variables associées à ce tampon.
Dans notre exemple, pour relire l’enregistrement numéro 8, il suffit d’exécuter :
600 GET #1 RECORD 8
Si l’on exécute ensuite :
610 PRINT NOM$, PRE$, CVT$F(SAL$)
on verra s’afficher dans la fenêtre SBASIC : DUPONT________________________Jacques_____8715.25
Il ne faut veiller à utiliser la fonction CVT$F, symétrique de la fonction CVTF$, qui permet de convertir en un nombre affichable la chaîne SAL$ codée en format interne.
Dans les instructions PUT et GET, la partie RECORD… est optionnelle : si elle n’est pas spécifiée, c’est l’enregistrement suivant le dernier auquel on a accédé qui est lu ou écrit (accès séquentiel).
Tenter de lire un enregistrement du fichier qui n’a pas été préalablement écrit provoque une erreur. Ecrire un enregistrement de numéro supérieur au dernier enregistrement écrit étend automatiquement le fichier.
Dans l’exemple qui nous intéresse, essayer de lire l’enregistrement numéro 17, provoque une erreur 24.
Il en est de même pour l’accès à l’enregistrement numéro 5.
Extension des fichiers à accès direct
Le mécanisme de création et d’extension des fichiers à accès direct est le même que pour les fichiers associés aux tableaux virtuels. Lors de sa création, le fichier ne contient aucun enregistrement. Tenter de lire un enregistrement inexistant provoque une erreur 24. Le fichier peut être étendu à tout moment par l’écriture d’un enregistrement qui n’existe pas encore.
Chaque fois qu’un enregistrement est écrit, SBASIC ajoute au fichier, si nécessaire, les enregistrements se trouvant dans le même secteur et qui n’ont pas encore été écrits ; ils sont alors remplis de caractères nuls, tels que ceux obtenus au moyen de la fonction CHR$(0).
Par exemple, l’exécution du programme :
10 KlLL "TESTD"
20 OPEN "TESTD” AS 1
30 FIELD #1, 100 AS G$
40 GET #1 RECORD 20
provoque une erreur 24. Il est donc nécessaire d’étendre le fichier avant toute lecture de l’enregistrement numéro 20 :
10 KILL "TESTD"
20 OPEN "TESTD" AS 1
30 FIELD #1, 100 AS G$
34 LSET G$="ENREGISTREMENT NUMERO 20"
38 PUT #1 RECORD 20
40 GET #1 RECORD 20
Exemple d’utilisation d’un fichier à accès direct
Le programme suivant montre comment on peut accéder à un fichier à accès direct. On considère le fichier du personnel précédemment décrit, dont chaque enregistrement contient des renseignements sur un employé : son nom, son prénom, son salaire. Le numéro d’enregistrement identifie l’employé. Le programme imprime les éléments correspondant à un employé dont on a donné le numéro d’identification et en permet la modification.
Le nom de l’employé est rangé dans les 30 premiers caractères de l’enregistrement, son prénom dans les 12 suivants et son salaire dans les 8 derniers.
98 REM *** Ouverture du fichier et définition des variables ***
100 OPEN "PERSON" AS 1 LEN 50
120 FIELD #1, 30 AS NOM$, 12 AS PRE$, 8 AS SAL$
125 FIELD #1, 42 AS NNN$
198 REM *** Saisie du numéro d'enregistrement à modifier ***
199 ON ERROR GOTO 250
200 INPUT "NUMERO DE L'EMPLOYE"; I%
210 IF I%=0 THEN 500
220 GET #1 RECORD I%
230 PRINT "Employé :"; NNN$
240 PRINT "Salaire : "; CVT$F(SAL$) : GOTO 300
248 REM *** Gestion de l'erreur "Enregistrement non trouvé"***
250 PRINT "Enregistrement inexistant"
260 RESUME 200
298 REM *** Mise à jour du contenu de la mémoire tampon (buffer)***
300 PRINT "Nom " ; : INPUT LINE R$
305 IF R$ <> "" THEN LSET NOM$=R$
320 PRINT "Prénom " ; : INPUT LINE R$
325 IF R$<>"" THEN LSET PRE$=R$
330 PRINT "Salaire " ; : INPUT LINE R$
335 IF R$<>"" THEN LSET SAL$=CVTF$(VAL(R$))
398 REM *** Ecriture de l'enregistrement ***
400 PUT #1 RECORD I%: GOTO 200
498 REM *** Fin de programme
500 CLOSE 1
510 END
Le fichier « PERSON.DAT » est ouvert sur le canal 1, puis les variables NOM$, PRE$, SAL$ et NNN$ sont associées à la mémoire tampon (buffer).
La ligne 200 demande le numéro identifiant l’employé afin de pour lire l’enregistrement le concernant. La valeur 0 permet de terminer la session. En cas de demande par l’utilisateur d’un enregistrement non présent, la ligne 210 permet un branchement en ligne 250 qui affiche un message explicatif. Dans les autres cas, les caractéristiques de l’employé sont affichées.
Les lignes 300 à 399 permettent la modification des données écrites dans le fichier. L’utilisation de l’instruction INPUT LINE autorise une réponse vide et, dans ce cas, de ne pas modifier la valeur affichée.
La ligne 400 provoque la réécriture dans le fichier du contenu la mémoire tampon (buffer) puis boucle sur une nouvelle demande.
Enfin la ligne 500 permet de fermer le fichier et termine le programme.
Gestion des erreurs
Les erreurs qui peuvent être signalées au cours de l’exécution d’un programme se répartissent en deux classes :
- Les erreurs d’entrée-sortie (disque, clavier, écran).
- Les erreurs de syntaxe ou d’exécution.
La liste complète des numéros d’erreur et leur signification est donnée en 0 « Liste des codes d’erreurs ». Les numéros d’erreur sont compris entre 1 et 49 pour les erreurs d’entrée-sortie et sont supérieurs à 49 pour les erreurs syntaxe ou d’exécution.
En général SBASIC signale l’erreur et arrête l’exécution du programme. Il est toutefois parfois utile de pouvoir continuer l’exécution en particulier quand les erreurs sont du premier type. L’ordre ON ERROR permet de gérer les erreurs signalées par SBASIC.
Il faut noter que la gestion des erreurs est locale aux sous-programmes appelés par l’instruction CALL.
Activation d’une procédure de gestion d’erreur
L’instruction ON ERROR GO TO num-ligne
, où num-ligne
désigne un numéro de ligne, strictement positif, permet de gérer les erreurs détectées par SBASIC. num-ligne
est le numéro de la ligne où doit se brancher le programme en cas d’erreur.
Chaque fois que SBASIC détecte une erreur, il vérifie si une instruction ON ERROR GOTO num-ligne
a été préalablement exécutée. Si tel est le cas, le contrôle est transféré à la ligne num-ligne
indiquée dans l’instruction ON ERROR GOTO.
La syntaxe d’une ligne de programme utilisant cette instruction est la suivante :
num-ligne-1
ON ERROR GO TO 'num-ligne-2'
Pour être efficace cette instruction doit être exécutée avant toute instruction susceptible de provoquer une erreur.
Dans sa procédure de gestion d’erreur l’utilisateur peut tester et utiliser les variables systèmes ERR et ERL qui contiennent, respectivement, le numéro de la dernière erreur rencontrée et le numéro de la ligne où elle s’est produite.
Reprise après gestion d’erreur
L’instruction RESUME permet de reprendre l’exécution du programme principal une fois le programme de gestion d’erreur exécuté. Elle permet de réactiver la procédure de gestion d’erreur associée à la dernière instruction ON ERROR GOTO num-ligne
exécutée.
La syntaxe en est :
num-ligne
RESUME [num-ligne
]
Si un numéro de ligne est fourni après RESUME, SBASIC reprendra l’exécution du programme à cette ligne. Si aucun numéro de ligne n’est fourni (ou si ce numéro est 0) SBASIC interprète cette instruction en réexécutant toute la ligne où l’erreur s’est produite, et non pas uniquement l’instruction qui a provoqué l’erreur.
Il ne faut pas oublier que le rôle de cette instruction ne se limite pas à celui d’un branchement, que nous venons de mettre en évidence. Elle réactive aussi la procédure de gestion d’erreur. Sa substitution par une simple instruction GOTO ne permettrait pas de prendre en charge l’erreur qui pourrait se produire dans la suite du programme.
Inhibition d’une procédure de gestion d’erreur
Parfois, seules certaines sections de programmes nécessitent l’activation d’une procédure de gestion d’erreur. Il est possible d’annuler l’ordre ON ERROR GOTO num-ligne
en utilisant l’une ou l’autre des lignes :
num-ligne
ON ERROR GOTO
num-ligne
ON ERROR GOTO 0
Ces deux lignes sont équivalentes et ont pour effet d’annuler tous les ordres ON ERROR GOTO activés.
Si l’on se trouve en situation de récupération d’erreur et que l’on n’a pas encore exécuté d’instruction RESUME, cette instruction annule la prise en charge de l’erreur et rend la main à SBASIC qui affiche l’erreur dans le format standard puis arrête l’exécution du programme.
Il faut aussi se souvenir que l’exécution d’une instruction ON ERROR GOTO à l’intérieur d’un sous-programme permet d’activer localement la procédure de gestion d’erreur référencée dans le numéro de ligne.
Si une procédure de gestion d’erreur était active lors de l’appel du sous-programme, le numéro de ligne correspondant est mémorisé. Cette procédure est réactivée lors de l’exécution de l’instruction RETURN terminant le sous-programme.
Exemples de gestion d’erreurs
Dans le programme suivant, l’utilisateur doit entrer 3 nombres dont le programme édite la somme dans la fenêtre SBASIC.
100 ON ERROR GOTO 1000
110 INPUT "ENTREZ 3 NOMBRES", A, B, C
120 PRINT "LA SOMME EST "; A+B+C
140 GOTO 110
1000 IF ERR<>30 THEN GOTO 1030
1010 PRINT " ENTREZ UNIQUEMENT DES NOMBRES"
1020 RESUME
1030 ON ERROR GOTO
Ce programme prévoit et prend en charge une possible erreur de l’utilisateur. Ce dernier pourrait en effet entrer des caractères non numériques, provoquant ainsi une erreur 30 lors de l’addition des variables correspondantes, à la ligne 120. Le programme gérant cette erreur débute en ligne 1000, mais il ne récupère que l’erreur 30. Les autres provoqueront l’arrêt du programme : c’est, entre autres, le cas de l’erreur 34, associée à l’utilisation des touches Ctrl-C
, qui permet à l’utilisateur d’interrompre le programme.
Le programme suivant demande de saisir le nom d’un fichier. Si ce dernier est présent sur le disque, travail le programme liste son contenu dans la fenêtre SBASIC.
10 INPUT "TAPEZ LE NOM DU FICHIER AVEC SON EXTENSION"; F$
20 ON ERROR GOTO 1000
30 OPEN OLD F$ AS 1
40 INPUT LINE #1 L$
50 PRINT L$
60 GOTO 40
100 CLOSE 1
110 END
1000 IF ERR = 8 THEN PRINT "Fin de fichier": END
1010 IF ERR = 4 THEN PRINT "Fichier absent": END
1020 PRINT "Erreur";ERR;"à la ligne";ERL: RESUME 10
Si Le fichier n’existe pas (Erreur système numéro 4), le programme affiche le message « Fichier absent » puis s’arrête.
Si le fichier existe sur le disque, le programme le liste, puis affiche le message « Fin de fichier » lorsque la fin du fichier est rencontrée (Erreur système 8), puis il s’arrête.
Pour les autres erreurs, par exemple si le nom du fichier est incorrect (Erreur système 21), il affiche « Erreur numéro de l’erreur à la ligne numéro de ligne » et reprend l’exécution à la ligne 10.
Codes d'erreur
2 Le fichier requis est déjà utilisé
3 Le fichier spécifié existe déjà
4 Le fichier spécifié n a pas été trouvé
5 Erreur en ouverture de fichier
6 Création fichier impossible
7 Tout l espace disque a été utilisé
8 Fin de fichier rencontrée en lecture
9 Erreur de lecture sur disque
10 Erreur d écriture sur disque
11 Fichier trop grand
12 Fichier protégé
13 Bloc de contrôle de fichier illégal
15 Numéro d unité disque illégal
16 Unité disque non prête
17 Le fichier est protégé - accès refusé
18 Format fichier compilé incompatible
20 Type de fichier à accès direct non défini
21 Spécification de fichier illégale
22 Erreur en fermeture de fichier
23 Débordement de la table d allocation - disque trop fragmenté
24 Numéro d enregistrement inexistant
29 Enregistrement verrouillé
30 Type de données non concordant
31 Hors donnée dans une instruction READ
32 Mauvais argument dans une instruction ON
40 Erreur de canal
41 Fichier déjà ouvert
42 Mode d ouverture du fichier erroné
43 Le fichier n a pas été ouvert
44 Erreur d état fichier
45 Taille trop grande dans FIELD
49 Répertoire non trouvé
50 Instruction non reconnue
51 Caractère illégal dans la ligne
52 Erreur de syntaxe
53 Fin de ligne illégale
54 Numéro de ligne illégal (<=0)
55 Parenthèses non balancées
56 Référence illégale à une fonction
58 THEN manquant dans une instruction IF
60 Ligne non trouvée
61 Return sans CALL ou sans GOSUB
62 Erreur FOR NEXT
63 Ne peut continuer
64 Source absent
65 Mauvais fichier - ne peut être chargé
66 RESUME hors traitement d erreur
67 Mauvais arguments dans DIGITS
68 Argument valide
69 Format fichier image invalide
70 Erreur de type dans une instruction PRINT USING
71 Format illégal dans une instruction PRINT USING
72 Types de opérandes incompatibles
73 Expression illégale
74 Argument <0 ou >255
75 Argument <=0
76 Type de variable illégal
77 Référence à un tableau hors dimension
78 Référence à un tableau non dimensionné
79 Mauvais argument dans une instruction SWAP
80 Débordement mémoire
81 Débordement tableau
82 Débordement mémoire programme
83 Chaîne trop longue
84 Trop d arguments dans une instruction SUB ou LOCAL
85 Chaîne vide dans une instruction EXECUTE
86 Chaîne trop longue dans une instruction EXECUTE
88 Redimensionnement d un tableau
89 Effacement d une ligne référencée
90 Fonction USR non définie
92 Argument virtuel dans l instruction
93 Instruction SUB sans CALL
94 Mauvaise longueur de chaîne spécifiée
95 Instruction LOCAL sans SUB
96 Libération par CLEAR d un tableau virtuel non fermé
97 Position curseur impossible
98 Mauvais argument dans l instruction CLEAR
99 Type erroné dans les arguments d un CALL
100 Expression trop complexe
101 Débordement virgule flottante
102 Argument trop grand
103 Division par zéro
104 Réel trop grand pour une conversion en entier
105 Argument négatif ou nul pour une fonction LOG
106 Erreur de conversion en entier dans une instruction INPUT
107 Racine carrée imaginaire
108 Erreur de conversion (nombre trop grand)
109 Débordement dans une opération entière
110 Numéro de couleur erroné
111 Numéro de port impossible
114 Ligne vide dans EDIT
115 No de ligne absent dans EDIT
128 Erreur non récupérable
Gestion des programmes volumineux
L’instruction CHAIN
Lorsqu’un programme est trop grand pour tenir en mémoire et y être exécuté, il doit être divisé en plusieurs segments. L’instruction CHAIN permet de charger et d’exécuter successivement plusieurs programmes. Les segments de programme doivent être soit de type .BAS
, soit des programmes compilés de type .BAC
. Chaque segment est un fichier et n’importe quel programme résidant sur disque peut être appelé par CHAIN. La syntaxe en est :
num-ligne
CHAIN nom-fich
[exp-num
]
Le fichier référencé par nom-fich
est chargé. L’expression exp-num
, optionnelle , désigne le numéro de ligne où le programme nouvellement chargé doit commencer à être exécuté. Notez l’absence de virgule entre les deux expressions.
Exemple :
1300 CHAIN "BALANCEZ" 100
Cette ligne charge le fichier BALANCEZ.BAC
et lance son exécution à la ligne 100.
Chaîner un programme compilé (de type .BAC
), est plus efficace que chaîner un programme écrit en langage source (.BAS
). Les communications entre programmes ainsi chaînés doivent être réalisés par l’intermédiaire de fichiers disque. En effet, lorsque l’ordre CHAIN est exécuté, tous les fichiers qui étaient ouverts sont fermés, le nouveau programme est chargé, les anciennes variables sont détruites, et l’exécution du nouveau programme commence. Les fichiers utilisés conjointement par plusieurs programmes doivent être ouverts dans chacun d’entre eux et les variables réinitialisées.
L’instruction OVERLAY
Dans les versions anciennes de SBASIC, l’instruction OVERLAY permettait de réserver une zone fixe de la mémoire pour y placer les lignes de programme. Elle divisait la mémoire disponible en une zone « programme » et une zone « données ». Ainsi, l’insertion de nouvelles lignes de programme n’affectait pas les données qui étaient alors protégées.
Les zones « programme » et « données » sont maintenant disjointes. L’instruction OVERLAY est sans effet. Elle est cependant conservée pour assurer la compatibilité avec les anciens programmes.
La syntaxe en est :
num-ligne
OVERLAY nbre-ligne
où nbre-ligne
est un nombre inférieur ou égal à 511.
Avec SBASIC, il est possible de charger des sous-programmes dans la zone « programme » en mode programme avec les instructions LOAD et BLOAD.
Par exemple, le programme suivant :
10 OVERLAY 50
99 REM *** saisie des éléments ***
100 INPUT "Nombre d'éléments "; NE% : DIM EL(NE%)
110 FOR X% = 1 TO NE%
120 PRINT "élément "; X%;
130 INPUT EL(X%)
140 NEXT X%
199 REM *** Choix de la fonction ***
200 PRINT "0 - QUITTER 1 - Autre tableau"
210 PRINT "2 - Somme 3 - Moyenne 4 - Ecart-type"
220 I%=INSTR(1,"01234",INCH$(0))
230 IF I% = 0 THEN PRINT CHR$(7);: GOTO 220
250 ON I% GOTO 300, 310, 320, 330, 340
300 END
305 REM *** Traitement de la fonction demandée ***
310 CLEAR EL(*): GOTO 100
320 BLOAD "SOMME" : CALL SOMME(NE%,EL(*)) : GOTO 200
330 BLOAD "MOYEN" : CALL MOYEN(NE%,EL(*)) : GOTO 200
340 BLOAD "ECART" : CALL ECART(NE%,EL(*)) : GOTO 200
Programme SOMME.BAC :
1000 SUB SOMME(N%, E(*))
1010 LOCAL I%,X
1020 FOR I%=1 TO N%
1030 X=X+E(I%)
1040 NEXT I%
1050 PRINT "Somme =";X
1060 RETURN
Programme MOYEN.BAC :
1000 SUB MOYEN(N%, E(*))
1010 LOCAL I%,X
1020 FOR I%=1 TO N%
1030 X=X+E(I%)
1040 NEXT I%
1050 PRINT "Moyenne =";X/N%
1060 RETURN
Programme ECART.BAC :
1000 SUB ECART(N%, E(*))
1010 LOCAL I%,X,Y
1020 FOR I%=1 TO N%
1030 X=X+E(I%)
1040 NEXT I%
1050 X=X/N%
1060 FOR I%=1 TO N%
1070 Y=Y+(E(I%)-X)**2
1080 NEXT I%
1090 PRINT "Ecart =";SQR(Y/N%)
1100 RETURN
Ce programme commence par l’instruction OVERLAY pour réserver une zone de 50 lignes. Cette instruction est ignorée et peut être supprimée. Puis l’utilisateur est invité à saisir une série de données numériques (lignes 110 à 140). Il choisit ensuite le type de calcul (somme, moyenne ou écart-type) devant être effectué sur cette série. Une même zone du programme peut donc être utilisée pour des traitements différents, en fonction des besoins.
Cet exemple simple permet de se rendre compte de toute la puissance du SBASIC.
Gestion de l’imprimante
Sous Windows, les impressions ne se font plus en direct. C’est pourquoi SBASIC gère un tampon d’impression. Les commandes du sous-menu « Imprimante » de la fenêtre SBASIC permettent de vider le tampon d’impression ou d’éditer son contenu et l’imprimer à travers NOTEPAD.
SBASIC sous Windows
Sous Windows, SBASIC est proposé en 2 formats : fenêtre ou ligne de commande.
La fenêtre SBASIC se rapproche le plus de la version originale sous MS/DOS au niveau de l’édition de ligne. Elle est complétée par un menu et une aide en ligne. Le fichier exécutable correspondant est SB32.EXE.
En ligne de commande, SBASIC tire partie des fonctionnalités de la console Windows. Le fichier exécutable est SBASIC.EXE.
SB32.EXE et SBASIC.EXE partagent le même moteur. Seule l’interface texte diffère.
Fenêtre SBASIC (SB32.EXE)
Afin de garder la compatibilité avec les applications SBASIC sous MS/DOS, la fenêtre SBASIC affiche un écran de 25 lignes de 80 caractères. La taille de l’écran SBASIC peut être modifiée par l’instruction TEXT. Lorsque la taille de la fenêtre SBASIC est réduite, des curseurs permettent de naviguer horizontalement et verticalement à l’intérieure de cet écran.
Nouveau sous Windows, le curseur vertical permet de naviguer à travers les lignes de texte précédemment affichées. L’équivalent de 10 écrans est mémorisé. La molette de la souris permet aussi de naviguer verticalement. Dès que le curseur d’affichage se déplace, la fenêtre SBASIC est automatiquement recentrée autour de celui-ci.
Edition ligne
Comme pour SBASIC sous MS/DOS, la combinaison de touches Ctrl-R
, utilisée au tout début d’une édition de ligne, permet de récupérer la dernière ligne entrée.
Nouveau sous Windows, les touches ↑ (flèche en haut) et ↓ (flèche en bas), utilisées au tout début d’une édition de ligne, permettent de retrouver une ligne parmi les 100 dernières lignes entrées. Si ces lignes sont utilisées sans modification, une séquence de ligne peut être simplement ré exécutée.
Nouveau aussi sous Windows, la combinaison de touches Ctrl-V
réalise un collé du texte présent dans le presse-papier.
Menu fenêtre SBASIC
Les commandes SBASIC de sauvegarde et de chargement des programmes sont accessibles directement à partir du menu « Fichier » de la fenêtre SBASIC. Dans le menu « Programme » se trouvent les commandes contrôlant l’exécution.
Aide
Un clic de souris sur un mot clé dans la fenêtre SBASIC ouvre une fenêtre d’aide sur celui-ci.
Photographie fenêtre graphique
Lorsque la fenêtre graphique est sélectionnée, la combinaison de touches Ctrl-P
effectue une photographie de cette fenêtre. Une fenêtre de dialogue permet de sauvegarder la photographie dans un fichier BMP.
Appel fonctions DLL
L'instruction OPEN LIBRARY permet de charger une librairie à chargement dynamique (DLL). Les fonctions de la librairie peuvent être appelées par l'instruction CALL.
Installation
Sous Windows, l’interpréteur SBASIC se présente sous la forme de 2 fichiers exécutables SB32.EXE (mode fenêtre) et SBASIC.EXE (mode ligne de commande). Son installation consiste simplement en la copie d’un de ces fichiers dans un répertoire de l’ordinateur.
Les différentes méthodes de lancement d’un programme au format .EXE peuvent être utilisées. Par exemples :
- Création, sur le bureau, d’un raccourci vers le fichier SB32.EXE ou SBASIC.EXE. Dans les propriétés du raccourci on spécifiera comme répertoire de travail, le répertoire contenant les fichiers SBASIC avec l’extension
.BAS
ou.BAC
. L’interpréteur SBASIC se lance alors par un double-clic sur l’icône SBASIC : - Un programme SBASIC peut être lancé directement en glissant le nom du fichier contenant le programme SBASIC sur l’icône SBASIC.
- Définition de SB32.EXE ou SBASIC.EXE comme programme associé aux extensions
.BAS
et.BAC
. Un programme SBASIC se lance alors en double-cliquant, dans l’explorateur de fichier, sur le nom du fichier contenant ce programme. - Pour que la commande SBASIC soit reconnue en ligne de commande, le fichier SBASIC.EXE doit être placé dans un répertoire spécifié dans le PATH (par exemple le répertoire C:\Windows).