2014-01-29 44 views
2

我有一個std::basic_streambuf子類,可使大寫的寫入所有輸出,這樣basic_streambuf子類:實施的std ::操縱輸入

class upper_streambuf : public std::streambuf 
{ 
    public: 
     upper_streambuf(std::streambuf &real) 
      : m_realBuffer(real) 
     { 
     } 

    protected: 
     virtual int overflow(int c) 
     { 
      int uc = std::toupper(c); 
      m_realBuffer.sputc(uc); 
      return uc; 
     } 

    private: 
     std::streambuf &m_realBuffer; 
}; 

我這樣使用它,例如(這似乎工作確定):

upper_streambuf buf(*std::cout.rdbuf()); 
std::ostream ucout(&buf); 

ucout << "Hello, world!" << std::endl; // prints "HELLO, WORLD!" 

我想實現的是或多或少的逆,我想從流中讀取並將所有輸入轉換爲小寫。我有以下幾點:

class lower_streambuf : public std::streambuf 
{ 
    public: 
     lower_streambuf(std::streambuf &real) 
      : m_realBuffer(real) 
     { 
     } 

    protected: 
     virtual int underflow() 
     { 
      return std::tolower(m_realBuffer.sbumpc()); 
     } 

    private: 
     std::streambuf &m_realBuffer; 
}; 

然而,當我試着用這一個這樣的:

lower_streambuf buf(*std::cin.rdbuf()); 
std::istream lcin(&buf); 
std::string line; 

std::getline(lcin, line); 

結果是分段錯誤。我是否覆蓋或調用錯誤的功能?請注意我在C++中有點新手。另請注意,我瞭解我可以完全讀取輸入內容,並在閱讀完成後將其簡單地轉換爲小寫字母,但這更多的是用於學習/學術目的,而不是實用的任何內容。

+0

也許我錯過這裏成才,但爲什麼它,你無論從性病::流緩衝繼承,幷包含一個作爲成員變量。 – Borgleader

+0

@Borgleader非常好。它是一個streambuf對象的包裝。 – 0x499602D2

+0

首先,[int underflow()](http://en.cppreference.com/w/cpp/io/basic_streambuf/underflow)不需要參數... – Cubbi

回答

4

underflow()有後續條件,你沒有建立:當你從它返回的時候,你需要在你的streambuf中有一個獲取區域來保存你要返回的字符。

單字符緩衝區是足夠了:

protected: 
     virtual int underflow() 
     { 
      ch = std::tolower(m_realBuffer.sbumpc()); 
    +   setg(&ch, &ch, &ch+1); 
      return ch; 
     } 
    private: 
    +  char ch; // input buffer! 
     std::streambuf &m_realBuffer; 
}; 
+0

我*認爲*我明白...「獲取」緩衝區是必需的,因爲一些讀取操作不會「消耗」字符,是嗎? – dreamlax

+0

@dreamlax破壞後件=任何事情都可能發生。具體來說,'getline'調用'sbumpc'(在我剛纔看到的實現中),當get區域爲空時調用'uflow',調用'underflow',如果這不會返回eof,它將取消引用get指針並返回那裏的字符。 – Cubbi