Возьмите числа из файла и поместите в Ve c но продолжаю получать ошибку - PullRequest
1 голос
/ 13 января 2020

Код:

use std::io::Read;

fn main() {
  let mut file = std::fs::File::open("numbs").unwrap();
  let mut contents = String::new();
  file.read_to_string(&mut contents).unwrap();
  let mut v: Vec<i32> = Vec::new();
  for s in contents.lines() {
      v.push(s.parse::<i32>().unwrap());
  }
}

Ошибка:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: Empty }', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

1 Ответ

1 голос
/ 13 января 2020

Скорее всего, у вас есть завершающий символ новой строки \n в конце вашего файла, т.е. пустая последняя строка. Вы также можете иметь пустые строки в середине вашего файла.

Самый простой способ исправить это для вашего варианта использования - просто игнорировать пустые строки:

for s in contents.lines() {
    if !s.is_empty() {
        v.push(s.parse::<i32>().unwrap());
    }
}

Однако, как правило, не стоит просто unwrap a Result, особенно если вы не можете гарантировать, что он никогда не будет панически c. Более надежное решение - правильно обрабатывать каждый возможный результат Result. Другое преимущество этого решения заключается в том, что оно будет игнорировать не только пустые строки, но и строки, которые не могут быть проанализированы как i32. Независимо от того, хотите ли вы этого, или если вы sh явно решите эту ошибку, решать только вам. В следующем примере мы будем использовать if-let для вставки значений в вектор, только если они были успешно проанализированы как i32:

for s in contents.lines() {
    if let Ok(i) = s.parse::<i32>() {
        v.push(i);
    }
}

. Примечание. Вам не нужно прочитать весь файл в строку, а затем проанализировать эту строку за строкой. Обратитесь к Читайте большие файлы построчно в Rust , чтобы увидеть, как достичь этого более идиоматически

Комбинируя вышеупомянутую точку и использование flatten и flat_map, мы можем значительно упростить лог c до:

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let file = File::open("numbs").unwrap();
    let v: Vec<i32> = BufReader::new(file)
                          .lines()
                          .flatten()                             // gets rid of Err from lines
                          .flat_map(|line| line.parse::<i32>())  // ignores Err variant from Result of str.parse
                          .collect();
}
...