簡體   English   中英

如何從字符串創建迭代器並_將其存儲在結構中?

[英]How to create an iterator from string _and_ store it in a struct?

我正在嘗試為我的結構創建一個構造函數,它將在從文件讀取的String上存儲一個迭代器。 問題是一旦函數返回, String被刪除並且編譯器抱怨new() returns a value referencing data owned by the current function 有沒有辦法以某種方式將String與結構相關聯,以便在返回后不會刪除它?

我想我在這里理解一個抱怨,但我不明白如何處理它,因為我希望構造函數同時處理文件讀取和迭代器創建。

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
    }
}

我會將CharStream重命名為FileContents並讓它擁有文件的filenamecontents作為String s。 然后,當您需要生成TokenIter以從contents中迭代char塊時,您可以按需創建Chars<'a>並將其傳遞給TokenIter 完整示例:

use std::fs;
use std::str::Chars;

struct FileContents {
    filename: String,
    contents: String,
}

impl FileContents {
    fn new(filename: String) -> Self {
        let contents = fs::read_to_string(&filename).unwrap();
        FileContents { filename, contents }
    }
    fn token_iter(&self) -> TokenIter<'_> {
        TokenIter {
            chars: self.contents.chars(),
        }
    }
}

struct TokenIter<'a> {
    chars: Chars<'a>,
}

struct Token; // represents some chunk of chars

impl<'a> Iterator for TokenIter<'a> {
    type Item = Token;
    fn next(&mut self) -> Option<Self::Item> {
        self.chars.next(); // call as many times as necessary to create token
        Some(Token) // return created token here
    }
}

fn example(filename: String) {
    let file_contents = FileContents::new(filename);
    let tokens = file_contents.token_iter();
    for token in tokens {
        // more processing here
    }
}

操場

String::chars()返回的迭代器僅在原始字符串input存在時才有效。 inputnew的末尾被刪除,因此無法從 function 返回迭代器。

為了解決這個問題,您還希望將input字符串存儲在結構中,但隨后您會遇到其他問題,因為一個結構成員不能引用同一結構的另一個成員。 這樣做的一個原因是結構將變得不可移動,因為移動它會使引用無效。

最簡單的解決方案可能是將char收集到Vec<char>並將該向量存儲在CharStream中。 然后添加一個usize索引並編寫您自己的Iterator<Item = char>實現。

另一種方法(更節省內存)是存儲String本身,並按需創建Chars迭代器,但這當然會導致不同的 API。

涉及RefCell或類似包裝器的解決方案也可能是可能的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM