2014-10-06 32 views
3

我正在使用一個istringstream逐字讀取string。但是,當我的條件失敗時,我需要能夠將istringstream恢復到上一個​​單詞被讀取之前。我的示例代碼有效,但我想知道是否有更直接的方式來使用流來完成此操作。如何保存和恢復std :: istringstream的緩衝區?

std::string str("my string"); 
std::istringstream iss(str); 

std::ostringstream ossBackup << iss.rdbuf(); // Writes contents of buffer and in the process changes the buffer 
std::string strBackup(ossBackup.str());  // Buffer has been saved as string 

iss.str(strBackup);       // Use string to restore iss's buffer 
iss.clear();         // Clear error states 
iss >> word;         // Now that I have a backup read the 1st word ("my" was read) 

// Revert the `istringstream` to before the previous word was read. 
iss.str(strBackup);       // Restore iss to before last word was read 
iss.clear();        // Clear error states 
iss >> word;        // "my" was read again 
+1

那麼,這似乎取決於你如何定義_「當我的情況失敗」_完全。你可以檢查'operator >>()'操作留下的值,並且設置流狀態失敗。這是一個[示例](http://stackoverflow.com/questions/24504582/test-whether-stringstream-operator-has-parsed-a-bad-type?noredirect=1#comment37965807_24504582)。 – 2014-10-06 18:28:58

回答

3

您可以使用tellg()seekg()以保存和恢復您的位置,如果你喜歡:

#include <string> 
#include <sstream> 

int main() 
{ 
    std::istringstream iss("some text"); 

    std::string word; 

    // save the position 
    std::streampos pos = iss.tellg(); 

    // read a word 
    if(iss >> word) 
     std::cout << word << '\n'; 

    iss.clear(); // clear eof or other errors 
    iss.seekg(pos); // move to saved position 

    while(iss >> word) 
     std::cout << word << '\n'; 

} 
+0

對我來說,現在看起來如此明顯,你已經說過我無法想到一個有效的解決方案,我感到很無聊。 – 2014-10-06 19:09:18

1

這是真的只保證對字符串流的工作,但可以反覆調用unget(),直到你達到一個空格字符:

#include <iostream> 
#include <sstream> 

template <int n> 
std::istream& back(std::istream& is) 
{ 
    bool state = is.good(); 

    auto& f = std::use_facet<std::ctype<char>>(is.getloc()); 
    for (int i = 0; i < n && is; ++i) 
     while (is.unget() && !f.is(f.space, is.peek())); 

    if (state && !is) 
     is.clear(); 
    return is; 
} 

int main() 
{ 
    std::stringstream iss("hello world"); 
    std::string str; 

    std::cout << "Value Before: "; 
    iss >> str; 

    std::cout << str << std::endl; 
    iss >> back<1>; // go back one word 

    std::cout << "Value after: "; 
    iss >> str; 

    std::cout << str; 
} 

Live Demo