How to do simple math with a list of numbers from a file and print out the result in Rust?
Asked Answered
R

2

-1
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
Russ answered 9/12, 2019 at 6:40 Comment(9)
Are you getting any Errors/Exceptions?Joule
Your code is fine. If this is about getting some advice for writing an idiomatic code, you can post on codereview.stackexchange.comPrentiss
play.rust-lang.org/… @FrenchBoiethios the code is not "fine" by the wayAmelita
@Amelita The OP didn't say anything about any requirement, so that's hard to answer anywayPrentiss
@FrenchBoiethios, the file is local so it wouldn't show up on an online ide.Russ
im not getting any error just Finished dev [unoptimized + debuginfo] target(s) in 0.00s Running /home/whilhelm/PycharmProjects/untitled4/target/debug/untitled4 main inputRuss
Did you try cargo run?Joule
Yeah cargo run main.rs @AbdulNiyasPMRuss
you don't get anything because Result implement intoiterator and so your for loop do not cycle over your numbers but over one result from all your string and obviously "50951\n69212..." is not a valid number.Amelita
R
3

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.

Redstone answered 9/12, 2019 at 8:18 Comment(0)
D
0

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:

Dar answered 11/12, 2019 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.