سؤال

أحاول تنفيذ مخزن مؤقت للتيار وأواجه مشكلة في صنعه 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