Manipuler des chaînes et des tranches

RustBeginner
Pratiquer maintenant

Introduction

Rust utilise String pour représenter du texte possédé et extensible, et &str pour représenter une vue empruntée sur du texte. Une tranche de chaîne peut correspondre à une chaîne entière ou à une plage d’octets sélectionnée, sans copier ses caractères.

Vous allez transmettre un texte possédé à une fonction qui emprunte un &str, créer un mot-clé de commande emprunté, puis demander volontairement au compilateur d’indexer du texte UTF-8 d’une manière non prise en charge, avant de corriger le code avec une tranche respectant les limites valides.

Emprunter du texte possédé et littéral comme &str

Dans cette étape, vous allez transmettre deux sources de texte différentes à une même fonction qui accepte une tranche de chaîne empruntée.

Accédez au projet préparé et ouvrez son code source :

cd /home/labex/project/string-slices
nano src/main.rs

Le type String possède un texte extensible. Le type &str, prononcé « tranche de chaîne », est une vue empruntée sur du texte UTF-8 valide. Un littéral de chaîne tel que "preview" possède déjà un type de tranche de chaîne empruntée, car le programme conserve son texte pendant toute son exécution.

La fonction show_text(label: &str) peut consulter l’un ou l’autre de ces types de texte. Remplacez uniquement /* Step 1: borrow command */ par &command :

    show_text(&command);

Rust convertit automatiquement le &String emprunté en vue &str attendue par la fonction. Cette conversion ne copie pas et ne déplace pas les caractères.

Enregistrez avec Ctrl+O, appuyez sur Entrée, puis quittez avec Ctrl+X. Exécutez le programme :

cargo run --quiet

La sortie doit être :

Text: serve reports
Text: preview
Keyword: <>
Status: ✅ ready

Les deux appels utilisent le même paramètre &str. Le mot-clé vide est un espace réservé préparé pour l’étape suivante.

Emprunter une sous-chaîne sans la copier

Dans cette étape, vous allez faire en sorte que keyword désigne uniquement le préfixe serve contenu dans command.

Ouvrez le code source :

nano src/main.rs

La syntaxe de tranche &text[start..end] emprunte une plage. Le début est inclus et la fin est exclue. Les plages de chaînes Rust comptent les octets. Chaque lettre ASCII de serve occupe donc un octet ; la plage commence à l’octet 0 et se termine juste avant l’octet 5.

Remplacez uniquement le littéral vide "" sur la ligne de l’étape 2 par &command[0..5] :

    let keyword = &command[0..5]; // Step 2: replace the empty slice.

Le &str obtenu pointe à l’intérieur de command : il n’alloue pas une seconde chaîne et ne la copie pas. Comme command reste dans la portée, la vue empruntée reste valide tant que keyword est utilisé.

Enregistrez et quittez, puis exécutez :

cargo run --quiet

La dernière ligne doit maintenant être :

Keyword: <serve>

La valeur command contient toujours le texte complet serve reports, tandis que keyword n’est qu’une fenêtre empruntée sur ses cinq premiers octets.

Respecter les limites des caractères UTF-8

Dans cette étape, vous allez essayer volontairement l’indexation par entier, lire l’explication du compilateur, puis la remplacer par une tranche UTF-8 valide.

Les caractères UTF-8 n’occupent pas tous un seul octet. Dans "✅ ready", le symbole de coche utilise trois octets. Par conséquent, l’octet zéro ne correspond pas automatiquement au « premier caractère », et Rust n’autorise pas status[0] sur une valeur String.

Ouvrez le fichier et supprimez uniquement les // initiaux de la ligne d’affichage de l’étape 3 :

nano src/main.rs

Enregistrez et quittez, puis lancez la vérification. Un échec est attendu :

cargo check

Recherchez le message stable suivant :

error[E0277]: the type `str` cannot be indexed by `{integer}`

Ce diagnostic vous empêche de supposer que chaque caractère possède une position sur un seul octet. Ouvrez à nouveau le fichier et remplacez la ligne d’affichage qui provoque l’erreur par ces deux lignes courtes :

    let symbol = &status[0..3];
    println!("Status symbol: {symbol}");

La plage 0..3 se termine exactement après les trois octets du symbole. Cette opération fonctionne parce que le texte préparé et sa limite en octets sont connus à l’avance ; ce n’est pas une méthode générale pour trouver le premier caractère visible par un humain dans un texte arbitraire. Une plage qui coupe un caractère UTF-8 en son milieu provoquerait une panique à l’exécution. Les plages de chaînes doivent donc commencer et se terminer sur des limites UTF-8 valides.

Enregistrez et quittez, puis vérifiez et exécutez le programme :

cargo check
cargo run --quiet

La sortie complète doit être :

Text: serve reports
Text: preview
Keyword: <serve>
Status: ✅ ready
Status symbol: ✅

Cette sortie réussie prouve que la tranche finale sélectionne un caractère UTF-8 complet sans copier la String d’origine.

Résumé

Vous avez relié des valeurs String possédées à des vues &str empruntées, sélectionné une sous-chaîne sans allocation et compris pourquoi le texte UTF-8 ne peut pas être traité comme un tableau de caractères indexé par octets. Les plages de chaînes sûres doivent commencer et se terminer sur des limites UTF-8 valides.