How to do simple math with a list of numbers from

2020-05-09 21:45发布

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::iter::Iterator;

fn main() -> std::io::Result<()> {
    let file = File::open("input")?; // file is input
    let mut buf_reader = BufReader::new(file);

    let mut contents = String::new();
    buf_reader.read_to_string(&mut contents)?;

    for i in contents.parse::<i32>() {
        let i = i / 2;
        println!("{}", i);
    }

    Ok(())
}

list of numbers:

50951
69212
119076
124303
95335
65069
109778
113786
124821
103423
128775
111918
138158
141455
92800
50908
107279
77352
129442
60097
84670
143682
104335
105729
87948
59542
81481
147508

2条回答
叼着烟拽天下
2楼-- · 2020-05-09 22:28

For tiny examples like this, I'd read the entire string at once, then split it up on lines.

use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let contents = fs::read_to_string("input")?;
    for line in contents.trim().lines() {
        let i: i32 = line.trim().parse()?;
        let i = i / 2;
        println!("{}", i);
    }

    Ok(())
}

See also:


For tightly-controlled examples like this, I'd ignore errors occurring while parsing:

use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let contents = fs::read_to_string("input")?;
    for i in contents.trim().lines().flat_map(|l| l.trim().parse::<i32>()) {
        let i = i / 2;
        println!("{}", i);
    }

    Ok(())
}

See also:


For fixed-input examples like this, I'd avoid opening the file at runtime at all, pushing the error to compile-time:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let contents = include_str!("../input");
    for i in contents.trim().lines().flat_map(|l| l.trim().parse::<i32>()) {
        let i = i / 2;
        println!("{}", i);
    }

    Ok(())
}

See also:


If I wanted to handle failures to parse but treat the iterator as if errors were impossible, I'd use Itertools::process_results:

use itertools; // 0.8.2

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let contents = include_str!("../input");

    let numbers = contents.trim().lines().map(|l| l.trim().parse::<i32>());
    let sum = itertools::process_results(numbers, |i| i.sum::<i32>());

    println!("{:?}", sum);

    Ok(())
}

See also:

查看更多
时光不老,我们不散
3楼-- · 2020-05-09 22:34

str::parse::<i32> can only parse a single number at a time, so you will need to split the text first and then parse each number one by one. For example if you have one number per line and no extra whitespace, you can use BufRead::lines to process the text line by line:

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

fn main() -> std::io::Result<()> {
    let file = File::open("input")?; // file is input
    let mut buf_reader = BufReader::new(file);

    for line in buf_reader.lines() {
        let value = line?
            .parse::<i32>()
            .expect("Not able to parse: Content is malformed !");

        println!("{}", value / 2);
    }

    Ok(())
}

As an extra bonus this avoids reading the whole file into memory, which can be important if the file is big.

查看更多
登录 后发表回答