如何将char数组[char; N]转换为字符串切片&str?

16

假设有一个固定长度的char数组,如下:

let s: [char; 5] = ['h', 'e', 'l', 'l', 'o'];

我如何获得一个&str


注意 : [char; 5] 是多余的,类型可以被推导。 - Shepmaster
1
@Shepmaster: 我放在那里是为了让问题更清晰 :) - Rufflewind
1
你为什么要创建这样的数组?使用"hello"会更加简单和实用。 - user395760
@delnan: 有时我想创建一个包含编译时未知字符的列表,例如[c1, c2, c3] - Rufflewind
3个回答

20

如果没有分配内存,你将无法进行操作,这意味着你最终会得到一个 String

let s2: String = s.iter().collect();

问题在于,Rust 中的字符串不是char的集合,它们是 UTF-8 编码,每个字符没有固定的大小。
例如,在此情况下,数组将占用 5 x 32 位,总共 20 字节。字符串的数据总共需要 5 个字节(虽然还有 3 个指针大小的值,因此在这种情况下,整个String会占用更多的内存)。
我们从数组开始,并调用[]::iter,它会产生类型为&char的值。然后我们使用Iterator::collectIterator<Item = &char>转换为String。这使用迭代器的size_hint预先分配String中的空间, 减少额外分配的需求。

是否有类似于 vec! 宏的 String 等效物? - Rufflewind
@Rufflewind 我不确定我理解了。你是指 String::from("foo") 还是 "foo".to_string()?在某些上下文中,您还可以使用 "foo".into()。您实际上不需要宏来进行任何操作; 那些只是函数调用。我想你可以创建一个名为s的方法,如果它们太长,就调用其中之一... - Shepmaster
我的意思是类似于 str!['h', 'e', 'y'] - Rufflewind
@Rufflewind 为什么你要用这个而不是直接用“嗨”呢? - Shepmaster
有时我想创建一个在编译时不知道其字符的列表,例如 [c1, c2, c3] - Rufflewind
@Rufflewind 或许你只是想要literator - Shepmaster

6

这是一个我之前没有看到的快速一行代码:

let whatever_char_array = ['h', 'e', 'l', 'l', 'o'];
let string_from_char_array = String::from_iter(whatever_char_array);

注: 这个功能(遍历array)是最近引入的。我试图寻找确切的rustc版本,但没有找到...

1
这个功能(遍历数组)是最近引入的。我试图寻找确切的rustc版本,但没有找到...std::array :: IntoIter在1.51中引入,而impl <T,const N:usize> IntoIterator for [T; N]在1.53中引入 - Dinu

-2

我会给你一个非常简单的功能性解决方案,但这不是最好的。你可以学习一些基础知识:

let s: [char; 5] = ['h', 'e', 'l', 'l', 'o'];
let mut str = String::from("");
for x in &s {
    str.push(*x);
}
println!("{}", str);

在变量名前面,如果您想保留签名,可以加下划线,但在这个简单的例子中并不必要。程序首先创建一个空的可变String,以便您可以向String添加元素(char)。然后我们通过获取其引用对s数组进行for循环。我们将每个元素添加到初始字符串中。最后,您可以返回您的字符串或只是打印它。


1
如果您想保留签名,可以使用下划线。但这在 Rust 变量命名中并不是下划线的惯用方式。前导下划线会告诉编译器该变量是有意未使用的,而这里并非如此。 - Shepmaster
3
“String::from("");”不是创建空字符串的惯用方式。请改用“String::new”。请注意,不要改变原意。 - Shepmaster
6
使用collect的答案比这种解决方案更有效,因为collect使用extend,它为所有字符预先分配空间 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接