Pourquoi ne puis-je pas lire les lignes de stdin, supprimer les espaces et les insérer dans un vecteur? `line` ne vit pas assez longtemps [dupliquer]

Aug 17 2020

Je voudrais lire les lignes de stdin, supprimer les espaces et les pousser dans un vecteur mais je ne peux pas car linene vit pas assez longtemps. Pourquoi?

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut read = Vec::new();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let line = line.trim();
        read.push(line);
    }
}
error[E0597]: `line` does not live long enough
  --> src/main.rs:8:20
   |
8  |         let line = line.trim();
   |                    ^^^^ borrowed value does not live long enough
9  |         read.push(line);
   |         ---- borrow later used here
10 |     }
   |     - `line` dropped here while still borrowed

Réponses

2 rodrigo Aug 17 2020 at 15:39

Si vous regardez la définition de str::trim()(annotations à vie ajoutées):

pub fn trim<'a>(&'a self) -> &'a str

Vous pouvez voir qu'il renvoie une tranche de chaîne qui fait référence à une partie de la chaîne d'origine. Autrement dit, il emprunte la chaîne au lieu de la copier. Ce qui a du sens, car le résultat de trimest toujours une sous-chaîne de l'original.

Vous pouvez être dérouté par d'autres fonctions, telles str::to_uppercase()que,, qui renvoient un nouveau String. C'est évidemment parce qu'ils ne renvoient pas une sous-chaîne de la chaîne d'origine, ils doivent donc en créer une nouvelle.

TL, DR; Vous avez un emprunté &strmais vous souhaitez qu'un propriétaire Stringstocke dans votre Vec. Ajoutez simplement .to_string().

A propos des inconvénients, il allouera un nouveau String. Vous pouvez essayer de l'éviter en faisant un trimsur place , mais je ne pense pas que cela en vaille la peine, à moins que vous ne profiliez et que vous décidiez que votre coupe nuit à votre performance.