Les stems sont chargés au préalable à partir de fichiers ou résultent de calculs. Par convention leur nombre d'éléments est toujours indiqué dans stem.0. Pour les tri et recherche il faut tenir compte des problèmes de comparaison et d'ordre de codage des caractères (§ 3.3.2 et 3.4). Dans les exemples suivants la clé testée est en début de ligne, lue par la fonction Left(), mais pourrait être au milieu : utiliser alors la fonction Substr() ou le parsing positionnel afin de toujours comparer des éléments de longueur fixe.
Moyenne glissante sur n valeurs contenues dans le stem data. Le calcul est effectué en deux boucles, pour les numéros de ligne jusqu'à n, puis supérieurs afin d'éviter son test à chaque itération ; le résultat est mis dans mav. :
Effectuer le tri en interne pour les faibles volumes sera plus simple que passer par un fichier intermédiaire et un programme extérieur. La méthode élémentaire, le bubble sort, sur une clé de x caractères :
Plus compliqué mais plus rapide, le shell sort, toujours sur une clé de x caractères :
Recherche de l'argument aa sur les x premiers caractères de chaque ligne ; le tableau est trié au préalable sur la clé de recherche :
Mais pour de faibles volumes une recherche séquencielle évite le tri, s'exécute sans dégradation de performance et détecte les occurences multiples.
Le tableau est trié au préalable suivant la clé. Cet exemple utilise le parsing positionnel : chaque ligne est composée de l'identifiant en colonnes 1 à 4, du nombre à additionner par clé en colonnes 5 à 8, puis le reste à partir de la colonne 9. Les totaux par clé sont écrits dans cumul. :
Pour une même clé, il suffit d'incrémenter un compteur pour le nombre d'occurences, il faut tester chaque valeur par rapport à la précédente pour les maximun ou minimum.
Comparaison sur les x caractères en début de ligne des tableaux ref. et data. triés au préalable sur les clés de rapprochement. Celles de ref. doivent être uniques, data. peut comporter des doubles, c'est pourquoi on teste l'élément suivant avant d'incrémenter la référence. La boucle de comparaison se termine lorsque l'un des deux fichiers est épuisé, il faut alors écrire le reste de l'autre en sortie. Le programme se simplifie si on ne désire conserver que les éléments communs ou s'il n'y a pas de doubles.
Les besoins de manipulation de chaînes de caractères sont très variés et d'autre part il n'y a pas
de solution universelle pour tel ou tel usage, même au prix d'un code très lourd. Ne seront donnés ci
après que quelques exemples.
Certaines opérations sont possibles directement à l'aide des nombreuses
fonctions de traitement des chaînes : substitution et suppression de caractères,
d'autres nécessitent une boucle de traitement.
D'une manière générale le découpage de la chaîne de caractères initiale par
une boucle autorise ensuite n'importe quel traitement dont le résultat est mis
dans une autre chaîne en sortie par concaténations successives.
Les listes de mots séparés par des espaces sont préférables pour profiter
des fonctions dédiées.
Le traitement se rapproche de celui des tableaux : le nombre d'éléments est donné
par Words(), chacun est identifié par Word(n).
Chargement d'un stem à partir d'une chaîne de caractères, le séparateur est un signe quelconque (une virgule dans cet exemple) :
i = 0; sep = ',' Do While Length(chaine) > 0 i = i + 1 Parse Var chaine data.i (sep) chaine End data.0 = i
Pour un découpage en longueur fixe (ici 6 caractères) :
i = 0 Do While Length(chaine) > 0 i = i + 1 Parse Var chaine data.i +6 chaine End
Inversement, conversion d'un tableau en chaîne de caractères. Celle-ci est d'abord initialisée à la longueur x nécessaire (calculée ou estimée par excès) afin d'éviter une réallocation d'espace mémoire pour la variable à chaque itération :
chaine = Copies(' ',x); sep = ',' chaine = data.1 Do i = 2 To data.0 chaine = chaine||sep||data.i End
En s'inspirant des deux exemples précédents on obtient une boucle de traitement des éléments d'une chaîne de caractères et écriture du résultat dans une autre. Ci-dessous mise en majuscule de la première lettre de chaque élément :
On effectue un ou exclusif entre les deux chaînes, position par position, qui donne '00'x pour chaque concordance. Celles-ci sont traduites en points et les différences marquées par un point d'exclamation :
a = Bitxor('abcdef','ab3de') b = Translate(a,'.',,'!') /* donne '..!..!' */ x = Countstr('!',b) /* nombre de différences */
Ou on repère les positions concernées comme dans l'exemple suivant.
Repérage de toutes les positions d'un groupe de caractères dans une chaîne :
La dernière position trouvée est augmentée de la longueur du groupe de caractères en cas de recouvrement ('BB' dans 'ABBBC'). On recherche de façon similaire les occurences d'un mot à l'aide de Wordpos(), la dernière position étant juste incrémentée de l'unité.
Calqué sur le premier tri du paragraphe 5.1.2 ; l'inversion des éléments oblige ici à reconstituer la liste de mots au lieu d'échanger simplement le contenu des variables :
(à la première itération Subword(liste,1,i-1) retourne une chaîne vide puisque i-1 = 0).
Le programme du paragraphe 6.2 donne un exemple de vérification de date entrée au clavier.
La saisie de l'heure est contrôlée suivant le même principe, mais en beaucoup plus simple !
Les conversions d'une durée hh:mm:ss en secondes ou l'inverse ne posent pas de difficulté.
Une simple comparaison entre dates ou heures ne demande aucun calcul (comparaison de chaînes de caractères) :
Say '12:08:23' < Time() Say '20030212' < Date('S') /* comparaison de dates triées */
L'absence d'interface graphique n'interdit pas de développer des écrans en mode texte, ayant une bonne ergonomie. Le plus simple est le menu : liste d'options et choix de l'utilisateur en entrant un numéro, plus compliqué l'affichage de données avec défilement (voir le programme du § 6.2.1).
Les fonctions spécifiques améliorent la présentation :
- Charout() utilisée à la place de Say évite un retour à la ligne ;
- SysGetKey() (ou son équivalent si disponible, fonction extérieure) à la place de Pull
saisit un caractère sans validation par la touche Entrée ;
- SysCurPos() ( fonction extérieure) pour déplacer le curseur...
Linux reconnait les contrôles ANSI (séquences 'escape [...'), par exemple pour définir les couleurs (suivi d'un effacement écran celles-ci seront appliquées à toute la fenêtre) :
COLOR: Procedure Arg fore back /* de 0, noir à 7, blanc */ If back = '' Then back = 7 Call Charout , '1B5B'x||'0;3'fore';4'back'm' Return
Windows NT ne reconnait pas les séquences ANSI. Elles fonctionnent sous DOS natif, à condition de charger le pilote ANSI.SYS.
Certaines bibliothèques de fonctions externes comprennent l'affichage de boîtes de dialogues simples (oui / non, ...), mais la gestion complète de fenêtres reste à écrire !
On utilise les gestionnaires d'écran disponibles, dont ISPF, pour créer des applications interactives comprenant des menus et l'affichage de données.
© G. Navarre, 2003 - 2006, màj 9/04/2021.