Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 从Vec创建字符串<;char>;_String_Rust - Fatal编程技术网

String 从Vec创建字符串<;char>;

String 从Vec创建字符串<;char>;,string,rust,String,Rust,我有一个Vec,我需要把它变成&str或字符串,但我不确定最好的方法。我环顾四周,发现的每一种资源似乎都在某种程度上过时了。中的答案似乎不适用于最新版本 我使用的是2015-3-19《夜间》杂志,基于迭代器的方法与一起使用。在更新语言更改后,collect应该可以工作: char_vector.iter().cloned().collect::<String>(); char_vector.iter().cloned().collect::(); (我选择用.clone()替换.

我有一个
Vec
,我需要把它变成
&str
字符串,但我不确定最好的方法。我环顾四周,发现的每一种资源似乎都在某种程度上过时了。中的答案似乎不适用于最新版本


我使用的是2015-3-19《夜间》杂志,基于迭代器的方法与
一起使用。在更新语言更改后,collect
应该可以工作:

char_vector.iter().cloned().collect::<String>();
char_vector.iter().cloned().collect::();

(我选择用
.clone()
替换
.map(|c |*c)
,但两者都有效。)

如果你的向量可以被消耗,你也可以使用
进入iter
以避免
克隆

fn main() {
    let char_vector = vec!['h', 'e', 'l', 'l', 'o'];
    let str: String = char_vector.into_iter().collect();

    println!("{}", str);
}

您可以将
Vec
转换为
字符串
,而无需进行任何分配。但它需要一些不安全的代码:

#![feature(raw, unicode)]
use std::raw::Repr;
use std::slice::from_raw_parts_mut;

fn inplace_to_string(v: Vec<char>) -> String {
    unsafe {
        let mut i = 0;
        {
            let ch_v = &v[..];
            let r = ch_v.repr();
            let p: &mut [u8] = from_raw_parts_mut(r.data as *mut u8, r.len*4);
            for ch in ch_v {
                i += ch.encode_utf8(&mut p[i..i+4]).unwrap();
            }
        }
        let p = v.as_ptr();
        let cap = v.capacity()*4;
        std::mem::forget(v);
        let v = Vec::from_raw_parts(p as *mut u8, i, cap);
        String::from_utf8_unchecked(v)
    }
}

fn main() {
    let char_vector = vec!['h', 'ä', 'l', 'l', 'ö'];
    let str: String = char_vector.iter().cloned().collect();
    let str2 = inplace_to_string(char_vector);

    println!("{}", str);
    println!("{}", str2);
}
我们需要它来迭代unicode字符,并用utf8编码的对应字符替换它们。由于utf8总是较短或与unicode长度相同,因此我们可以保证不会覆盖尚未阅读的任何部分

for ch in ch_v {
    i += ch.encode_utf8(&mut v[i..i+4]).unwrap();
}
由于
char
始终是unicode,我们的缓冲区始终正好是4个字节(这是utf8编码的unicode字符所需的最大字节数),因此我们可以将字符编码为utf8,而无需检查它是否工作(它将始终工作)。
encode\u utf8
函数返回utf8表示的长度。我们的索引
i
是最后写入的utf8字符的位置

最后,我们需要做一些清理。我们的向量仍然是
Vec
类型。我们获得了所需的所有信息(指向堆分配数组和容量的指针)

然后我们从所有义务中释放前一个向量,比如释放内存

std::mem::forget(v);
最后以正确的长度和容量重新创建u8向量,并直接将其转换为字符串。不需要检查到字符串的转换,因为我们已经知道utf8是正确的,因为原始的
Vec
只能包含正确的unicode字符

let v = Vec::from_raw_parts(p as *mut u8, i, cap);
String::from_utf8_unchecked(v)

在这种情况下,克隆是一个
char
,这是非常便宜的(它将编译成一个指针解引用,将char从内存带到一个(4字节)寄存器)。当然,避免克隆通常对性能很重要,但是
char
不是这样的类型,放弃对
Vec
的控制可能并不可取。对于超便宜的部分,我不知道。只是想为克隆提供替代方案,这在其他不太便宜的情况下也会有所帮助哦,对了,我误读了构造函数(它将容量乘以元素大小,但只将其用于分配大小,而不用于容量)。好吧,现在我们有一个很有启发性的例子,说明为什么不应该轻率地使用
不安全的
。-)不过修复应该很容易,请参阅
Vec::from_raw_parts
.niat trick的文档。“由于我们的字符绝对是unicode,我们可以将它们编码为utf8而不检查它是否有效”:fwiw,
encode\u utf8
char
s进行操作,这些字符始终是有效的unicode:错误在于输入缓冲区太短(例如,试图将一个4字节的代码点写入
&mut v[i..i+2]
)。谢谢,补充了这一信息
std::mem::forget(v);
let v = Vec::from_raw_parts(p as *mut u8, i, cap);
String::from_utf8_unchecked(v)