2013-12-15 43 views
4

可以說我有一個外部while循環來讀取每個字符並將其輸出到控制檯。我也想標記一個單詞,如果它被發現,並通過使用peek方法,我可以找到一個單詞的第一個實例。有沒有辦法在前面看到多個地方?例如,如果我在尋找「發薪日」這個詞。我知道我可以將它輸入到一個字符串中並搜索一個字符串,但我想以二進制模式讀取文件,而且我不想從外部循環中取走任何值。如果我有一個讀取方法的內部循環,那麼這些值不會通過外部循環顯示。peek()前方多個地方?

感謝

int main() 

ifstream strm; 
char *chr = new char; 

strm.open("mytext.txt",ios::out | ios::binary); 

while (strm.read(chr,1) 
{ 
    if (strm.peek() == 'p'; 
    { 
    cout << "found a word beginning with 'p'" << endl; 
    //what if I want to read multiple characters ahead. Peek will read only one. 
    } 

} 
+0

爲什麼使用動態分配? – Shoe

回答

5

您可以使用seekg方法將istream的內跳來跳去。

如果以二進制模式打開文件,可以使用tellg方法標記要跳轉到的位置。

但是,如果以文本模式打開文件,則最好使用偏移量跳轉(即strm.seekg(offset,strm.cur)),因爲tellg和seekg會計算像newline這樣的多字節字符在文本模式下。所以,如果你發現下一個字符是「p」,那麼你可以閱讀下一個n字符,然後跳回-n字符,如果它不是你想要的。

+0

謝謝。這兩種解決方案都可以在這裏工作,但是我之前從未真正使用過seekg,現在我已經發現它了,它完全符合我的需求。非常感謝。 – domonica

+0

@domonica:請注意,從長遠來看,擁有合適的解析器通常是一個更好的解決方案,因爲正確解析正確的錯誤處理,針對空白更改的穩健性以及安全轉義意味着解析作業可以非常迅速地增長複雜性。更好的辦法是使用像XML或JSON或CSV等格式良好的格式,而不是定義自己的格式,並使用良好的調試庫來編寫和加載它們。 –

4

有多種方法可以實現這一點,但傳統方法只是在原始文件和「用戶」功能之間添加一層:詞法分析器。

例如,具有無限的緩衝詞法分析:

class Lexer { 
public: 
    Lexer(std::istream& s): source(s) { this->read(); } 

    explicit operator bool() const { 
     return not queue.empty(); 
    } 

    Lexer& operator>>(std::string& s) { 
     assert(*this and "Test for readiness before calling this method"); 

     s = queue.front(); 
     queue.pop_front(); 

     if (queue.empty()) { this->read(); } 
     return *this; 
    } 

    std::string const* peek(size_t const i) { 
     while (source and queue.size() < i) { this->read(); } 
     return queue.size() >= i ? &queue[i] : nullptr; 
    } 

private: 
    void read() { 
     queue.emplace_back(); 
     if (not (source >> queue.back())) { queue.pop_back(); } 
    } 

    std::istream& source; 
    std::deque<std::string> queue; 
}; // class Lexer 

注:很明顯,你可以完全限制詞法分析器的緩衝,或使其緩衝東西比其他的話,等...主自定義類的優勢在於:you指示語義!