15

Note The code in this question pertains to a version of Rust before 1.0 but the answers have been updated for Rust 1.0.

I have trouble converting a string to an integer.

fn main() {
    let input_text = io::stdin()
        .read_line()
        .ok()
        .expect("failed to read line");

    let input: Option<int> = from_str(input_text.as_slice());

    println!("{}", input);
}

I enter a number on the console (42 for example) and my program prints None.

The documentation says that that is a normal situation when the string is ill-formatted, but what's wrong with my 42?

5 Answers 5

19

You can call str::parse(), but you need to make sure that read_line is working. We need a reader:

use std::io;

fn main() {
    let reader = io::stdin();
}

stdin reads the global buffer that handles the input stream and also implements the BufRead trait which has the read_line method method. This takes a mutable String as an input buffer and reads all bytes from the stream until a newline byte is reached and appends them to the buffer. The #expect() method unwraps the Result; if it is an Err it will panic with the message and the cause.

use std::io;

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

We now have the input text that we want to convert into an i32. This is where str::parse() will work for us, as long as we give it a type to parse to. str::trim() is necessary because read_line includes the newline byte the buffer

use std::io;

fn main() {
    let reader = io::stdin();
    let mut input_text = String::new();
    reader.read_line(&mut input_text).expect("failed to read line");
    let input = input_text.trim().parse::<i32>();
}

We're not done yet, we still need to ensure that we successfully parsed the input using pattern matching. All the code you need to convert your original input buffer into a usable integer is:

use std::io;

fn main() {
    let reader = io::stdin();
    let mut input_text = String::new();

    reader.read_line(&mut input_text).expect("failed to read line");

    let input_opt = input_text.trim().parse::<i32>();

    let input_int = match input_opt {
        Ok(input_int) => input_int,
        Err(e) => {
            println!("please input a number ({})", e);
            return;
        }
    };

    println!("{}", input_int);
}

This compiles without errors or warnings.

Sign up to request clarification or add additional context in comments.

Comments

8

The input includes a newline at the end, as explained in the documentation for read_line. This causes from_str() to fail. Using std::str::trim() and changing this:

let input: Result<i32, _> = input_text.parse();

into this:

let input: Result<i32, _> = input_text.trim().parse();

seems to work.

Comments

4

As of Rust 1.14, The Rust Programming Language has this example:

let guess: u32 = guess.trim().parse()
    .expect("Please type a number!");

You can also just use the same variable name again and the new type will "shadow" the old type:

use std::io;

fn main() {
    let mut input_text = String::new();

    io::stdin()
        .read_line(&mut input_text)
        .expect("failed to read line");

    let input: u32 = input_text.trim().parse()
        .expect("Please type a number!");
}

Comments

3

Try this:

fn main() {
    let input_text = std::old_io::stdin()
        .read_line()
        .ok()
        .expect("failed to read line");
    let input_number: Option<i32> = input_text.trim().parse().ok();
    let number = match input_number{
        Some(num) => num,
        None => {
            println!("Wrong input data! Input a number.");
            return;
        }
    };
    println!("{}", number);
}

1 Comment

This answer refers to the old_io module, which is not available in Rust 1.0; this answer is no longer useful.
-1

For converting the string to integer we use trim and parse. The trim() method on Strings will eliminate any whitespace at the beginning and end of our string.

This means that if we type 5 and hit return, guess looks like this: 5\n. The \n represents ‘newline’, the enter key. trim() gets rid of this, leaving our string with only the 5.

The parse() method on strings parses a string into some kind of number. Since it can parse a variety of numbers, we need to give Rust a hint as to the exact type of number we want. Hence, let a_int: i32. The colon (:) after guess tells Rust we’re going to annotate its type. i32 is an integer, thirty-two-bit integer. We use the expect() method to crash if there’s an error.

 let a_int: i32 = input_1.trim().parse()
 .ok()
 .expect("Please type a number!");

Ref:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.