2017-02-24 46 views
1

我正在寫一個簡單的通用分析器組合庫。這意味着庫包含許多小的函數對象,稱爲解析器,這(調用時)字符串作爲輸入,並返回ParseResults作爲輸出,其中一個ParseResult是C++:使用std :: cin的多個副本?

template <typename A> using ParseResult = std::pair<A, std::string> 名單列表爲空,如果解析器做不匹配,如果匹配,則包含單個結果,並且可能會以多種(不明確)方式匹配的某些解析器可能會返回更多結果。

但是,這意味着現在正在進行大量的字符串複製。而且,在開始時,最終構造的解析器需要用字符串調用,因此所有的std::cin(或文件的coompete內容)都被複制到一個字符串中。

什麼看起來更好一些(因爲解析器只查看字符串的當前前面的第一個(幾個)字符),是爲了跟蹤你現在在標準輸入中的位置流。我相信這正是std::istream。但是,istreams不可複製。我的問題如何解決? 有沒有辦法返回一個istream的副本,指向原始指向的幾個字符?還是有另一種更清潔的方法來解決這個問題?

+3

你知道C++中的引用是什麼嗎? – PiotrNycz

回答

1

這個問題可以這樣改寫:如何以避免過度複製並允許輸入流的方式表示未分離的輸入部分?

最靈活的方法是用迭代器表示它。如果你的解析器做回溯,它需要是ForwardIterator,否則InputIterator就足夠了。這意味着您可以直接使用std::istream_iterator而不是std::cinstd::ifstream,或者從內存中解析std::stringschar陣列。使用回溯進行流式傳輸會涉及更多,需要您編寫緩衝迭代器適配器,將InputIterator(如std::istream_iterator)轉換爲ForwardIterator,或者在需要回溯時編寫迭代器直接包裝std::ifstream並執行.seekg()

另一種選擇是使用C++ 17的std::string_view,它不會複製,並且有一個很好的解析友好的界面。儘管這並不能解決流式傳輸問題,但仍需要先讀取整個文件。

+0

謝謝你這個偉大的答案!進一步的研究指出'.seekg()'不適用於標準輸入,這意味着將所有內容讀入內存(然後使用'std :: istringstream'或者'std :: string_view'可能是最好的要走的路。 – Qqwy