【问题标题】:How to allocate a string before you know how big it needs to be如何在知道它需要多大之前分配一个字符串
【发布时间】:2015-11-18 13:41:46
【问题描述】:

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

...
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&lt;&amp;str&gt; 在循环迭代中的寿命比 line 长,其中 latest_activity 被重新分配。

对吗?

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

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

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

【问题讨论】:

    标签: string rust lifetime


    【解决方案1】:

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

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

    最简单的方法可能是把latest_activity变成Option&lt;String&gt;。当您想更改它时,您可以使用.clear() 后跟.push_str(s)(参见String documentation)。如果它足够大,这应该重新使用现有分配,如果不是,则调整大小。它可能需要重新分配,但没什么大不了的(例如,如果您不尝试存储越来越长的字符串)。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-13
      • 2020-08-14
      • 2015-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多