Display of numbers and character strings

published: 22 December 2024 / updated 22 December 2024

Lire cette page en français

 

Affichage des nombres et chaînes de caractères

article: 24 mai 2019 / mis à jour 25 mai 2019

Changement de base numérique

Applicable également sur Flash Forth pour Arduino

FORTH ne traite pas n'importe quels nombres. Ceux que vous avez utilisés en essayant les précédents exemples sont des entiers signés simple précision. Le domaine de définition des entiers simple précision est compris entre moins 32768 et plus 32767. Exemple:

32767 .         \ affiche    32767 
-32768 .        \ affiche    -32768 
65535 .         \ affiche    -1 ( sur systèmes FORTH avec pile 16 bits) 

Ces nombres peuvent être traités dans n'importe quelle base numérique, toutes les bases numériques situées entre 2 et 36 étant valides:

255 HEX . DECIMAL    \ affiche    FF 

On peut choisir une base numérique encore plus grande, mais les symboles disponibles sortiront de l'ensemble alpha-numérique [0..9,A..Z] et risquent de devenir incohérents. Exemple:

DECIMAL 255 BASE ! 
    ò 2 + . 

fonctionnera, mais n'est guère concevable sur un plan sémantique.

La base numérique courante est controlée par une variable nommée BASE et dont le contenu peut être modifié. Ainsi, pour passer en binaire, il suffit de stocker la valeur 2 dans BASE. Exemple:

2 BASE ! 

et de taper DECIMAL pour revenir à la base numérique décimale.

Forth dispose de deux mots pré-définis permettant de sélectionner différentes bases numériques:

Dès sélection d'une de ces bases numériques, les nombres litéraux seront interprétés, affichés ou traités dans cette base. Tout nombre entré précédemment dans une base numérique différente de la base numérique courante est automatiquement converti dans la base numérique actuelle. Exemple:

DECIMAL     \ base en décimal 
255         \ empile 255 
HEX         \ sélectionne base hexadécimale 
1+          \ incrémente 255 devient 256 
.           \ affiche     100 

On peut définir sa propre base numérique en définissant le mot approprié ou en stockant cette base dans BASE. Exemple:

: BINARY ( ---)         \ sélectionne la base numérique binaire 
    2 BASE ! ; 
DECIMAL 255 BINARY .    \ affiche     11111111 

Le contenu de BASE peut être empilé comme le contenu de n'importe quelle autre variable:

VARIABLE RANGE_BASE     \ définition de variable RANGE-BASE 
BASE @ RANGE_BASE !     \ stockage contenu BASE dans RANGE-BASE 
HEX FF 10 + .           \ affiche 10F 
RANGE_BASE @ BASE !     \ restaure BASE avec contenu de RANGE-BASE 

Dans une définition "deux-points", le contenu de BASE peut transiter par la pile de retour:

: OPERATION ( ---) 
    BASE @ >R       \ stocke BASE sur pile de retour 
    HEX FF 10 + .   \ opération du précédent exemple 
    R> BASE ! ;     \ restaure valeur initiale de BASE 

ATTENTION: les mots >R et R> ne sont pas exploitables en mode interprété. Vous ne pouvez utiliser ces mots que dans une définition qui sera compilée.

Définition de nouveaux formats d'affichage

Applicable également sur Flash Forth pour Arduino

Forth dispose de primitives permettant d'adapter l'affichage d'un nombre à un format quelconque. Ces primitives ne traitent que des nombres double précision:

Ces mots ne sont utilisables qu'au sein d'une définition. Exemple, soit à afficher un nombre exprimant un montant libellé en francs avec la virgule comme séparateur décimal:

: EUROS ( ud ---) 
    <# # # ASCII , HOLD #S #> 
    TYPE ." EUR " ; 

Exemples d'exécution:

0.35  EUROS             \ affiche     0,35 EUR 
35.75 EUROS             \ affiche     35,75 EUR 
10.15 35.75 D+ EUROS    \ affiche     45,90 EUR 

La définition de EUROS ne prend pas en compte le signe du résultat, ni la position de la virgule. Si vous tapez:

35. EUROS          \ vous aurez à l'affichage 0,35 EUR 

Dans la définition de EUROS, le mot <# débute la séquence de définition de format d'affichage; les deux mots # placent les chiffres des unités et des dizaines dans la chaîne de caractère; ASCII , HOLD placent le caractère , (virgule) à la suite des deux chiffres de droite, le mot #S complète le format d'affichage avec les chiffres non nuls à la suite de "," le mot #> ferme la définition de format et dépose sur la pile l'adresse et la longueur de la chaîne contenant les digits du nombre à afficher; le mot TYPE affiche cette chaîne de caractères.

En exécution, une séquence de format d'affichage traite exclusivement des nombres entiers double précision signés ou non signés. La concaténation des différents éléments de la chaîne se fait de droite à gauche, c'est à dire en commençant par les chiffres les moins significatifs.

Le traitement d'un nombre par une séquence de format d'affichage est exécutée en fonction de la base numérique courante. La base numérique peut être modifiée entre deux digits.

Voici un exemple plus complexe démontrant la compacité du FORTH. Il s'agit d'écrire un programme convertissant un nombre quelconque de secondes au format HH:MM:SS:

: :00 ( ---) 
    DECIMAL #           \ insertion digit unité en décimal 
    6 BASE !            \ sélection base 6 
    #                   \ insertion digit dizaine 
    ASCII : HOLD        \ insertion caractère : 
    DECIMAL ;           \ retour base décimale 
: HMS ( ud ---)         \ affiche nombre secondes format HH:MM:SS 
    <# :00 :00 #S #> TYPE SPACE ; 

Exemples d'exécution:

59. HMS     \ affiche     0:00:59
60. HMS     \ affiche     0:01:00
4500. HMS   \ affiche     1:15:00

Explication: le système d'affichage des secondes et des minutes est appelé système sexagésimal. Les 'unités' sont exprimées dans la base numérique décimale, les 'dizaines' sont exprimées dans la base six. Le mot :00 défini précédemment gère la conversion des 'unités' et des 'dizaines' dans ces deux bases pour la mise au format des digits correspondants aux secondes et aux minutes. Pour les heures, les digits sont tous décimaux.

Autre exemple, soit à définir un programme convertissant un nombre entier simple précision décimal en binaire et l'affichant au format bbbb bbbb bbbb bbbb:

: QUATRE-DIGITS ( ---) 
    # # # # 32 HOLD ; 
: AFB ( d ---)              \ mise au format 4 digits et un espace 
    BASE @ >R               \ Sauvegarde base courante 
    2 BASE !                \ Sélection base numérique binaire        
    <#  
    4 0 DO                  \ Boucle de mise au format 
        QUATRE-DIGITS  
    LOOP    
    #> TYPE SPACE           \ Affichage en binaire 
    R> BASE ! ;             \ Restauration base numérique initiale 

Exemple d'exécution:

DECIMAL 12. AFB    \ affiche     0000 0000 0000 0110 
HEX 3FC5. AFB      \ affiche     0011 1111 1100 0101 

Encore un exemple, soit à créer un agenda téléphonique où l'on associe à un patronyme un ou plusieurs numéros de téléphone. On définit un mot par patronyme:

: .## ( ---) 
    # # ASCII . HOLD ; 
: .TEL ( d ---) 
    CR <# .## .## .## .## .## #> TYPE CR BYE ; 
: DUGENOU ( ---)  
    .06051254 .TEL ; 
\ ...ici votre agenda téléphonique... 
puis sous DOS:
 

Cet agenda, qui peut être compilé depuis un fichier source, est facilement modifiable, et bien que les noms ne soient pas classés, la recherche y est extrêmement rapide.

Affichage des caractères et chaînes de caractères

L'affichage d'un caractère est réalisé par le mot EMIT:

65 EMIT         \ affiche A 

Les caractères affichables sont compris dans l'intervalle 32..255. Les codes compris entre 0 et 31 seront également affichés, sous réserve de certains caractères exécutés comme des codes de contrôle. Voici une définition affichant tout le jeu de caractères de la table ASCII:

: JEU-ASCII ( ---) 
    DARK 256 32 
    DO  
        I 3 .R SPACE        \ affiche code du caractère 
        I EMIT 2 SPACES     \ affiche caractère 
        #OUT @ 77 =  
        IF  
            CR  
        THEN 
    LOOP ; 

L'exécution de JEU-ASCII affiche les codes ASCII et les caractères dont le code est compris entre 32 et 255. Pour afficher la table équivalente avec les codes ASCII en hexadécimal, taper HEX JEU-ASCII.

Les chaînes de caractères sont affichées de diverses manières. La première, utilisable en compilation seulement, affiche une chaîne de caractères délimitée par le caractère " (guillemet):

: TITRE ." MENU GENERAL" ; 
    TITRE    \  affiche     MENU GENERAL 

a chaîne est séparée du mot ." par au moins un caractère espace.

Une chaîne de caractères peut aussi être compilée par le mot S" et délimitée par le caractère " (guillemet):

: LIGNE1 ( --- adr len) 
    S" E..Enregistrement de données" ; 

L'exécution de LIGNE1 dépose sur la pile de données l'adresse et la longueur de la chaîne compilée dans la définition. L'affichage est réalisé par le mot TYPE:

LIGNE1 TYPE   \ affiche E..Enregistrement de données 

En fin d'affichage d'une chaîne de caractères, le retour à la ligne doit être provoqué s'il est souhaité:

LIGNE1 TYPE  \ affiche E..Enregistrement de données 
CR TITRE CR CR LIGNE1 TYPE CR 
\ affiche 
\ MENU GENERAL 
\ 
\ E..Enregistrement de données 

Un ou plusieurs espaces peuvent être ajoutés en début ou fin d'affichage d'une chaîne alphanumérique:

SPACE         \ affiche un caractère espace 
10 SPACES     \ affiche 10 caractères espace