2015-11-18 1 views
-1

Я уверен, что это ошибка начинающих. Мой код:Как выделить строку, прежде чем вы узнаете, насколько она должна быть

... 
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> живет дольше, чем line внутри итерации цикла, где latest_activity переназначен.

Правильно?

Если да, то как лучше всего это исправить. Стоимость выделения новой строки не беспокоит меня, хотя я бы предпочел не делать этого для каждой итерации.

Я чувствую, что мне может понадобиться поле с подсчетом, чтобы положить activity в - это правильный подход?

Я мог бы выделить String вне цикла - но как я могу это сделать, прежде чем я знаю, насколько это будет необходимо?

ответ

1

Проблема заключается в том, что вы уже выделении новой строки для каждой итерации (нет нигде для Lines итератора для хранения буфера, поэтому он должен выделить свежий String для каждой строки), но вы пытаетесь для хранения фрагмента в нем вне цикла.

Вы также не можете знать, насколько большой внешний String должен быть в этом случае ... так что вы не будете беспокоиться об этом и просто изменять размер по мере необходимости.

Простой способ, вероятно, сделать latest_activity a Option<String>. Если вы хотите изменить это, вы можете использовать .clear(), а затем .push_str(s) (см. String documentation). Это должно повторить использование существующего распределения, если оно достаточно большое, изменение размера, если оно отсутствует. Это может потребовать некоторого перераспределения, но ничего существенного (если вы, например, не пытаетесь хранить все более длинные и длинные строки).

Другая возможность - просто сохранить wrapped_line сам, вытащив его из петли. Вы можете сохранить это вместе с индексами среза, а затем сделать актуальным срезанием вне цикла (нет, вы не можете просто сохранить String и &str срез отдельно или вместе с только стандартными типами библиотек).

Смежные вопросы