Что не так с моей реализацией overflow ()?

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

2

Решение

Первое, что не нужно делать, это то, что вы производите от 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 если ты чувствуешь удвоение, это не очень хорошая идея.
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]