我为自己设定了一项任务,以获得一些基本的Rust知识。任务是:
然而,这是一个比预期更棘手的挑战。主要是由于对生命的理解。以下代码是我在几次实验后得到的代码,但编译器并没有停止对我大喊大叫。从stdin中读取一些键值对并将它们放入一个hashmap。
use std::io;
use std::collections::HashMap;
fn main() {
let mut input = io::stdin();
let mut lock = input.lock();
let mut lines_iter = lock.lines();
let mut map = HashMap::new();
for line in lines_iter {
let text = line.ok().unwrap();
let kv_pair: Vec<&str> = text.words().take(2).collect();
map.insert(kv_pair[0], kv_pair[1]);
}
println!("{}", map.len());
}
编译器基本上说:
`text` does not live long enough
据我了解,这是因为&#39; text&#39;仅限于循环的范围。 因此,我在循环中提取的键值对也绑定到循环边界。因此,将它们插入到外部地图会导致悬空指针,因为文本&#39;每次迭代后都会被销毁。 (请告诉我,如果我错了)
最大的问题是:如何解决这个问题?
我的直觉说:
制作一份&#34;拥有的副本&#34;键值对和&#34;扩展&#34;它的生命周期到外部范围......但我不知道如何实现这一目标。
答案 0 :(得分:3)
'text'的生命周期仅限于循环的范围。因此,我在循环中提取的键值对也绑定到循环边界。因此,将它们插入外部地图会导致悬空指针,因为“文本”将在每次迭代后被销毁。
听起来对我不错。
制作键值对的“拥有副本”。
拥有的&str
是String
:
map.insert(kv_pair[0].to_string(), kv_pair[1].to_string());
修改强>
原始代码如下,但我已将上面的答案更新为更惯用的
map.insert(String::from_str(kv_pair[0]), String::from_str(kv_pair[1]));
答案 1 :(得分:1)
在 Rust 1.1
中,函数words
被标记为已弃用。现在你应该使用split_whitespace
。
这是一个替代解决方案,它更具功能性和惯用性(适用于1.3
)。
use std::io::{self, BufRead};
use std::collections::HashMap;
fn main() {
let stdin = io::stdin();
// iterate over all lines, "change" the lines and collect into `HashMap`
let map: HashMap<_, _> = stdin.lock().lines().filter_map(|line_res| {
// convert `Result` to `Option` and map the `Some`-value to a pair of
// `String`s
line_res.ok().map(|line| {
let kv: Vec<_> = line.split_whitespace().take(2).collect();
(kv[0].to_owned(), kv[1].to_owned())
})
}).collect();
println!("{}", map.len());
}