patternrustModerate
Remove single trailing newline from String without cloning
Viewed 0 times
cloningfromremovetrailingsinglewithoutstringnewline
Problem
I have written a function to prompt for input and return the result. In this version, the returned string includes a trailing newline from the user. I would like to return the input with that newline (and just that newline) removed:
The reason for only removing the single trailing newline is that this function will also be used to prompt for a password (with appropriate use of termios to stop echoing) and if someone's password has trailing whitespace, this should be preserved.
After much fussing about how to actually remove a single newline at the end of a string, I ended up using
Error:
| _____|
| |
14 | | if !trimmed && c == '\n' {
15 | | trimmed = true;
16 | | true
... |
20 | | }
21 | | })))
| |________^ returns a value referencing data owned by the current func
fn read_with_prompt(prompt: &str) -> io::Result {
let stdout = io::stdout();
let reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
reader.read_line(&mut input)?;
// TODO: Remove trailing newline if present
Ok(input)
}
The reason for only removing the single trailing newline is that this function will also be used to prompt for a password (with appropriate use of termios to stop echoing) and if someone's password has trailing whitespace, this should be preserved.
After much fussing about how to actually remove a single newline at the end of a string, I ended up using
trim_right_matches. However that returns a &str. I tried using Cow to deal with this but the error still says that the input variable doesn't live long enough.fn read_with_prompt(prompt: &str) -> io::Result> {
let stdout = io::stdout();
let reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
reader.read_line(&mut input)?;
let mut trimmed = false;
Ok(Cow::Borrowed(input.trim_right_matches(|c| {
if !trimmed && c == '\n' {
trimmed = true;
true
}
else {
false
}
})))
}
Error:
error[E0515]: cannot return value referencing local variable input
--> src/lib.rs:13:5
|
13 | Ok(Cow::Borrowed(input.trim_right_matches(|c| {
| ^ ----- input` is borrowed here| _____|
| |
14 | | if !trimmed && c == '\n' {
15 | | trimmed = true;
16 | | true
... |
20 | | }
21 | | })))
| |________^ returns a value referencing data owned by the current func
Solution
You can use
String::pop or String::truncate:fn main() {
let mut s = "hello\n".to_string();
s.pop();
assert_eq!("hello", &s);
let mut s = "hello\n".to_string();
let len = s.len();
s.truncate(len - 1);
assert_eq!("hello", &s);
}Code Snippets
fn main() {
let mut s = "hello\n".to_string();
s.pop();
assert_eq!("hello", &s);
let mut s = "hello\n".to_string();
let len = s.len();
s.truncate(len - 1);
assert_eq!("hello", &s);
}Context
Stack Overflow Q#37888042, score: 43
Revisions (0)
No revisions yet.