Вопрос

Я пытаюсь внедрить буфер потока, и у меня возникли проблемы с созданием 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();
}

Когда я печатаю строку, она выходит как:

Привет, как ты?

Не хватает d и y. Анкет Что я сделал не так?

Это было полезно?

Решение

Первое, чего не нужно, это то, что вы получаете std::basic_stringbuf<char> По какой -то причине, не переопределяя все соответствующие виртуальные функции. Например, вы не переопределяете xsputn() или же sync(): Что бы ни делали эти функции, вы унаследовали. Я настоятельно рекомендую вывести ваш буфер потока std::basic_streambuf<char> вместо!

А overflow() Метод объявляет буфер, который является одним символом, меньше, чем строка в буфере потока: &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 в геометрической прогрессии, например, удваивает его каждый раз или растут в 1.5 Если вы чувствуете, что удвоение - не очень хорошая идея.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top