32

Existing answers I've found are all based on from_str (such as Reading in user input from console once efficiently), but apparently from_str(x) has changed into x.parse() in Rust 1.0. As a newbie, it's not obvious how the original solution should be adapted taking this change into account.

As of Rust 1.0, what is the easiest way to get an integer input from the user?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Sundar R
  • 13,776
  • 6
  • 49
  • 76

8 Answers8

66

Here is a version with all optional type annotations and error handling which may be useful for beginners like me:

use std::io;

fn main() {
    let mut input_text = String::new();
    io::stdin()
        .read_line(&mut input_text)
        .expect("failed to read from stdin");

    let trimmed = input_text.trim();
    match trimmed.parse::<u32>() {
        Ok(i) => println!("your integer input: {}", i),
        Err(..) => println!("this was not an integer: {}", trimmed),
    };
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Michael
  • 4,722
  • 6
  • 37
  • 58
  • what about the use of unwrap()? how do you handle parse errors, and reporting them to stderr? – zero_cool Mar 30 '18 at 23:25
  • @zero_cool the errors are reported by handling `Result` produced by `parse()` with a `match`. `unwrap()` would cause the program to panic. – raindev Jan 07 '20 at 07:21
  • This "reads a line and parses the entire line as an integer" rather than "reads a next single integer", which is far from `cin >> i` in C++. – ynn Mar 28 '23 at 05:39
23

If you are looking for a way to read input for the purpose of competitive programming on websites like codeforces where you do not have access to text_io, this solution is for you.

I use the following macro to read different values from stdin:


#[allow(unused_macros)]
macro_rules! read {
    ($out:ident as $type:ty) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).expect("A String");
        let $out = inner.trim().parse::<$type>().expect("Parsable");
    };
}

#[allow(unused_macros)]
macro_rules! read_str {
    ($out:ident) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).expect("A String");
        let $out = inner.trim();
    };
}

#[allow(unused_macros)]
macro_rules! read_vec {
    ($out:ident as $type:ty) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).unwrap();
        let $out = inner
            .trim()
            .split_whitespace()
            .map(|s| s.parse::<$type>().unwrap())
            .collect::<Vec<$type>>();
    };
}
  

Use it as follows:


fn main(){
   read!(x as u32);
   read!(y as f64);
   read!(z as char);
   println!("{} {} {}", x, y, z);

   read_vec!(v as u32); // Reads space separated integers and stops when newline is encountered.
   println!("{:?}", v);
}

ouflak
  • 2,458
  • 10
  • 44
  • 49
coder3101
  • 3,920
  • 3
  • 24
  • 28
14

Probably the easiest part would be to use the text_io crate and write:

#[macro_use]
extern crate text_io;

fn main() {
    // read until a whitespace and try to convert what was read into an i32
    let i: i32 = read!();
    println!("Read in: {}", i);
}

If you need to read more than one value simultaneously, you might need to use Rust nightly.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Daniel Fath
  • 16,453
  • 7
  • 47
  • 82
  • I think it does run on stable if you only need to read one value at a time. – Vladimir Matveev May 20 '15 at 17:42
  • 1
    `text_io` dev here. @VladimirMatveev is right, `text_io` runs on stable if you don't read tuples but just a single value per `read!()` invocation. It actually requires nightly for multiple values. I'll update the github description. – oli_obk May 20 '15 at 18:50
  • Is there a better option now? After 3 years of Rust being out, I would assume there would be better ways of inputting values into integer variables. The solution suggested is what I encountered in the rust book, but its lengthy and feels a bit overkill for input. The `text_io` suggestion is great, but I'm not able to print statements out from functions before using `read!()` – JosephTLyons Mar 20 '18 at 09:01
  • @joe_04_04 What do you mean by "print statements out from functions before using `read!()` ? – Daniel Fath Mar 20 '18 at 12:05
  • @DanielFath, if I use `println!()` before trying to use `read!()` from `text_io`, items that are supposed to print from `println!()` do not get printed until after the `read!()` method. – JosephTLyons Mar 21 '18 at 05:15
14

Here are a few possibilities (Rust 1.7):

use std::io;

fn main() {
    let mut n = String::new();
    io::stdin()
        .read_line(&mut n)
        .expect("failed to read input.");
    let n: i32 = n.trim().parse().expect("invalid input");
    println!("{:?}", n);

    let mut n = String::new();
    io::stdin()
        .read_line(&mut n)
        .expect("failed to read input.");
    let n = n.trim().parse::<i32>().expect("invalid input");
    println!("{:?}", n);

    let mut n = String::new();
    io::stdin()
        .read_line(&mut n)
        .expect("failed to read input.");
    if let Ok(n) = n.trim().parse::<i32>() {
        println!("{:?}", n);
    }
}

These spare you the ceremony of pattern matching without depending on extra libraries.

qed
  • 22,298
  • 21
  • 125
  • 196
  • 4
    Come on, it's clearly different, and a complete answer makes it easier for the reader. – qed Apr 12 '16 at 14:21
  • It looks pretty identical to [the accepted answer](http://stackoverflow.com/a/30355925/155423) to me. – Shepmaster Apr 12 '16 at 14:22
  • Yeah, you have to get a string from the user and store that in a variable, that part is the same. The parsing part is more concise, as explained in my answer. – qed Apr 12 '16 at 14:44
  • *The parsing part is more concise* — a comment along the lines of "use [`Option::expect`](http://doc.rust-lang.org/std/option/enum.Option.html#method.expect) instead of `match` to be more concise and fail in cases of error" would be equivalent. *a complete answer makes it easier for the reader* — this answer is missing the required `use std::io` and `fn main` that the accepted answer has and a true beginner would want. – Shepmaster Apr 12 '16 at 14:51
  • Yeah, fair enough. – qed Apr 12 '16 at 15:00
  • 2
    To be clear, feel free to leave the answer, other people may find it useful and upvote it. So long as there's prose to describe why it's different and better, it's a valid answer! – Shepmaster Apr 12 '16 at 15:02
  • @Shepmaster its not the same for a beginner – Hamza Zubair May 06 '22 at 10:58
4

parse is more or less the same; it’s read_line that’s unpleasant now.

use std::io;

fn main() {
    let mut s = String::new();
    io::stdin().read_line(&mut s).unwrap();

    match s.trim_right().parse::<i32>() {
        Ok(i) => println!("{} + 5 = {}", i, i + 5),
        Err(_) => println!("Invalid number."),
    }
}
Ry-
  • 218,210
  • 55
  • 464
  • 476
3

You can create an extension method if you want a simple syntax:

use std::error::Error;
use std::io;
use std::str::FromStr;

trait Input {
    fn my_read<T>(&mut self) -> io::Result<T>
    where
        T: FromStr,
        T::Err: Error + Send + Sync + 'static;
}

impl<R> Input for R where R: io::Read {
    fn my_read<T>(&mut self) -> io::Result<T>
    where
        T: FromStr,
        T::Err: Error + Send + Sync + 'static,
    {
        let mut buff = String::new();
        self.read_to_string(&mut buff)?;

        buff.trim()
            .parse()
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
    }
}

// Usage:

fn main() -> io::Result<()> {
    let input: i32 = io::stdin().my_read()?;

    println!("{}", input);

    Ok(())
}
Boiethios
  • 38,438
  • 19
  • 134
  • 183
2

I would definitely use the file system Rust-Lang provides std::fs (See more here: https://doc.rust-lang.org/stable/std/fs/) But more particularly https://doc.rust-lang.org/stable/std/fs/fn.read_to_string.html

Let's say you just want to read input of a text file, try this :

use std::fs
or
use std::fs::read_to_string

fn main() {
    println!("{}", fs::read_to_string("input.txt"));   
}
2

you can try this piece of code

fn main() {

    let mut line  = String::new();

    // read input line string and store it into line
    std::io::stdin().read_line(&mut line).unwrap();

    // convert line to integer
    let number : i32 = line.trim().parse().unwrap();

    println!("Your number {}",number);
}

now you can write a function for taking user input and use it everytime like below

fn main() {

    let first_number = get_input();
    let second_number = get_input();

    println!("Summation : {}",first_number+second_number);

}

fn get_input() -> i32{

    let mut line  = String::new();
    std::io::stdin().read_line(&mut line).unwrap();
    let number : i32 = line.trim().parse().unwrap();
    return number ;
}
Ruman
  • 936
  • 11
  • 9