• 0
Install

سؤال حول الإخراج Output في C++ باستخدام Cout

سؤال

السلام عليكم ورحمة الله .

 

هناك نقطة لم افهمها 

.

الــ endl يعمل Flushing للــ Buffer الخاص بالــ Stream

 

ما معنى هذا ؟؟ ومتى يحصل ولماذا ؟؟ ماهي عملية ال Flushing 

 

ال Buffer هو شيء ما يشبه مخزن مؤقت وال Stream هو كلاس بالنهاية وهو نفسه ال Cout صحيح ؟؟ 

 

وجزاكم الله خير

تم تعديل بواسطه مصطفى 36a2
add some tags
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

8 إجابة على هذا السؤال .

  • 0
مالم افهمه إلى الآن اخي العزيز هو مالفائدة من استخدام ال Buffer فمثلاً لو كتبت الثابت المحرفي النصي "HHHIIIIII" وقمت بتطباعته عن طريق الستريم Cout

لننسى قليلا موضوع كتابتك لنص و حرف و رقم و غيره من الأنواع و تعال لننظر للأمر بوجهة نظر مجرده من الدوال و الفئات.

 

لنفترض ان لديك ملف على جهاز الكمبيوتر و فتحته لتكتب فيه عملية الكتابه داخله من خلالك تتم حرف بحرف و كل حرف داخل سيتم حفظه داخل الملف فى وقته لأن البرنامج الذى تكتب من خلاله أقصى ما يستطيع التعامل معه هو حرف واحد.

لنفترض وجود 100 حرف مخزنين بالذاكره و قمت بإضافتهم دفعه واحده داخل ذلك المحرر، كل ما سيفعله هو الحصول على تلك الحروف واحد تلو الاخر يقوم برسمه على الشاشه ثم حفظه داخل الملف و هكذا.

 

عملية الحفظ داخل الملف على الهارد ديسك عملية مكلفه جدا - من حيث الوقت - و لهذا قد تجد البرنامج يتوقف عن العمل للحظات لوجود برنامج أخر يقوم بعملية اخرى داخل الهارد ديسك.

 

تخيل معى ان هذا المحرر قام بتوسعة المساحه التى يقوم بحفظ المحتويات بها إلى خمسة أحرف فى المره الواحده بدلا من حرف و احد لذا بعد كل خمسة أحرف تكتبها امامك على الشاشه سيقوم هو بإتمام عملية الحفظ مرة واحدة.

 

لنعود للغة الـ ++C.

 

الـ buffer الموجود داخل الـ stream يستخدم لحفظ القيم بشكل مؤقت قبل إرسالها دفعه واحده للمكان الذى تمثله هذه الـ stream و فى حالتنا هذه نحن نتكلم عن cout و التى هى عباره عن in-memory file و إسمها standard output.

 

عندما تقوم بالكتابة داخل cout فإنها تقوم بالكتالبة داخل الـ buffer و الذى يتم إرسال محتوياته إلى standard output و التى بدورها تكتبه داخل مكان جانبى تحسبا لحفظه.

 

عندما تقوم بإستدعاء الدالة flush الموجوده بالـ stream فأنت تعلم الـ standard output بأن كل ما تم كتابته لن يتم التعديل عليه و لن يتغير و بهذا انت تعطيها الامر بحفظ هذه المحتويات داخل الـ in-memory file و لهذا السبب نقوم بتفريغ محتويات الـ buffer.

 

لنفترض انك استطعت بعد فتره من الكتابة داخل cout بدون إستدعاء flush أو كتابة new-line بالتعديل على بعض المحتويات التى سبق كتابتها، ما سيحدث وقتها هو ان cout ستقوم بإرسال المساحه المعدله و بداية موقع التعديل للـ standard output.

 

لذا الخلاصه: cout تكتب فى مخزن مؤقت الذى يمكن تعديل محتوياته فى أى وقت و بعد التأكد من عدم تعديل هذه المحتويات يتم إرسالها للـ standard output و التى تتحفظ عليه بشكل دائم.

 

توجد بعض الملاحظات هنا:

1- الـ standard output فى أغلب انظمة التشغيل هى write-only stream و فى بعضهم لا يسمح لك بتعديل المحتويات التى كتبتها و فى أخرين يسمح لك (ويندوز يسمح بها).

2- قولي ان الـ standard output عبارة عن in-memory stream قد لا يكون صحيحا ففى العديد من أنظمة التشغيل هو عبارة Pipe stream.

 

طيب مافائدة حفظ الثابت المحرفي الأول في ال Buffer إذا كنت طبعته انا اي لن استخدمه مرة اخرى

لاحظ ان الامر مختلط عليك فى موضوع الكتابة و الطباعه فما يعرض على الشاشة امامك ليس بالضرورة تم حفظه بشكل نهائي فمثلا عندما تفتح برنامج محرر نصوص و تكتب فيه انت لاتراه قد انشأ ملف امامك و وضع فيه المحتويات و لكن عندما تعطيه الأمر بأن ما كتبت تريد حفظه حينها يحفظه.

 

الأمر مماثل مع أى stream فأنت تكتب داخلها العديد من الحروف و قد تظهر امامك - فى حالة cout مثلا- و لكن كتابتك داخلها لا يعنى ان ما كتبت لن يتم التعديل عليها أو انك ستحتفظ به، و لكن عندما تعطى الأمر flush فأنت تعنى ان ما كتبته سيحفظ.

 

هنا في الموقع الرسمي ل c++ يقولون ان ال endl سيقوم بعد استدعائه بعمل Flushing لل Buffer طيب هل عملية ال flushing تعني تفريغ البافر "او المخزن المؤقت " اليس كذلك اخي العزيز ؟؟؟

عملية الـ flush تعنى حفظ ما تم كتابته أولا ثم تفريغ المخزن المؤقت بعدها.

لاحظ انك عندما تتكلم عن cout فالأمر يختلف قليلا (و لهذا تجد ان تعريف cout هو extern بدلا من وجود الكود) لأن cout قد يوجد لها أكثر من مستوى للـ buffer على عكس الـ stream التى تتعامل مع ملف.

 

إن كنت تتسائل عن مستويات الـ buffer فهم قد يكونوا كالتالي: أولهم الموجود داخل ++C يليه الموجود داخل الـ C يليه الموجود داخل نظام التشغيل و بعدها الـ stream الفعليه.

 

المستوى الخاص بلغة الـ C يمكن تجاهله عن طريق إستخدام الكود التالي:

std::cout.sync_with_stdio(false)

و بهذا السطر سيتم إسقاط الـ buffer الخاص بلغة الـ C - و الذى يتم الوصول إليه بإستخدام دوال الملفات - و يصبح الإتصال مباشر بين المخزن الخاص بلغة ++C و مخزن نظام التشغيل، و فى هذه الحالة يصبح إستخدام endl أمر سئ لأنه سيقلل من اداء البرنامج و له اسباب يطول الكتابة فيها (إقراء الموضوع المشار إليه بإسم الدالة endl فى مشاركتى السابقه و ستجد الشرح به).

 

اخي العزيز ال endl تمت تسميتها في موقع c++ الرسمي بال Manipulator او المتلاعب ؟؟ 

هل يصح ان اسميها دالة ؟؟ ولماذا سميت بالمتلاعب Manipulator

هى دالة و لكن لأن لها تصميم محدد للتعامل مع الـ streams فقد تم إعطائها الإسم manipulator.

الأمر يشبه الفئات التى تعرف المعامل () و الذى تجعل كائنات الفئه يمكن التعامل معها كما يتم التعامل مع الدوال و لهذا يطلق عليها Function objects أو Functor.

 

 

و الله ولي التوفيق

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ال Buffering يستخدم لتقليل عمليات الكتابة لأقل مايمكن، فأغلب الوقت تكون Line Buffered أي عندما ترسل \n سيتم كتابة البيانات عند السطر الجديد، يمكن كذلك التحكم في نوعية ال Buffering بالحرف مثلا على سبيل المثال أو عند أنتهاء المساحة المتاحة
بالتوفيق
http://www.cplusplus.com/reference/cstdio/setvbuf/
 

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لم افهم كيف ان "ال Buffering يستخدم لتقليل عمليات الكتابة لأقل مايمكن" كيف ذلك ؟؟؟؟

 

 

فأغلب الوقت تكون Line Buffered أي عندما ترسل \n سيتم كتابة البيانات عند السطر الجديد

طيب يعني كل سطر جديد تتم كتابة محتوى ال Buffer ؟؟ طيب هل يتم عمل Flush له ام لا 

وولو كان الجواب لا مالفائدة من حفظ محتويات ال Buffer القديمة

يعني مثلاً لو كتبت انا اول سطر جملة ijjijijij ومن ثم ثاني سطر جملة nmnmnmnmn طيب مالفائدة ان ابقاء السطر الأول بال Buffer

شكرا على الرابط اخي العزيز , يبدوا انها دالة لضبط ال Buffer

وبخصوص كلامي هل صحيح ان ال Stream هو مجرد Object من كلاس برمجي ؟؟ صحيح ؟؟ 

ارجوا التفصيل اكثر بالموضوع ان امكن ولك جزيل الشكر اخي العزيز

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

Hello World\n

 

هل ستقوم بعملية كتابة لكل حرف هنا حوالي ١٢ عملية :D

 

أما إذا كان Line Buffered فستكون العملية الوحيدة عند ال \n

 

*cout هو object من ostream، معرف كالتالي

extern ostream cout;
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بما أنك ذكرت endl فسأتكلم حصريا عن الـ ++C

 

بادئ ذى بدء

ال Buffering يستخدم لتقليل عمليات الكتابة لأقل مايمكن، فأغلب الوقت تكون Line Buffered أي عندما ترسل \n سيتم كتابة البيانات عند السطر الجديد، يمكن كذلك التحكم في نوعية ال Buffering بالحرف مثلا على سبيل المثال أو عند أنتهاء المساحة المتاحة

هذا الكلام ينطبق فقط على لغة الـ C و عند التحدث عن الـ ++C فإما يوجد buffering أو لا يوجد.

 

الـ buffer فى لغة ++C يمثل بالفئه basic_streambuf و كل الأنواع التى قد تستخدم مخزن إحتياطى فى الذاكره لديها نسخه منه (ليس منه فعليا و لكن من فئه ورثته) فإذا كانت تحتاج لـ buffer فإنها تقوم بإستخدام الأجزاء التى تحتاجها منه و إن لم تريد فإنها لا تقوم بتضمين أى شئ.

 

الـ basic_streambuf تحتوى على العمليات الأساسية للكتابه او القراءة من buffer و توجد الفئه basic_streambuf التى تمثل buffer يستخدم مع أبناء basic_ios (سيتم ذكرهم بعد قليل) و توجد الفئه basic_stringbuf و التى تمثل buffer تنتج محتوياته كائن من النوع basic_string - و الذى نقوم بإستخدامه من خلال الفئه string و wstring.

 

الفئه basic_stringbuf تتيح لك إستخدام معامل الإدخال و الإخراج لتنظيم و تهيئة شكل محتويات النص و فى النهاية يمكنك الحصول على نسخه من الحتويات داخل basic_string تتلائم مع ذلك الـ basic_stringbuf. توجد 3 فئات يقوموا بإستخدم هذا الـ buffer و هم basic_istringstream  و basic_ostringstream و أخيرا الفئه basic_stringstream.

 

الفئه basic_streambuf تحتوى على نوعين من المؤشرات و هم مؤشرات للكتابة و مؤشرات للقراءه فالفئه basic_ostream - و التى تستخدمها عن طريق الكائنات cout و wcout و cerr و wcerr - تقوم بإستخدام مؤشرات الكتابة فقط و الفئه basic_istream - و التى تستخدمها عن طريق الكائنات cin و wcin - تقوم بإستخدام مؤشرات القراءة فقط و أحيانا لا تستخدم buffer على الإطلاق بناءا على نوع الـ stream التى تقرأ منها.

 

الفئات basic_ifstream و basic_ofstream و basic_fstream برثوا الفئات basic_istream و basic_ostream و basic_iostream على التوالي.

 

الـ endl هو دالة تقوم بكتابة سطر جديد داخل الـ basic_ostream و بعدها تقوم بإستدعاء flush لحفظ المحتويات و السبب فى ذلك السلوك يعود للطريقة المتبعه فى لغة الـ C حيث مع علامة السطر الجديد يتم حفظ المحتويات فعليا.

 

endl وظيفتها أكبر من مجرد كتابة علامة السطر الجديد حيث انها فى حالة الـ standard output\error\log تقوم بجعل المحتويات الخاصه بالـ basic_ostream و الـ FILE متقاربين فى المحتوى، راجع الملاحظات فى الرابط الخاص بالـ endl.

 

 

و الله ولي التوفيق

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا للاخوة الاكارم وخصوصاً الاخ السي بلس بلسي  :D

 

الأخ العزيز 

C++er  

 

 

 

الـ buffer فى لغة ++C يمثل بالفئه basic_streambuf و كل الأنواع التى قد تستخدم مخزن إحتياطى فى الذاكره لديها نسخه منه (ليس منه فعليا و لكن من فئه ورثته) فإذا كانت تحتاج لـ buffer فإنها تقوم بإستخدام الأجزاء التى تحتاجها منه و إن لم تريد فإنها لا تقوم بتضمين أى شئ.

مالم افهمه إلى الآن اخي العزيز هو مالفائدة من استخدام ال Buffer فمثلاً لو كتبت الثابت المحرفي النصي "HHHIIIIII" وقمت بتطباعته عن طريق الستريم Cout 

cout << "HHHIIIII";

ومن ثم قمت بطباعة ثابت محرفي آخر "XXXX" 

طيب مافائدة حفظ الثابت المحرفي الأول في ال Buffer إذا كنت طبعته انا اي لن استخدمه مرة اخرى 

ولو عملت /n بعد طباعة الثابت المحرفي الأول مالذي يحصل فقط طباعة سطر جديد صحيح ؟؟

طيب ولو استخدمت المتلاعب endl وطبعت سطر جديد بعد طباعة الثابت المحرفي الأول مالذي سوف يحصل ؟؟؟

هنا في الموقع الرسمي ل c++ يقولون ان ال endl سيقوم بعد استدعائه بعمل Flushing لل Buffer طيب هل عملية ال flushing تعني تفريغ البافر "او المخزن المؤقت " اليس كذلك اخي العزيز ؟؟؟

 

 

الـ endl هو دالة تقوم بكتابة سطر جديد

 

اخي العزيز ال endl تمت تسميتها في موقع c++ الرسمي بال Manipulator او المتلاعب ؟؟ 

هل يصح ان اسميها دالة ؟؟ ولماذا سميت بالمتلاعب Manipulator 

 

 

هذا ما احببت ان اسئل عنه بالضبط وشكرا لكل من جاوب على هذا الموضوع بارك الله فيكم اجمعين 

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بارك الله فيك وجزاك الله كل خير فصلًت اخي وافدت جزاكم الله خير 

سأقرأ الموضوع الذي تحدثت عنه 

جزاكم الله خير مرة اخرى

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

جزاك الله خير 

واسعدك دنيا واخرى

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .