Chercher dans un texte
Nettoyer, interroger, situer — et la convention du −1, qui n'est pas le zéro des absences.
Une ligne lue quelque part ne se présente jamais comme on l’espérait : des espaces au bord, une
information qu’il faut situer avant de la prendre. Quatre méthodes suffisent à la mettre en
forme, et elles viennent du même StrText que la 9.1 a importé.
import { StrText } from "std/extensions/str-text.arc";
extend archetype str StrText;
@entry(demarrer)
object MonProgramme {
demarrer() {
var ligne := " mandragore : 3 doses ";
var propre := ligne.trimmed();
var connu := propre.startsWith(prefix: "mandragore");
var rang := propre.indexOf(needle: ":", since: 0);
Console.print(text: $"nettoyée : « {propre} »");
Console.print(text: $"commence par « mandragore » : {connu}");
Console.print(text: $"contient « dose » : {propre.contains(needle: "dose")}");
Console.print(text: $"les deux points sont au rang {rang}");
Console.print(text: $"l'ingrédient : {propre.substring(start: 0, end: rang).trimmed()}");
Console.print(text: $"« belladone » : {propre.indexOf(needle: "belladone", since: 0)}");
}
}
trimmed rend une copie, il ne modifie rien
var propre := ligne.trimmed();
ligne n’a pas bougé : elle vaut toujours " mandragore : 3 doses ", espaces compris.
trimmed rend un texte, il n’en corrige pas un. C’est vrai de toutes les méthodes de cette
section, et c’est vrai de str en général : un texte, une fois écrit, ne se retouche pas — on en
fabrique un autre. D’où l’affectation : sans elle, le travail est fait puis jeté.
Répondre par oui ou par non
propre.startsWith(prefix: "mandragore")
propre.contains(needle: "dose")
Deux bool, qui se posent tels quels dans un if ou se combinent avec le and et le or de la
3.3. endsWith existe aussi, symétrique de startsWith.
Situer, et la convention du −1
propre.indexOf(needle: ":", since: 0)
indexOf rend le rang de la première occurrence à partir de since — ici 11, et l’on peut
chercher la suivante en repartant de 12. Quand l’aiguille n’est nulle part, la réponse est
-1.
Pourquoi -1, alors que le cours a présenté le zéro comme la marque de l’absence en 5.2 ?
Parce qu’ici zéro est déjà pris : c’est le rang du tout premier caractère, une réponse
parfaitement valable. Une absence ne peut pas se marquer par une valeur qui veut dire déjà autre
chose, et -1 — un rang qui n’existe pas — est libre. Retenez donc la forme :
if (propre.indexOf(needle: "belladone", since: 0) >= 0) {
et non une comparaison à zéro, qui manquerait le premier caractère.
C’est d’ailleurs tout ce que contains est : indexOf(…) >= 0, écrit une fois pour n’avoir plus
à y penser.
Situer, puis couper
Les deux dernières lignes du programme font ensemble ce à quoi tout cela sert :
propre.substring(start: 0, end: rang).trimmed()
indexOf a donné le rang des deux points, substring prend ce qui précède, trimmed retire
l’espace resté au bord — et il reste mandragore. Les méthodes s’enchaînent parce que chacune
rend un texte, et qu’un texte sait faire tout ce que StrText lui a appris.
À vous
- Affichez
ligne.lengthpuispropre.length: la première n’a rien perdu. - Cherchez
":"à partir de12plutôt que de0: il n’y a pas de second deux-points, donc-1. - Remplacez
>= 0par> 0dans leifci-dessus, et cherchez"mandragore": la condition est fausse alors que le mot est bien là, au rang zéro. C’est exactement le piège que la convention du-1demande d’éviter. - Prenez ce qui suit les deux points —
substring(start: rang + 1, end: propre.length)— et nettoyez-le. Ce morceau-là,3 doses, est le sujet de la sous-section suivante.