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
。