Remove the new line from read_line

I've the below code to try stdin

use std::io;

fn main() {
    println!("What's your name?");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    println!("Hello {}!", input);
}

The output I get is:

What's your name? <- from app
Hasan <- my input followed by pressing Enter
Hello Hasan <- First line of the output
! < -Second line of the output, this should be in the same first line, not in separate line!

Perhaps calling trim or one of its friends helps? Or if input.ends_with('\n') { input[0..input.len() - 2].to_string() or using a regex to capture (this is overkill).

1 Like

Not -2, but -1 instead and you can also omit the 0, something like this.

let foo = "abc\n";
println!("{}", &foo[..foo.len()-1]);

but I would recommend .trim() (or .trim_right() if you want).

1 Like

Oh... Well you know what Dijkstra said? (paraphrased)

There are 2 hard problems in programming:

  • Naming things
  • Cache invalidation
  • Off by one errors

When sub-slicing I tend to be explicit. I tend to say its personal style/taste.

Yeah, I think so too, or .trim_matches()/.trim_right_mathches() if other kind of whitespace should be kept.

2 Likes

Thanks, I did not understand the meaning of the double dots before the foo.len, i,e, ..foo.len() can you pls explain the meaning of using them.

In generall .. constructs a range. If its left argument is ommitted, it has no lower bound and (in theory reaches from -infinty to the specified maximum. But in fact its determined by std::ops::Range and friends how its treated.

For indexing a String by a range the appropriate implementation for Index<R> is used, where R is one of the range you can construct using the .. syntax.

When subslicing anything it is common to interprete missing ends of the range as the index types minumum or maximum, such that x[..] is treated equivalent to x[0..x.len()], x[..1] equivalent to x[0..1] and x[1..] equivalent to x[1..x.len()].

3 Likes

i've used to following in the past to get a line from stdin without the newline (BufRead.lines() strips those)—tho it might be kind of silly to create an iterator if you only want to get one line:

    let stdin = io::stdin();
    let input = stdin.lock().lines().next().unwrap().unwrap();