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