String 在文件中的行上迭代并从vec中查找子字符串!锈迹斑斑

String 在文件中的行上迭代并从vec中查找子字符串!锈迹斑斑,string,rust,match,String,Rust,Match,我正在写一个项目,在这个项目中,可以从一个数据文件构造一个结构System。 在数据文件中,某些行包含一些关键字,这些关键字指示要在该行内部或在随后的N行中读取的值(与该行用空行分隔) 我想要一个vec包含关键字(编译时静态已知),检查迭代器返回的行是否包含关键字,并执行适当的操作 现在,我的代码如下所示: impl System { fn read_data<P>(filename: P) -> io::Result<io::Lines<io::BufRe

我正在写一个项目,在这个项目中,可以从一个数据文件构造一个结构
System
。 在数据文件中,某些行包含一些关键字,这些关键字指示要在该行内部或在随后的N行中读取的值(与该行用空行分隔)

我想要一个
vec包含关键字(编译时静态已知),检查迭代器返回的行是否包含关键字,并执行适当的操作

现在,我的代码如下所示:

impl System {
    fn read_data<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> where P: AsRef<Path> {
        let file = File::open(filename)?;
        let f = BufReader::new(file);
        Ok(f.lines())
    }
    ...
    pub fn new_from_data<P>(dataname: P) -> System where P: AsRef<Path> {
        let keywd = vec!["atoms", "atom types".into(),
                         "Atoms".into()];
        let mut sys = System::new();
        if let Ok(mut lines) = System::read_data(dataname) {
            while let Some(line) = lines.next() {
                for k in keywd {
                    let split: Vec<&str> = line.unwrap().split(" ").collect();
                    if split.contains(k) {
                        match k {
                        "atoms" => sys.natoms = split[0].parse().unwrap(),
                        "atom types" => sys.ntypes = split[0].parse().unwrap(),
                        "Atoms" => {
                            lines.next();
                            // assumes fields are: atom-ID molecule-ID atom-type q x y z
                            for _ in 1..=sys.natoms {
                                let atline = lines.next().unwrap().unwrap();
                                let data: Vec<&str> = atline.split(" ").collect();
                                let atid: i32 = data[0].parse().unwrap();
                                let molid: i32 = data[1].parse().unwrap();
                                let atype: i32 = data[2].parse().unwrap();
                                let charge: f32 = data[3].parse().unwrap();
                                let x: f32 = data[4].parse().unwrap();
                                let y: f32 = data[5].parse().unwrap();
                                let z: f32 = data[6].parse().unwrap();
                                let at = Atom::new(atid, molid, atype, charge, x, y, z);
                                sys.atoms.push(at);
                            };
                        },
                        _ => (),
                        }
                    }
                }
            }
        }
        sys
    }
}

我们应该如何声明子字符串并将其与我放入
keywd
中的字符串进行比较?我试着尊重k的内容,告诉它去看&keywd等等,但我只是觉得我没有正确地解决这个问题是在浪费时间。提前感谢,我们非常感谢您的帮助。

让我们逐一讨论这些问题。我将按照代码中显示的方式查看

首先,您需要在
for
循环中借用
keywd
,即
&keywd
。因为否则
keywd
while
循环的第一次迭代后会被移动,因此编译器会对此抱怨

for k in &keywd {
    let split: Vec<&str> = line.unwrap().split(" ").collect();
请注意,您正在为每个
关键字拆分
,这是不必要的。因此,您也可以将其移动到
for
循环之外

总而言之,结果是这样的:

impl System {
    fn read_data<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> where P: AsRef<Path> {
        let file = File::open(filename)?;
        let f = BufReader::new(file);
        Ok(f.lines())
    }
    ...
    pub fn new_from_data<P>(dataname: P) -> System where P: AsRef<Path> {
        let keywd = vec!["atoms", "atom types".into(),
                         "Atoms".into()];
        let mut sys = System::new();
        if let Ok(mut lines) = System::read_data(dataname) {
            while let Some(line) = lines.next() {
                for k in keywd {
                    let split: Vec<&str> = line.unwrap().split(" ").collect();
                    if split.contains(k) {
                        match k {
                        "atoms" => sys.natoms = split[0].parse().unwrap(),
                        "atom types" => sys.ntypes = split[0].parse().unwrap(),
                        "Atoms" => {
                            lines.next();
                            // assumes fields are: atom-ID molecule-ID atom-type q x y z
                            for _ in 1..=sys.natoms {
                                let atline = lines.next().unwrap().unwrap();
                                let data: Vec<&str> = atline.split(" ").collect();
                                let atid: i32 = data[0].parse().unwrap();
                                let molid: i32 = data[1].parse().unwrap();
                                let atype: i32 = data[2].parse().unwrap();
                                let charge: f32 = data[3].parse().unwrap();
                                let x: f32 = data[4].parse().unwrap();
                                let y: f32 = data[5].parse().unwrap();
                                let z: f32 = data[6].parse().unwrap();
                                let at = Atom::new(atid, molid, atype, charge, x, y, z);
                                sys.atoms.push(at);
                            };
                        },
                        _ => (),
                        }
                    }
                }
            }
        }
        sys
    }
}
如果让Ok(多行)=读取数据(“test.txt”){
而让一些(行)=行。下一个(){
let split:Vec=line.split(“”.collect();
用于输入和输入键{
如果拆分。包含(k){
...

既然我们借用了
&keywd
,那么我们就不需要将
k
更改为
&k
,因为现在
k
已经是
&&str
了,让我们逐一讨论这些问题。我将按照代码中出现的内容来讨论

首先,您需要在
for
循环中借用
keywd
,即
&keywd
。否则
keywd
会在
while
循环的第一次迭代后移动,因此编译器会对此抱怨

for k in &keywd {
    let split: Vec<&str> = line.unwrap().split(" ").collect();
请注意,您正在为每个
keywd
拆分
,这是不必要的。因此,您也可以将该行移动到
for
循环之外

总而言之,结果是这样的:

impl System {
    fn read_data<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> where P: AsRef<Path> {
        let file = File::open(filename)?;
        let f = BufReader::new(file);
        Ok(f.lines())
    }
    ...
    pub fn new_from_data<P>(dataname: P) -> System where P: AsRef<Path> {
        let keywd = vec!["atoms", "atom types".into(),
                         "Atoms".into()];
        let mut sys = System::new();
        if let Ok(mut lines) = System::read_data(dataname) {
            while let Some(line) = lines.next() {
                for k in keywd {
                    let split: Vec<&str> = line.unwrap().split(" ").collect();
                    if split.contains(k) {
                        match k {
                        "atoms" => sys.natoms = split[0].parse().unwrap(),
                        "atom types" => sys.ntypes = split[0].parse().unwrap(),
                        "Atoms" => {
                            lines.next();
                            // assumes fields are: atom-ID molecule-ID atom-type q x y z
                            for _ in 1..=sys.natoms {
                                let atline = lines.next().unwrap().unwrap();
                                let data: Vec<&str> = atline.split(" ").collect();
                                let atid: i32 = data[0].parse().unwrap();
                                let molid: i32 = data[1].parse().unwrap();
                                let atype: i32 = data[2].parse().unwrap();
                                let charge: f32 = data[3].parse().unwrap();
                                let x: f32 = data[4].parse().unwrap();
                                let y: f32 = data[5].parse().unwrap();
                                let z: f32 = data[6].parse().unwrap();
                                let at = Atom::new(atid, molid, atype, charge, x, y, z);
                                sys.atoms.push(at);
                            };
                        },
                        _ => (),
                        }
                    }
                }
            }
        }
        sys
    }
}
如果让Ok(多行)=读取数据(“test.txt”){
而让一些(行)=行。下一个(){
let split:Vec=line.split(“”.collect();
用于输入和输入键{
如果拆分。包含(k){
...

既然我们借用了
&keywd
,那么我们就不需要将
k
更改为
&k
,因为现在
k
已经是
&str
对“预期
&str
,发现
&str
的快速回答。”是使用
&k
,但您是对的,通过类型检查的修复,但随后借用检查器进入并发现更多错误“预期
和&str
,找到
&str
”的快速回答就是使用
&k
,但是你是对的,通过了类型检查的修复程序,但是借用检查器进来发现了更多的错误。我认为这是成功的。在随后的比赛中,我仍然必须取消对
*k
的引用,将其与
str
进行比较,但现在它似乎运行并在测试文件上执行我想要的操作。谢谢!我我喜欢Rust的大部分设计,但我真的无法克服这种字符串类型的问题……啊,是的,我错过了比赛。Rust确实有点棘手,等一下,很快你就会使用
AsRef
Cow
。我想这就成功了。在随后的比赛中,我仍然不得不取消对
*k
的引用,以便与之进行比较
str
但目前它似乎在测试文件上运行并执行我想要的操作。谢谢!我喜欢Rust的大部分设计,但我真的无法克服这种字符串类型的问题…啊,是的,我错过了匹配。Rust确实有点棘手,请稍等,很快你就会使用
AsRef
Cow