如何在知道需要多大之前分配一个字符串

How to allocate a string before you know how big it needs to be

我敢肯定这是初学者的错误。我的代码是:

...
let mut latest_date : Option<Date<Local>> = None;
let mut latest_datetime : Option<DateTime<Local>> = None;
let mut latest_activity : Option<&str> = None;

for wrapped_line in reader.lines() {
    let line = wrapped_line.unwrap();
    println!("line: {}", line);

    if date_re.is_match(&line) {
        let captures = date_re.captures(&line).unwrap();
        let year = captures.at(1).unwrap().parse::<i32>().unwrap();
        let month = captures.at(2).unwrap().parse::<u32>().unwrap();
        let day = captures.at(3).unwrap().parse::<u32>().unwrap();
        latest_date = Some(Local.ymd(year, month, day));
        println!("date: {}", latest_date.unwrap());
    }

    if time_activity_re.is_match(&line) && latest_date != None {
        let captures = time_activity_re.captures(&line).unwrap();
        let hour = captures.at(1).unwrap().parse::<u32>().unwrap();
        let minute = captures.at(2).unwrap().parse::<u32>().unwrap();
        let activity = captures.at(3).unwrap();

        latest_datetime = Some(latest_date.unwrap().and_hms(hour, minute, 0));

        latest_activity = if activity.len() > 0 {
            Some(activity)
        } else {
            None
        };

        println!("time activity: {} |{}|", latest_datetime.unwrap(), activity);
    }
}
...

我的错误是:

   Compiling tt v0.1.0 (file:///home/chris/cloud/tt)
src/main.rs:69:55: 69:59 error: `line` does not live long enough
src/main.rs:69             let captures = time_activity_re.captures(&line).unwrap();
                                                                     ^~~~
src/main.rs:55:5: 84:6 note: in this expansion of for loop expansion
src/main.rs:53:51: 86:2 note: reference must be valid for the block suffix following statement 7 at 53:50...
src/main.rs:53     let mut latest_activity : Option<&str> = None;
src/main.rs:54 
src/main.rs:55     for wrapped_line in reader.lines() {
src/main.rs:56         let line = wrapped_line.unwrap();
src/main.rs:57         println!("line: {}", line);
src/main.rs:58 
               ...
src/main.rs:56:42: 84:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 56:41
src/main.rs:56         let line = wrapped_line.unwrap();
src/main.rs:57         println!("line: {}", line);
src/main.rs:58 
src/main.rs:59         if date_re.is_match(&line) {
src/main.rs:60             let captures = date_re.captures(&line).unwrap();
src/main.rs:61             let year = captures.at(1).unwrap().parse::<i32>().unwrap();
               ...
error: aborting due to previous error
Could not compile `tt`.

我认为问题在于 latest_activity : Option<&str>latest_activity 被重新分配的循环迭代中比 line 寿命更长。

正确吗?

如果是这样,修复它的最佳方法是什么。分配新字符串的成本并不困扰我,尽管我不希望每次迭代都这样做。

我觉得我可能需要一个引用计数框来放入 activity - 这是正确的方法吗?

我可以在循环外分配一个 String - 但在我知道它需要多大之前我该怎么做?

问题是您已经为每次迭代分配一个新字符串(Lines迭代器无处存储缓冲区,因此它必须分配每行一个新的 String),但您试图在循环外将一个切片存储到其中。

你也无法真正知道在这种情况下外部分配的 String 需要多大...所以通常你不会担心它,只是根据需要调整大小。

最简单 的方法可能是将 latest_activity 变成 Option<String>。当你想改变它时,你可以使用.clear()然后是.push_str(s)(见String documentation)。如果它足够大,这应该重新使用现有分配,如果不是,则调整大小。它可能需要一些重新分配,但没什么大不了的(前提是你不这样做,例如,尝试存储越来越长的字符串)。

另一种可能性是只存储 wrapped_line 本身,将其移出循环。您可以将其与切片索引一起存储,然后在循环外进行 actual 切片(不,您不能只存储 String&str单独切片 以及标准库类型)。