Struct 如何从字符串创建迭代器并将其存储在结构中?
我正在尝试为我的结构创建一个构造函数,它将在从文件读取的Struct 如何从字符串创建迭代器并将其存储在结构中?,struct,rust,iterator,lifetime,borrow-checker,Struct,Rust,Iterator,Lifetime,Borrow Checker,我正在尝试为我的结构创建一个构造函数,它将在从文件读取的字符串上存储一个迭代器。问题是一旦函数返回,String就会被删除,编译器会抱怨new()返回一个引用当前函数所拥有的数据的值。有没有一种方法可以将字符串以某种方式与结构相关联,从而在返回后不会删除它 我想我理解这里的抱怨,但我不明白如何处理它,因为我希望构造函数同时处理文件读取和迭代器创建 pub struct CharStream<'a> { input: std::str::Chars<'a>,
字符串上存储一个迭代器。问题是一旦函数返回,String
就会被删除,编译器会抱怨new()返回一个引用当前函数所拥有的数据的值。有没有一种方法可以将字符串
以某种方式与结构相关联,从而在返回后不会删除它
我想我理解这里的抱怨,但我不明白如何处理它,因为我希望构造函数同时处理文件读取和迭代器创建
pub struct CharStream<'a> {
input: std::str::Chars<'a>,
filename: String,
}
impl<'a> CharStream<'a> {
pub fn new(filename: String) -> CharStream<'a> {
let mut file = File::open(&filename).unwrap();
let mut input = String::new();
file.read_to_string(&mut input);
CharStream {
input: input.chars(), // Create an iterator over `input`
filename: filename,
}
// `input` is dropped here
}
}
pub struct CharStream,
文件名:String,
}
恳求{
pub fn new(filename:String)->CharStream通过String::chars()
返回的迭代器仅在原始字符串input
存在时有效。input
在new
的末尾被删除,因此迭代器无法从函数返回
要解决此问题,您可能还希望在结构中存储输入
字符串,但随后会遇到其他问题,因为一个结构成员不能引用同一结构的另一个成员。原因之一是结构将变得不可移动,因为移动它会使引用无效
最简单的解决方案可能是将char
收集到Vec
中,并将该向量存储在CharStream
中。然后添加usize
索引并编写自己的迭代器
实现
另一种方法(内存效率更高)是存储字符串本身,并根据需要创建字符
迭代器,但这当然会导致不同的API
涉及RefCell
或类似包装的解决方案也可能是可行的。我会将CharStream
重命名为FileContents
,让它同时拥有文件的filename
和contents
作为String
s。然后当需要生成TokenIter
在c上迭代时然后可以从内容中创建字符的大块char
s{
记号笔{
chars:self.contents.chars(),
}
}
}
结构令牌,
}
结构令牌;//表示一些字符块
恳求{
类型项=令牌;
fn下一步(&mut self)->选项{
self.chars.next();//根据需要多次调用以创建令牌
Some(Token)//在此处返回创建的Token
}
}
fn示例(文件名:字符串){
让file_contents=FileContents::new(文件名);
让tokens=file_contents.token_iter();
代币中的代币{
//更多的处理在这里
}
}
为什么不能将字符串存储在结构中,然后按需创建Chars迭代器?@pretzelhammer,因为CharStream将是另一个迭代器的一部分,该迭代器将在字符块(令牌迭代器)上进行迭代。所以我们可以在TokenIterator上调用next(),因为它在字符上进行迭代,所以它应该将状态存储在某个地方。哇,我没有想到一个API,FileStream(FileContents)会在其中创建并返回标记器(反之亦然),我想这对我来说是可行的:),但我认为这里有一个缺陷。我想到了一个解决方案,fn example
将直接调用Token::new_iter(filename)
并在迭代器上获得迭代器。在您的示例中,我需要首先创建文件内容
,因此管理文件内容
生存期的是fn示例
,而不是TokenIter
。