Bonjour à tous !
L’article d’aujourd’hui va traiter de la manipulation des chaînes de caractères en ABAP.
Lorsque j’ai débuté l’ABAP, j’ai été un peu choqué de la façon de traiter une chaîne de caractères qui me paraissait pour le moins archaïque, il faut aujourd’hui dire que les choses ont évolué et, selon moi, dans le bon sens.
Il y a désormais moult façons de gérer les chaînes de caractères. Peut-être même un peu trop, mais cela est dû à la nécessité de conserver une compatibilité descendante avec les précédentes versions du langage. Il serait en effet difficile de dire à tous les clients de recoder leurs programmes à chaque évolution du langage (même si une fois de temps en temps, ça ne ferait pas de mal…) !
La première chose à faire est de déclarer une chaîne de caractères ; je préconise le type string mais il faut bien distinguer deux types. La chaîne de caractères de type C avec une longueur bien définie, et la chaîne de caractères de type STRING dont la longueur est dynamique et varie selon le contenu de la variable.
Ensuite, on peut la valoriser notre chaîne, et c’est là que les choses deviennent sérieuses, car il y a plusieurs façons de faire :
v_string = c_label.
v_string = 'baz'.
v_string = `qux`.
v_string = |quux|.
La première façon correspond à l’affectation à partir du contenu d’une constante. Les suivantes permettent d’affecter une valeur « en dur » (ou hard codée) à notre variable. À première vue, les trois lignes ont le même effet. Mais ce n’est pas tout à fait le cas…
Simple quote – ou Text Field Literal
Il s’agit de la base historique. Une chaîne de caractère est bornée par le caractère « '
» (simple quote). Pour échapper cette simple quote au sein du texte, il faut la doubler.
Exemple : v_string = 'C''est simple non ?'.
Ce n’est pas très beau, et c’est assez limité.
Pour concaténer deux chaînes (ou plus), il faut utiliser l’instruction CONCATENATE. L’exemple ci-dessous déclare une constante et une variable. Il valorise cette variable avec une valeur en dur via simple quote, puis concatène avec la constante avant d’afficher le résultat.
constants c_value type string value 'bar'.
data v_string type string.
v_string = 'Foo'.
concatenate v_string c_value into v_string separated by space.
write v_string.
Le résultat sera « Foo bar ».
L’instruction CONCATENATE a l’intérêt de permettre de choisir le (ou les) caractère(s) de séparation de la concaténation. Si on l’avait omis dans l’exemple précédent, le résultat aurait été « Foobar ».
Mais voici un comportement surprenant du système : si on met separated by ''
(donc une chaîne vide), le résultat est le même qu’avec separated by space
ou separated by ' '
.
La raison est que la simple quote crée une zone de type C et de longueur égale à la chaîne entre les quotes, mais qu’il ne peut exister de zone vide. La zone » est donc identique à la zone ‘ ‘, c’est à dire une chaîne de caractères de longueur 1.
En outre, la taille maximale est limitée à 255 caractères.
Enfin, je recommande l’utilisation de l’opérateur « & » pour concaténer de façon plus fluide qu’avec l’instruction CONCATENATE. Cet opérateur conserve les éventuelles espaces autour des chaînes à concaténer, à l’exception de la fin de la chaîne résultante.
Exemple :
v_string = ' test ' & ' truc '.
write / v_string.
Affichera "
test truc"
.
Quote inversée – ou Text String Literal
La principale différence avec le précédent cas est que le résultat est de type string plutôt que de type chaîne de caractères d’une longueur donnée. Dit comme ça ça paraît équivalent, mais pas tout à fait.
La différence notable : la chaîne vide.
Nous avons vu que ''
était équivalent à ' '
, mais ``
sera différent de ` `
. En effet, une zone de type string peut être vide.
Les autres caractéristiques sont identiques : limitation à 255 caractères, échappement en doublant le caractère et utilisation de l’opérateur « & ».
Une légère différence sur l’opérateur « & ». Contrairement aux text field literals, ici les éventuelles espaces de fin sont conservées.
Exemple :
v_string = ` test ` & ` truc `.
write / v_string.
Affichera "
test truc "
.
Barre verticale – ou String Template
Ici c’est un peu plus complexe. Un modèle de chaînes (pour traduire à ma façon) est borné par deux barres verticales « | » et ne peut être utilisé que dans une expression de chaînes (string expression) d’un programme unicode. Le modèle crée une zone de type string qui sera utilisée dans l’expression en remplacement du dit modèle.
Autrement dit, entre les barres on peut définir toute opération qui aurait pour résultat une chaîne et elle sera considérée comme telle lors de l’exécution.
Pour échapper la barre verticale, il faut la faire précéder de l’antislash « \ ».
La concaténation avec « & » est également possible, mais elle fonctionnera comme l’opérateur « && » : c’est-à-dire contrôlé à l’exécution et non à la compilation et la limitation des 255 caractères saute.
Je recommande l’utilisation du String Template systématique, dans la mesure où c’est celle qui a le moins de limitations et est la plus puissante en terme de possibilités. Il devient possible d’ajouter des variables, des calculs, des appels de méthodes au sein du modèle de chaîne.
Ci-dessous un exemple de programme qui prend en entrée un nom et affiche la phrase « Hello nom » en mettant le nom saisi en majuscule :
parameters p_name type string default 'world' lower case.
data v_string type string.
v_string = | hello { to_upper( p_name ) }!|.
write / v_string.
Sur l’exemple on peut voir que les opérations à effectuer sont bornées par les accolades. À l’exécution, le système va d’abord exécuter la fonction prédéfinie to_upper avec l’argument p_name, puis va utiliser le résultat dans le modèle de chaîne, puis va générer la chaîne issue du modèle.
Ainsi, si l’utilisateur a saisi « world », le programme affichera « hello WORLD! »
Conclusion
Comme je le disais plus haut, je préfère désormais utiliser les modèles de chaîne. Ils sont très souples et permettent notamment de se passer de concaténation. En effet, au lieu de concaténer, il suffit d’ajouter la nouvelle zone dans le modèle. Un petit exemple :
v_string = | hello { to_upper( p_name ) }! The date is | && zcl_convert=>any_to_string( sy-datum ) && |.|.
v_string = | hello { to_upper( p_name ) }! The date is { zcl_convert=>any_to_string( sy-datum ) }.|.
Ces deux lignes auront le même résultat : « hello WORLD! The date is 20131031. » Mais la seconde est, à mes yeux, plus propre.
Avec cette récente notion de modèle de chaîne, l’ABAP prend un tournant dans la gestion des chaînes de caractères, en se rapprochant un peu plus des langages de programmation plus modernes, et ce ne peut qu’être une bonne chose.
P.-S. : il existe désormais de nombreuses fonctions prédéfinies qui permettent de manipuler les chaînes de caractères, à l’instar de celle que j’ai utilisée dans mes exemples, to_upper( ) qui convertit une chaîne en majuscules. Je ne ferai pas de liste de ces fonctions car leur utilisation reste anecdotique à mon sens et il ne s’agirait que de copier purement et simplement la documentation officielle.