lundi 21 mai 2018

Chapitre 29 : chaines de caractères


Dans cet article, nous allons voir plusieurs routines très utiles pour traiter les chaines de caractères (string). Une chaine de caractères est toujours stockée en mémoire et est accessible par son adresse de début contenu dans un pointeur ou un registre. Il existe plusieurs manières de  gérer une chaine soit par exemple comme le C en terminant celle çi par un zéro binaire soit en mettant dans le premier octet (ou le demi mot ou le mot) sa longueur.
Ici nous utiliserons la définition comme le C cad avec un zéro final. Nous avons vu qu’une chaine se définissait en mémoire par la directive .asciz (ou aussi .string)qui mettra le zéro binaire automatiquement à la fin de la chaine. Pour des suites de caractères sans 0 final, il faut utiliser la directive .ascii.
Ces routines peuvent être utiliser tel quel mais elles serviront surtout de base pour écrire des fonctions plus intégrables ou répondant à d’autres besoins spécifiques. Par exemple le calcul de la longueur peut être fait directement dans le code soit avoir à appeler la routine ( pour alléger le nombre d’instructions et réduire le temps d’exécution).
La première fonction permet de vérifier et de corriger une chaine de caractère si celle ci n’est pas correcte. Elle force un zéro binaire à la rencontre du premier caractère non alphanumérique au sens strict. En effet, sur mon système les programmes sont encodés avec l’option uft8 et donc les caractères accentués ne sont pas considérés comme des caractères ascii mais sont codées sur 2 caractères (ou plus pour des alphabets exotiques). Donc suivant les cas, il faudra adapter cette fonction pour gérer vos besoins. Elle peut être utile pour la lecture des lignes d’un fichier car chaque ligne ne se termine pas par un 0 binaire mais par les caractères 0x0D0A.
La deuxième fonction permet de calculer la longueur d’une chaine. Il s’agit d’une boucle simple qui compte le nombre de caractères jusqu’à trouver le zéro final.
Ensuite nous trouvons les fonctions de copie d’une chaine entière et de copie de n caractères d’une chaine
Puis 2 fonctions de concaténation de chaines,  la première oblige la fourniture par le code appelant de la zone de réception . La seconde utilise le tas (heap) Linux pour réserver la zone de réception et retourne son adresse au code appelant.
De même 2 fonctions de comparaison de chaine, la première qui tient compte de la casse (majucules-minuscules) et l’autre qui n’en tient pas compte.
Puis 2 fonctions de recherche, une pour chercher un seul caractère et l’autre pour chercher une sous-chaine à l’intérieur d’une chaine. Ces fonctions s’arrêtent au premier caractère ou sous chaine trouvé et sont donc à adapter pour rechercher d’autres occurrences.
Enfin une fonction d’insertion d’une sous chaine dans une autre puis une fonction de tri. Pour cela toutes les chaines qui ont servies dans les tests précédents sont identifiées par un pointeur stocké dans une table. Cette table permet l’affichage des chaines puis leur tri et enfin un affichage après le tri pour vérification. Dans notre exemple nous appelons la fonction de comparaisonsanscasse mais vous pouvez la remplacer par l’autre fonction de comparaison. Le tri utilisé est un tri shell dans lequel seuls les pointeurs des chaines sont déplacés. Ainsi les chaines quelle que soit leur longueur ne sont pas déplacées ce qui permet au tri d’être efficace. Attention, ce tri utilise une gestion des incréments simplifiée ce qui peut entrainer pour des grosses quantités de chaine une dégénérescence du tri (pour plus de détails, voir la théorie et les multiples analyses du tri shell).
Pour terminer, une fonction permet d’éclater une chaine en plusieurs sous chaines en fonction d’un séparateur. La fonction retourne l’adresse d’une table qui contient dans le premier poste, le nombre de zones extraites puis ensuite dans chaque poste l’adresse de la sous-chaine. Dans ce programme, nous découpons la chaine avec un séparateur espace. Nous affichons le résultat dans une boucle qui balaye la table fournie en retour de la fonction.
La table des zones est aussi stockée sur le tas grâce à l’appel system linux Brk.

Exercice :   écrire une fonction qui inverse une chaine
                   améliorer la recherche d'un caractère pour trouver le 2ième, 3iéme etc.
 

1 commentaire:

  1. Le fichier routchaines.s a été mis à jour le 6/10/2018 pour corriger 2 erreurs. Dans une des routines, le registre r3 n'était pas sauvegardé car j'utilisais l'instruction push {r2,r4] à la place de push {r2-r4}.
    La deuxième correction concerne la réservation de place sur le tas : en effet une chaine peut avoir une longueur quelconque et la réservation de sa place pouvait entrainer un non alignement des données suivantes sur le tas.

    RépondreSupprimer