質問

私はストリームバッファを実装しようとしています、そして私は作るのに苦労しています overflow() 仕事。バッファーをさらに10文字でサイズ変更し、使用してバッファーをリセットします setp. 。次に、中断した場所でポインターを戻します。何らかの理由で、出力は正しくありません:

template <class charT, class traits = std::char_traits<charT>>
class stringbuf : public std::basic_stringbuf<charT, traits>
{
public:
    using char_type   = charT;
    using traits_type = traits;
    using int_type    = typename traits::int_type;
public:
    stringbuf()
        : buffer(10, 0)
    {
        this->setp(&buffer.front(), &buffer.back());
    }

    int_type overflow(int_type c = traits::eof())
    {
        if (traits::eq_int_type(c, traits::eof()))
            return traits::not_eof(c);

        std::ptrdiff_t diff = this->pptr() - this->pbase();

        buffer.resize(buffer.size() + 10);
        this->setp(&buffer.front(), &buffer.back());

        this->pbump(diff);

        return traits::not_eof(traits::to_int_type(*this->pptr()));
    }
    // ...
    std::basic_string<charT> str()
    {
        return buffer;
    }
private:
    std::basic_string<charT> buffer;
};

int main()
{
    stringbuf<char> buf;
    std::ostream os(&buf);

    os << "hello world how are you?";
    std::cout << buf.str();
}

文字列を印刷すると、次のように表示されます。

こんにちはworlお元気ですか?

それはありません d そしてその y. 。私は何を間違えましたか?

役に立ちましたか?

解決

最初にそうでないことは、あなたが派生しているということです std::basic_stringbuf<char> 何らかの理由で、関連するすべての仮想関数を無効にしません。たとえば、オーバーライドしません xsputn() また sync(): :これらの機能が最終的に行うことになっても、継承します。ストリームバッファーを導き出すことを強くお勧めします std::basic_streambuf<char> 代わりは!

overflow() メソッドは、ストリームバッファーの文字列よりも小さい1文字のバッファーを発表します。 &buffer.back() 配列の最後へのポインターではなく、文字列の最後の文字へのポインターです。個人的には、私は使用します

this->setp(&this->buffer.front(), &this->buffer.front() + this->buffer.size());

これまでのところ問題はありません。ただし、より多くのキャラクターのためのスペースを作成した後、あふれる文字、すなわち、に渡された議論を省略したことを省略しました overflow() バッファーへ:

this->pbump(diff);
*this->pptr() = traits::to_char_type(c);
this->pbump(1);

まったく正しくないものがいくつかあります:

  1. 一般的に、オーバーライドを与えることは悪い考えです virtual デフォルトのパラメーターを機能します。基本クラスの関数は既にデフォルトを提供しており、新しいデフォルトは関数が明示的に呼ばれる場合にのみピックアップされます。
  2. 返された文字列には、バッファが正確に満たされない限り、これまでに書かれたシーケンスよりも実際に大きいため、最後に多くのヌル文字が含まれる場合があります。おそらく実装する必要があります str() 異なる機能:

    std::basic_string<charT> str() const
    {
        return this->buffer.substr(0, this->pptr() - this->pbase());
    }
    
  3. 文字列を一定の値だけで拡大することは、主要なパフォーマンスの問題です。執筆コスト n キャラクターはです n * n. 。大きい場合 n (彼らは本当に大きくなる必要はありません)これは問題を引き起こします。あなたはあなたを育てる方がはるかに良いです buffer 指数関数的に、たとえば、毎回それを2倍にするか、 1.5 倍増していると感じる場合は、良い考えではありません。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top