从字符串中删除单个尾随换行符而不克隆 [英] Remove single trailing newline from String without cloning

查看:47
本文介绍了从字符串中删除单个尾随换行符而不克隆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个函数来提示输入并返回结果.在此版本中,返回的字符串包括来自用户的尾随换行符.我想返回删除该换行符(以及仅该换行符)的输入:

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:

fn read_with_prompt(prompt: &str) -> io::Result<String> {
    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)
}

只删除单个尾随换行符的原因是该函数还将用于提示输入密码(适当使用 termios 停止回显),如果某人的密码有尾随空格,则应保留.

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.

在对如何实际删除字符串末尾的单个换行符大惊小怪之后,我最终使用了 trim_right_matches.然而,它返回一个 &str.我尝试使用 Cow 来解决这个问题,但错误仍然说 input 变量的寿命不够长.

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<'a>(prompt: &str) -> io::Result<Cow<'a, str>> {
    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[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 function

基于之前的问题,这似乎是不可能.分配一个删除了尾随换行符的新字符串是唯一的选择吗?似乎应该有一种方法可以在不复制的情况下修剪字符串(在 C 中,您只需将 '\n' 替换为 '\0').

Based on previous questions along these lines it seems this is not possible. Is the only option to allocate a new string that has the trailing newline removed? It seems there should be a way to trim the string without copying it (in C you'd just replace the '\n' with '\0').

推荐答案

您可以使用 String::popString::truncate:

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);
}

这篇关于从字符串中删除单个尾随换行符而不克隆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆