我编写了一个函数来提示输入并返回结果。在此版本中,返回的字符串包含用户的尾随换行符。我想将该换行符(以及该换行符)删除后返回输入:
fn read_with_prompt(prompt: &str) -> io::Result<String> {
let stdout = io::stdout();
let mut reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
try!(reader.read_line(&mut input));
// TODO: Remove trailing newline if present
Ok(input)
}
仅删除单个尾随换行符的原因是此函数还将用于提示输入密码(适当使用termios以停止回显),如果某人的密码具有尾随空格,则应保留该空格。
在关于如何在字符串末尾实际删除单个换行符之后,我最后使用trim_right_matches
。然而,返回一个&str
。我尝试使用Cow
来处理这个问题,但错误仍然表明input
变量的存活时间不够长。
fn read_with_prompt<'a>(prompt: &str) -> io::Result<Cow<'a, str>> {
let stdout = io::stdout();
let mut reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
try!(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
}
})))
}
错误:
src/main.rs:613:22: 613:27 error: `input` does not live long enough
src/main.rs:613 Ok(Cow::Borrowed(input.trim_right_matches(|c| {
^~~~~
src/main.rs:604:79: 622:2 note: reference must be valid for the lifetime 'a as
defined on the block at 604:78...
src/main.rs:604 fn read_with_prompt<'a, S: AsRef<str>>(prompt: S) -> io::Resul
t<Cow<'a, str>> {
src/main.rs:605 let stdout = io::stdout();
src/main.rs:606 let mut reader = io::stdin();
src/main.rs:607 let mut input = String::new();
src/main.rs:608 print!("{}", prompt.as_ref());
src/main.rs:609 stdout.lock().flush().unwrap();
...
src/main.rs:607:35: 622:2 note: ...but borrowed value is only valid for the bl
ock suffix following statement 2 at 607:34
src/main.rs:607 let mut input = String::new();
src/main.rs:608 print!("{}", prompt.as_ref());
src/main.rs:609 stdout.lock().flush().unwrap();
src/main.rs:610 try!(reader.read_line(&mut input));
src/main.rs:611
src/main.rs:612 let mut trimmed = false;
...
基于previous questions along these lines,似乎这是不可能的。是唯一一个分配删除了尾部换行符的新字符串的选项吗?似乎应该有一种方法来修剪字符串而不复制它(在C中你只需用'\n'
替换'\0'
)。
你可以使用String::pop
或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);
}
比通用解决方案更通用的解决方案,适用于任何类型的行结束:
fn main() {
let mut s = "hello\r\n".to_string();
let len_withoutcrlf = s.trim_right().len();
s.truncate(len_withoutcrlf);
assert_eq!("hello", &s);
}
在不重新分配字符串的情况下剥离单个尾随换行符的跨平台方法是:
fn trim_newline(s: &mut String) {
if s.ends_with('\n') {
s.pop();
if s.ends_with('\r') {
s.pop();
}
}
}
这将从字符串的末尾删除"\n"
或"\r\n"
,但没有额外的空格。