Professional Documents
Culture Documents
C++ Primer, Fifth Edition ترجمتي (الفصل9 التاسع)
C++ Primer, Fifth Edition ترجمتي (الفصل9 التاسع)
9الحــــــــــاويــــــــــات الـمتســــــــــلســــــلة
Chapter 9. Sequential Containers
الـمحتويات
Contents
يتوسع هذا الفصل في موضوعات الفصل الثالث ويكمل مناقشتنا للحاويات املتسلسلة في املكتبة القياسية.
حيث ترتيب العنارص في الحاوية املتسلسلة يتوافق مع املواضع اليت يتم فيها إضافة عنارص إلى الحاوية. •
أيض ا عدة حاويات تجميعية ،تحتوي على عنارص يعتمد موضعها على مفتاح مرتبط بكل تعرف املكتبة ً
ّ •
عنرص.
سنغطي العمليات الخاصة بالحاويات التجميعية في الفصل الحادي عرش. •
تشرتك فئات الحاوية في واجهة مشرتكة ،واليت توسع كل حاوية بطريقتها الخاصة.
هذه الواجهة املشرتكة تجعل املكتبة أسهل في التعلم ؛ •
فما نتعلمه عن نوع من الحاويات سينطبق على نوع آخر. •
يقدم كل نوع من الحاويات مجموعة مختلفة من مقايضات األداء والدوال. •
تحتوي الحاوية على مجموعة من الكائنات من نوع محدد.
تسمح الحاويات املتسلسلة للمربمج بالتحكم في الرتتيب الذي يتم به تخزين العنارص والوصول إليها. •
هذا الرتتيب ال يعتمد على قيم العنارص ؛ بل يتوافق مع املوضع الذي يتم فيه وضع العنارص في الحاوية. •
على النقيض من ذلك ، •
بناء على قيمة مفتاح.
ً تخزن الحاويات التجميعية مرتبة وغري مرتبة – سنغطيها في الفصل – 11عنارصها •
أيضا ثالثة مكيفات للحاويات ،
توفر املكتبة ً •
يتكيف كل منها مع نوع الحاوية من خالل تعريف واجهة مختلفة لعمليات الحاوية. •
سنغطي املكيفات في ختام هذا الفصل. •
ملحوظة
يبين هذا الفصل على املواد املشمولة في الفصل الثاني والثالث والرابع .سنفرتض أنك على دراية بتلك املواد.
. 9٫1الحــــــــــاويات الـمتــــــــــسلسلة :نظــــــــــرة عــــــــامة
9.1 Overview of the Sequential Containers
Fixed-size array. Support fast random access. Can NOT add or
array
remove elements.
باستثناء املصفوفة ،واليت هي حاوية ذات حجم ثابت ،توفر الحاويات إدارة ذاكرة فعالة ومرنة.
يمكننا إضافة وإزالة العنارص ،وزيادة حجم الحاوية وتقليصها. •
فاالسرتاتيجيات اليت تستخدمها الحاويات لتخزين عنارصها لها تأثري متأصل – وأحيا ًنا مهم – على كفاءة •
تلك العمليات.
أيضا على ما إن كانت حاوية معينة توفر عملية معينة.
في بعض الحاالت ،تؤثر هذه االسرتاتيجيات ً •
فعلى سبيل املثال ،السلسلة واملتجه يحتفظان بعنارصهما في ذاكرة متجاورة. •
ونظرًا ألن العنارص متجاورة ،فمن السهل حوسبة عنوان العنرص من الفهرس الخاص به. •
ومع ذلك ،فإن إضافة عنارص أو إزالتها في منتصف إحدى هذه الحاويات يستغرق وق ًتا: •
يجب نقل جميع العنارص بعد إدراجها أو إزالتها للحفاظ على االتصال. •
عالوة على ذلك ،قد تتطلب إضافة عنرص في بعض األحيان تعيني مساحة تخزين إضافية. •
في هذه الحالة ،يجب نقل كل عنرص إلى التخزين الجديد. •
تم تصميم حاويات القائمة والقائمة_اﻷمامية لترسيع إضافة عنرص أو إزالته في أي مكان من الحاوية.
في املقابل ،ال تدعم هذه األنواع وصوال ً عشوائياً إلى العنارص: •
• ال يمكننا الوصول إلى عنرص إال من خالل مكرر عرب الحاوية.
• عالوة على ذلك ،غالبًا ما تكون سعة الذاكرة لهذه الحاويات كبرية – عند مقارنتها باملتجه والطابور
واملصفوفة.
الطابور عبارة عن بنية بيانات أكرث تعقي ًدا .يدعم مثل السلسلة واملتجه الوصول العشوائي الرسيع.
وكما هو حال السلسلة واملتجه ،فإن إضافة عنارص أو إزالتها في منتصفه عملية مكلفة (محتملة). •
مع ذلك ،فإن إضافة أو إزالة عنارص في أي من طرفيه تعد عملية رسيعة ،يمكن مقارنتها بإضافة عنرص •
إلى قائمة أو قائمة_أمامية.
ملحوظة
تلميح
عادة ،من األفضل استخدام املتجه ما لم يكن هناك سبب وجيه لتفضيل حاوية أخرى.
هناك بعض القواعد األساسية اليت تنطبق على اختيار الحاوية املراد استخدامها :
ما لم يكن لديك سبب الستخدام حاوية أخرى ،استخدم متجهاً. •
إن كان برنامجك يحتوي على الكثري من العنارص الصغرية واألمور املتعلقة باملساحة ، •
فال تستخدم القائمة أو القائمة_اﻷمامية. •
متجها أو الطابور.
ً عشوائيا إلى العنارص ،فاستخدم
ً إن كان الربنامج يتطلب وصوال ً •
إن احتاج الربنامج إلى إدراج عنارص أو حذفها في منتصف الحاوية ،فاستخدم قائمة أو قائمة_أمامية. •
إن احتاج الربنامج إلى إدراج عنارص أو حذفها في املقدمة والخلفية ،لكن ليس في املنتصف ،استخدم •
الطابور.
أما إن كان الربنامج يحتاج إلى إدراج عنارص في منتصف الحاوية فقط أثناء قراءة املدخالت ،وبالتالي يحتاج
وصوال ً عشوائياً إلى العنارص :
• أوال ً ،حدد ما إن كنت تحتاج بالفعل إلى إضافة عنارص في منتصف الحاوية.
غالبا سيكون من األسهل اإللحاق بمتجه ثم استدعاء دالة املكتبة فرز (سنغطيها في فقرة ، )10.2.3
ً •
وذلك إلعادة ترتيب الحاوية عند االنتهاء من املدخالت. •
إن كان ال بد من اإلدراج في املنتصف ،ففكر في استخدام قائمة ملرحلة املدخالت. •
وبمجرد اكتمال مرحلة املدخالت تلك ،انسخ تلك القائمة إلى متجه. •
ماذا لو كان الربنامج يحتاج وصوال ً عشوائياً ويحتاج إلى مدخالت وحذف عنارص في منتصف الحاوية؟
سيعتمد هذا القرار على التكلفة النسبية للوصول إلى العنارص في قائمة أو قائمة_أمامية … •
في مقابل تكلفة إدراج أو حذف عنارص في متجه أو طابور. •
لكن بشكل عام ،ستحدد العملية السائدة للتطبيق اختيار نوع الحاوية (سواء كان ذلك وصوال ً أكرث أو مزيداً •
من اإلدراج أو الحذف).
رضوريا.
ً في مثل تلك الحاالت ،يحتمل أن يكون اختبار األداء للتطبيق باستخدام كلتا الحاويتني •
أفضل املمارسات
إن لم تكن متأك ًدا من الحاوية اليت يجب استخدامها ، •
فاكتب كودك بحيث ال يستخدم إال عمليات مشرتكة بني كل من املتجهات والقوائم : •
استخدم املكرر ،وليس الفهارس ،وتجنب الوصول العشوائي إلى العنارص. •
بهذه الطريقة سيكون من السهل استخدام متجه أو قائمة حسب الرضورة. •
التمرين :9.1
-ما هو األنسب -متجه ،أم طابور ،أم قائمة -ملهام الربنامج التالية؟
-ارشح األساس املنطقي الختيارك.
-إن لم يكن هناك سبب لتفضيل حاوية أو أخرى ،فرس لم ال.
أبجديا عند مدخالتها.
ً (أ) قراءة عدد ثابت من الكلمات ،مع مدخالتها في الحاوية
-سرنى في الفصل التالي أن الحاويات التجميعية هي األنسب لهذه املشكلة.
(ب) قراءة عدد غري معروف من الكلمات.
-إدراج الكلمات الجديدة دوما يكون في الخلف .وإزالة القيمة التالية من األمام.
(ج) قراءة عدد غري معروف من أعداد صحيحة من ملف.
-فرز األرقام ثم طباعتها على املخرجات القياسية.
نظــــــــــرة عــــــــامة: مكتبــــــــة الحــــــــــاوية. 9٫2
9.2 Container Library Overview
Type Aliases
Construction
Size
Obtain Iterators
Constructor that take a size are valid for sequential containers only
(not including array)
.ال تزال بعض العمليات اﻷخرى شائعة في مجموعة فرعية أصغر من الحاويات •
. سنغطي الجوانب املشرتكة بني جميع الحاويات، في هذا القسم •
ثم يركز الجزء املتبقي من هذا الفصل فقط على الحاويات املتسلسلة ؛ •
بينما نغطي العمليات الخاصة بالحاويات التجميعية في الفصل الحادي عرش. •
بشكل عام ،يتم تعريف كل حاوية في ملف عنوان يحمل نفس اسم النوع.
هذا يعين أن الطابور موجود في العنوان طابور dequeوالقائمة في العنوان قائمة … listإلخ. •
الحاويات عبارة عن قوالب فئة . •
وكما هو الحال مع املتجهات ،يجب علينا توفري معلومات إضافية إلنشاء نوع حاوية محدد. •
بالنسبة ملعظم الحاويات ،وليس كلها فإن املعلومات اليت يجب أن نقدمها هي نوع العنرص: •
ملحوظة
قد تتطلب برامج الرتجمة األقدم مسافة بني قويس الزاوية ،مثالً .vector<vector<string< < :
بينما نصف عمليات الحاوية ،سنالحظ قيوداً إضافية ،إن وجدت ،تضعها كل عملية حاوية على نوع العنرص.
التمرين :9.2
عرف قائمة تحتوي على عنارص طابور تحمل .ints
ّ
ملحوظة
يتم اإلشارة إلى نطاق املكرر بزوج من املكررات يشري كل منهما إلى عنرص ،أو ما بعد آخر عنرص في نفس الحاوية.
يُشار إلى هذين املكررين ،غالباً باسم بداية_ ونهاية_ -أو (بشكل مضلل تقريباً) باألول واألخري - •
حيث يحددان نطاقاً من عنارص حاوية. •
تسمية األخري ،بالرغم من استخدامه بشكل شائع ،مضلل قليالً ، •
ألن املكرر الثاني ال يشري بداية_ إلى آخر عنرص في النطاق. •
بل يشري إلى نقطة تأتي بعد آخر عنرص. •
تشمل عنارص النطاق العنرص املشار إليه أوال ً وكل عنرص من أول النطاق إلى األخري دون أن يشمل األخري. •
يسمى نطاق العنرص هذا بالنطاق الشامل لليسار .الكود الريايض القيايس ملثل هذا النطاق هو •
تحذير
ال يستطيع املرتجم تنفيذ هذه املتطلبات .األمر مرتوك لنا للتأكد من أن برامجنا تتبعها.
تستخدم املكتبة النطاقات الشاملة لليسار ألن لها ثالث خصائص مالئمة.
فبافرتاض أن بداية_ونهاية_تدالن على نطاق مكرر صالح ،إذن •
إن كانت بداية_تساوي نهاية_ ،فإن النطاق فارغ •
إن كانت بداية_ال تساوي نهاية_ ،فهناك عنرص واحد على األقل في النطاق ،وتشري بداية_ألول عنرص فيه •
يمكننا أن نزايد بداية_عد ًدا من املرات حىت تتساوى بداية_مع نهاية_ •
هذه الخصائص تعين أنه يمكننا كتابة حلقات بأمان مثل ما يلي ملعالجة مجموعة من العنارص : •
التمرين :9.3
ما هي القيود املفروضة على املكررات اليت تشكل نطاقات املكرر؟
التمرين :9.4
زوجا من املكررات إلى متجه < >intوقيمة .int
ً -اكتب دالة تأخذ
-ابحث عن هذه القيمة في النطاق وقم بإعادة منطقي يشري إلى ما إن كان قد تم العثور عليه.
التمرين :9.5
-أعد كتابة الربنامج السابق إلعادة مكرر إلى العنرص املطلوب.
-الحظ أن الربنامج يجب أن يتعامل مع الحالة اليت ال يوجد فيها العنرص.
تمرين :9.6
ما هو الخطأ في الربنامج التالي؟ كيف يمكنك تصحيح ذلك؟
;list<int> lst1
;)(list<int>::iterator iter1 = lst1.begin(), iter2 = lst1.end
while (iter1 < iter2) /* ... */
تستخدم هذه اإلعالنات عامل النطاق لتخرب بأننا نريد عضو املكرر لفئة قائمة<سلسلة> و •
املعرف بواسطة متجه < ، >intعلى التوالي. ّ difference_type
قسم التدريبات 9.2.2
تمرين :9.7
ما هو النوع الذي يجب استخدامه كمؤرش في متجه ints؟
التمرين :9.8
ما النوع الذي يجب استخدامه لقراءة العنارص املوجودة في قائمة السالسل؟ ولكتابتها؟
ينتج عن عملييت بداية_ونهاية_ مكرران يشريان ﻷول عنرص وآخر عنرص في الحاوية.
غالباً ما يستخدم هذان املكرران لتشكيل نطاق مكرر يشمل كل العنارص املوجودة في الحاوية. •
وكما هو مبني في الجدول ، 9.2هناك العديد من اإلصدارات من بداية_ ونهاية_ : •
فاإلصدارات اليت تحتوي على rتعترب مكررات عكسية (سنغطيها في فقرة .)10.4.3 •
أما تلك اليت تبدأ بحرف cفتعيد اإلصدار الثابت للمكرر ذي الصلة: •
الدوال اليت ال تبدأ بحرف cتعترب زائدة التعبئة .هذا يعين أنه يوجد في الواقع عضوان باسم "بداية_".
أحدهما عضو ثابت يقوم بإعادة نوع مكرر حاوية ثابت. •
أما اآلخر فغري ثابت ويعيد نوع مكرر حاوية. •
واألمر نفسه بالنسبة لـ rbeginو endو .rend •
مكررا.
ً عندما نستدعي إحدى تلك األعضاء على كائن غري ثابت ،نحصل على اإلصدار الذي يعيد •
وﻻ نحصل على نسخة ثابتة من املكررات إﻻ عندما نستدعي هذه الدوال على كائن ثابت. •
وكما هو حال املؤرشات واملراجع لثابت ،يمكننا تحويل مكرر عادي إلى الثابت املقابل ،لكن ليس العكس. •
تم تقديم إصدارات cبواسطة املعيار الجديد لدعم استخدام النوع التلقائي مع بداية_ ونهاية_ .auto
ففي املايض ،لم يكن لدينا خيار سوى تعريف نوع املكرر الذي نريده: •
عندما نستخدم autoمع بداية_ أو نهاية_ ،سيعتمد نوع املكرر الذي نحصل عليه على نوع الحاوية. •
أما كيف نعزتم استخدام ذلك املكرر فغري ذي صلة. •
تتيح لنا إصدارات cالحصول على مكرر_ثابت برصف النظر عن نوع الحاوية. •
أفضل املمارسات
عندما ال تكون هناك حاجة إلى حق الوصول للكتابة ،استخدم بداية_ث cbeginونهاية_ث .cend
تمرين :9.9
-ما هو الفرق بني داليت beginو cbegin؟
تمرين :9.10
-ما هي أنواع الكائنات األربعة التالية؟
;vector<int> v1
;const vector<int> v2
;)(auto it1 = v1.begin(), it2 = v2.begin
;)(auto it3 = v1.cbegin(), it4 = v2.cbegin
// each container has three elements, initialized from given initializers
;}"list<string> authors = {"Milton", "Shakespeare", "Austen
;}"vector<const char*> articles = {"a", "an", "the
list<string> list2(authors); // ok: types match
deque<string> authList(authors); // error: container types don't match
vector<string> words(articles); // error: element types must match
// ok: converts const char* elements to string
;))(forward_list<string> words(articles.begin(), articles.end
ملحوظة
عند تهيئة حاوية كنسخة من حاوية أخرى ،يجب أن يتطابق نوع الحاوية ونوع العنرص في كلتا الحاويتني.
امل ُنشئة اليت تأخذ مكررين تستخدمهما لتشري إلى مجموعة العنارص اليت نريد نسخها. •
كالعادة ،يقوم املكرران بتعريف أول وآخر عنرص من املراد نسخه. •
الحاوية الجديدة ستملك نفس حجم عدد العنارص في النطاق. •
وستتم تهيئة كل عنرص في الحاوية الجديدة على قيمة العنرص املقابل في النطاق. •
ونظرًا ألن املكررات تشري إلى نطاق ،يمكننا استخدام هذه املُنشئة لنسخ نتيجة الحقة للحاوية.
على سبيل املثال ،بافرتاض أن itمكرر يشري إلى عنرص في املؤلفني ، authorsيمكننا كتابة •
// each container has three elements, initialized from given initializers
;}"list<string> authors = {"Milton", "Shakespeare", "Austen
;}"vector<const char*> articles = {"a", "an", "the
عندما نفعل ذلك ،نحدد رصاحة قيمة لكل عنرص في الحاوية. •
أيضا حجم الحاوية بشكل ضمين:
بالنسبة ألنواع أخرى غري املصفوفة ،تحدد تهيئة القائمة ً •
ستحتوي الحاوية على عدد عنارص بنفس عدد املُهئي. •
يمكننا استخدام ُمنشئة تأخذ وسيطة حجم إن كان نوع العنرص مدمجاً أو فئة لها ُمنشئة افرتاضية. •
أما إن كان نوع العنرص ال يملك ُمنشئة افرتاضية ،فيجب تعريف ُمهئي عنرص واضح مع الحجم. •
ملحوظة
املُنشئات اليت تأخذ حجماً تعد صالحة فقط للحاويات املتسلسلة ؛ لن يتم دعمها في الحاويات التجميعية.
Library arrays Have Fixed Size مصفوفات املكتبة حجمها ثابت
وألن الحجم جزء من نوع املصفوفة ،فإنها ال تدعم منشئات الحاوية العادية. •
تعرف تلك املنشئات ،ضمناً أو رصاحة ،حجم الحاوية.
ّ •
سيكون ذلك التعريف زائداً عن الحاجة (بأحسن األحوال) وعرضة للخطأ ، •
• بسبب السماح للمستخدمني بتمرير وسيطة حجم إلى ُمنشئة مصفوفة.
تعرفها املصفوفة.
أيضا على سلوك املنشئات اليت ّ
تؤثر طبيعة املصفوفات ذات الحجم الثابت ً
لكن على عكس الحاويات األخرى ،فإن املصفوفة اليت لها ُمنشئة افرتاضية ليست فارغة : •
فهي تحتوي على عدد عنارص بنفس حجمها. •
تماما مثل العنارص في املصفوفة املدمجة.
ً هذه العنارص ستكون مهيأة افرتاضياً •
إن هيئنا املصفوفة تهيئة قائمة ،فيجب أن يكون عدد املهيئات مساوياً لحجم املصفوفة أو أقل. •
فإن كان هناك عدد املهيئات أقل من حجم املصفوفة ، •
سيتم استخدام املُهيئات للعنارص األولى وسيتم تهيئة أية عنارص متبقية. •
في كال الحالتني ،إن كان نوع العنرص نوع فئة ،يجب أن يكون للفئة ُمنشئة افرتاضية تسمح بتهيئة قيمة: •
تجدر اإلشارة إلى بالرغم من أننا ال نستطيع نسخ أو تعيني كائنات أنواع املصفوفات املدمجة ،فال يوجد •
مثل هذا التقييد على املصفوفة :
كما هو الحال مع أي حاوية ،يجب أن يكون للمهئي نفس نوع الحاوية اليت نقوم بإنشائها. •
بالنسبة إلى املصفوفات ،يجب أن يكون نوع العنرص والحجم متماثلني ، •
ذلك ألن حجم املصفوفة جزء من نوعها. •
التمرين :9.11
-اعرض مثاال ً لكل طريقة من الطرق الست إلنشاء متجه وتهيئته.
-ارشح القيم اليت يحتوي عليها كل متجه.
التمرين :9.12
-ارشح االختالفات بني منشئة تأخذ حاوية لنسخها ومنشئة تأخذ مكررين.
التمرين :9.13
-كيف تقوم بتهيئة املتجه < >doubleمن قائمة <>int؟ من متجه <>int؟
-اكتب الكود للتحقق من إجاباتك.
تعمل العامالت ذات الصلة بالتعيني ،املدرجة في الجدول ( 9.4أدناه) على الحاوية بأكملها.
يستبدل عامل التعيني النطاق الكامل للعنارص في الحاوية اليرسى بنسخ من عنارص املعامل األيمن: •
تحذير
تؤدي العمليات املرتبطة بالتعيني إلى إبطال املكررات واملراجع واملؤرشات في الحاوية اليرسى
. وباستثناء املصفوفات يتم تبديل الحاويات اليت تشري إليها. ستظل صالحة بعد املبادلة، ما عدا السلسلة
list<string> names;
vector<const char*> oldstyle;
names = oldstyle; // error: container types don't match
// ok: can convert from const char*to string
;))(names.assign(oldstyle.cbegin(), oldstyle.cend
يستبدل استدعاء assignالعنارص في أسماء بنُسخ من العنارص في النطاق املشار إليه باملكررات. •
تحدد وسيطات assignعدد العنارص والقيم اليت ستحتوي عليها الحاوية. •
تحذير
تقوم عملية املبادلة بتبادل محتويات حاويتني من نفس النوع .بعد استدعاء مبادلة ،يتم مبادلة العنارص في
الحاويتني :
بعد املبادلة ،يحتوي svec1على 24عنرص سلسلة بينما سيحتوي svec2على عرشة. •
باستثناء املصفوفات ،فإن مبادلة حاويتني تضمن املكتبة رسعته ؛ •
إذ ﻻ يتم تبديل العنارص نفسها ؛ بل يتم تبديل هياكل البيانات الداخلية. •
ملحوظة
باستثناء املصفوفة ،ال تنسخ مبادلة أو تحذف أو تدرج أية عنارص وهي مضمونة العمل في وقت ثابت.
حقيقة عدم تحريك العنارص تعين أنه – وباستثناء السلسلة – لن يتم إبطال مكرر أو مراجع أو مؤرش في الحاويات.
بل ستشري إلى نفس العنارص كما كانت قبل املبادلة. •
ومع ذلك ستكون تلك العنارص بعد املبادلة في حاوية مختلفة. •
فمثالً ،إن كانت iterتشري إلى سلسلة في الفهرس ] svec1[3قبل املبادلة ، •
فستشري إلى العنرص في الفهرس ] svec2[3بعد املبادلة. •
وبشكل مختلف عن الحاويات ،قد تؤدي مبادلة على سلسلة إلى إبطال مكررات ومراجع ومؤرشات. •
وعلى عكس الطريقة اليت تترصف بها مبادلة مع الحاويات األخرى ، •
فإن مبادلة مصفوفتني سيؤدي إلى تبادل العنارص. •
نتيجة لذلك ،يتطلب مبادلة مصفوفتني وق ًتا يتناسب مع عدد العنارص في املصفوفة. •
بعد مبادلة ،ستظل املؤرشات واملراجع واملكررات مرتبطة بنفس العنرص الذي تشري إليه قبل التبادل. •
بالطبع ،تم تبادل قيمة ذلك العنرص بالعنرص املقابل في املصفوفة األخرى. •
في املكتبة الجديدة ،تقدم الحاويات إصداري مبادلة لألعضاء وغري األعضاء.
عرفت اإلصدارات السابقة للمكتبة إصدار العضو من املبادلة فقط.
ّ •
تعترب مبادلة لغري األعضاء ذات أهمية قصوى في الربامج الشاملة. •
ولكن كعادة ،من األفضل استخدام نسخة مبادلة لغري األعضاء. •
التمرين :9.14
برنامجا لتعيني العنارص من قائمة مؤرشات charإلى سالسل أحرف نمط Cإلى متجه من السالسل.
ً -اكتب
باستثناء واحد ،تحتوي أنواع الحاويات على ثالث عمليات تتعلق بالحجم.
يعيد العضو حجم sizeعدد العنارص املوجودة في الحاوية ؛ •
ويعيد العضو فارغ emptyقيمة منطقية صحيحة إن كان الحجم صفرًا وخطأ بخالف ذلك ؛ •
بينما يعيد العضو حجم_أقىص max_sizeعد ًدا أكرب من أو يساوي عنارص قد تحتويها حاوية ذلك النوع. •
ألسباب سنرشحها في القسم التالي ،توفر القائمة_اﻷمامية الحجم األقىص والفارغ ،لكن ليس الحجم. •
ملحوظة
ال يمكننا استخدام عامل عالئقي ملقارنة حاويتني إال إن تم تعريف عامل املقارنة املناسب لنوع العنرص.
تستخدم عوامل تساوي الحاوية عامل == عنرصها ،وتستخدم العوامل العالئقية عامل > عنرصها.
فإن كان نوع العنرص ال يدعم العامل املطلوب ،فال يمكننا استخدام العمليات املقابلة في حاويات تحتوي •
على ذلك النوع.
عرفناه في الفصل 7ﻻ عملية == وﻻ > . يعرف نوع بيانات_املبيعات الذي ّ
مثالً ،ال ّ •
لذلك ،ال يمكننا مقارنة حاويتني تحتويان عنارص بيانات_مبيعات : •
التمرين :9.15
برنامجا لتعريف ما إن كان متجهان من نوع < int> sمتساويني.
ً اكتب
التمرين :9.16
كرر الربنامج السابق ،لكن قارن العنارص املوجودة في قائمة < >intبمتجه <.>int
التمرين :9.17
-بافرتاض أن c1و c2حاويتان ،
-ما هي القيود (إن وجدت) اليت يضعها االستخدام التالي على نوعي c1و c2؟
)if (c1 < c2
. 9٫3عمليــــــــات الحــــــــــاويات الـمتــــــــــسلــــــسلة
9.3 Sequential Container Operations
تغري هذه العمليات من حجم الحاوية وبالتالي ﻻ تدعمها مصفوفات املكتبة •
تحذير
يحتمل أن تؤدي إضافة عنارص إلى متجه أو سلسلة أو طابور إلى إبطال مكررات ومراجع ومؤرشات في الحاوية •
عندما نستخدم هذه العمليات ،يجب أن نتذكر أن الحاويات تستخدم اسرتاتيجيات مختلفة لتخصيص •
العنارص وأن هذه االسرتاتيجيات تؤثر على األداء.
تتطلب إضافة عنارص في أي مكان نقل عنارص إﻻ في نهاية_ متجه أو سلسلة ،أو في أي مكان ما عدا •
مقدمة أو خلفية طابور .
عالوة على ذلك ،قد تؤدي إضافة عنارص إلى متجه أو سلسلة إلى إعادة تخصيص الكائن بأكمله. •
تتطلب إعادة تخصيص كائن ما تخصيص ذاكرة جديدة ونقل العنارص من املساحة القديمة إلى الجديدة. •
// read from standard input, putting each word onto the end of container
;string word
)while (cin >> word
;) container.push_back(word
يؤدي استدعاء دفع_للخلف إلى إنشاء عنرص جديد في آخر الحاوية ، •
ما يؤدي إلى زيادة في حجم الحاوية مقدارها .1 •
قيمة هذا العنرص هي نسخة من الكلمة. •
ويمكن أن يكون نوع الحاوية أياً من قائمة ،أو متجه ،أو طابور. •
ونظر ًا ألن السلسلة حاوية من األحرف ،فيمكننا استخدام دفع_للخلف إلضافة أحرف إلى آخر السلسلة : •
عنارص الحاوية عبارة عن نسخ Container Elements Are Copies مفهوم رئييس :
عندما نستخدم كائنًا لتهيئة حاوية ،أو إدراج كائن في حاوية ، •
يتم وضع نسخة من قيمة هذا الكائن في الحاوية ،وليس الكائن نفسه. •
مثلما نقوم بتمرير كائن إلى معامل غري مرجعي ، •
ال توجد عالقة بني العنرص في الحاوية والكائن الذي نشأت منه تلك القيمة. •
لن تؤثر التغيريات الالحقة على العنرص في الحاوية على الكائن األصلي ،والعكس صحيح. •
إضافة إلى دفع_للخلف ،تدعم حاويات القائمة والقائمة_اﻷمامية والطابور عملية مماثلة تسمى دفع_للمقدمة.
تُدخل هذه العملية عنرصًا جدي ًدا في مقدمة الحاوية : •
;list<int> ilist
// add elements to the start of ilist
)for (size_t ix = 0; ix != 4; ++ix
;) ilist.push_front(ix
توفر عمليتا دفع_للخلف و دفع_للمقدمة طر ًقا مالئمة إلدراج عنرص واحد في آخر أو مقدمة الحاوية املتسلسلة.
بشكل عام ،تسمح لنا العنارص املدرجة بإدراج صفر أو أكرث من العنارص في أي نقطة في الحاوية. •
يتم دعم أعضاء اإلدراج للمتجه و طابور والقائمة والسلسلة. •
نسخا متخصصة من هذه األعضاء سنغطيها في الفقرة .9.3.4
ً تقدم القائمة_اﻷمامية •
كررا كوسيطة أولى لها.
تأخذ كل دالة من الدوال إدراج ُ insertم ً
يشري املكرر إلى مكان وضع العنرص (العنارص) في الحاوية. •
يمكن أن يشري إلى أي موضع في الحاوية ،بما في ذلك واحد بعد آخر الحاوية. •
ونظرًا ألن املكرر قد يشري إلى عنرص غري موجود من نهاية_الحاوية ، •
وألنه من املفيد أن يكون لديك طريقة إلدراج العنارص في بداية_الحاوية ، •
يتم إدراج العنرص (العنارص) قبل املوضع الذي يشري إليه املكرر. •
على سبيل املثال ،هذه الجملة
تدرج سلسلة ذات قيمة " "Helloقبل العنرص الذي يشري إليه iterمبارش ًة. •
بالرغم من أن بعض الحاويات ال تحتوي على عملية دفع_للمقدمة ، •
فال توجد قيود مماثلة على إدراج. •
يمكننا إدراج عنارص في مقدمة الحاوية دون القلق بشأن ما إن كانت الحاوية بها دفع_للمقدمة أم ال : •
تحذير
من الرشعي اﻹدراج من أي مكان في متجه أو طابور أو سلسلة .مع ذلك ،فالقيام بذلك قد يكون عملية مكلفة.
تتشابه وسيطات إدراج واليت تظهر بعد وسيطة املكرر األولية مع ُمنشئة الحاوية اليت تأخذ نفس املعلمات.
اإلصدار الذي يأخذ عدد العنارص والقيمة يضيف عد ًدا محدداً من العنارص املتطابقة قبل املوضع املحدد : •
يقوم هذا الكود بإدراج عرشة عنارص في آخر svecويقوم بتهيئة كل عنرص منها على سلسلة "."Anna •
تُدرج إصدارات إدراج اليت تأخذ زوج مكررات أو قائمة ُمهئي العنارص من النطاق املحدد قبل املوضع املحدد: •
;}"vector<string> v = {"quasi", "simba", "frollo", "scar
// insert the last two elements of v at the beginning of slist
;))(slist.insert(slist.begin(), v.end() - 2, v.end
slist.insert(slist.end(), {"these", "words", "will","go", "at", "the",
;)}""end
// run-time error: iterators denoting the range to copy from
// must not refer to the same container as the one we are changing
;))(slist.insert(slist.begin(), slist.begin(), slist.end
عندما نمرر زوج مكررات ،قد ال يشري املكرران إلى نفس الحاوية كتلك اليت نضيف إليها العنارص. •
مكررا ﻷول عنرص تم إدراجه.
ً بموجب املعيار الجديد ،فإن إصدارات إدراج اليت تأخذ عد ًدا أو نطا ًقا ستعيد •
(في اإلصدارات السابقة للمكتبة ،كانت هذه العمليات تعيد باطالً). •
فارغا ،فلن يتم إدراج أي عنارص ،وتقوم العملية بإعادة املعلمة األولى.
ً إن كان النطاق •
يمكننا استخدام القيمة املعادة بواسطة insertإلدراج العنارص بشكل متكرر في موضع محدد من الحاوية :
;list<string> 1st
;)(auto iter = 1st.begin
)while (cin >> word
iter = 1st.insert(iter, word); // same as calling push_front
ملحوظة
من املهم أن نفهم كيف تعمل هذه الحلقة -تحديداً ،لفهم سبب تكافؤ الحلقة مع استدعاء دفع_للمقدمةي.
استدعاء غرس_للخلف واستدعاء دفع_للخلف الثاني كالهما ينشئان كائنات بيانات_مبيعات جديدة. •
في استدعاء غرس_للخلف ،يتم إنشاء هذا الكائن مبارشة في مساحة تديرها الحاوية. •
محليا يتم دفعه إلى الحاوية.
ً يُنئش استدعاء دفع_للخلف كائنًا مؤق ًتا •
تختلف وسيطات دالة غرس اعتما ًدا على نوع العنرص. •
ويجب أن تتطابق تلك الوسيطات مع ُمنشئة من نوع العنرص: •
ملحوظة
تقوم دوال غرس بإنشاء عنارص في الحاوية .يجب أن تتطابق وسيطات هذه الدوال مع ُمنشئة لنوع العنرص.
التمرين :9.18
برنامج ا لقراءة سلسلة من السالسل من املدخالت القياسية في طابور.
ً -اكتب
-استخدم املكررات لكتابة حلقة لطباعة العنارص في طابور.
التمرين :9.19
-أعد كتابة الربنامج من التمرين السابق الستخدام قائمة.
-ضع قائمة بالتغيريات اليت احتجت إلى إجرائها.
التمرين :9.20
برنامجا لنسخ العنارص من قائمة < >intإلى اثنني من طابور.s
ً -اكتب
-يجب أن تدخل العنارص ذات القيمة الزوجية في جزء واحد والعنارص الفردية في اآلخر.
التمرين :9.21
-ارشح كيف ستعمل الحلقة من الصفحة 345اليت استخدمت اإلعادة من املدخالت إلضافة عنارص إلى القائمة إن
قمنا بإدراجها في متجه بدال ً من ذلك.
التمرين :9.22
-بافرتاض أن ivمتجه لـ ، ints
-فما الخطأ في الربنامج التالي؟ كيف يمكنك تصحيح املشكلة (املشاكل)؟
يرسد الجدول 9.6العمليات اليت يمكننا استخدامها للوصول إلى العنارص في حاوية متسلسلة.
معرفة إن كانت الحاوية فارغة وﻻ تحتوي على عنارص.
تكون عمليات الوصول غري ّ
عوامل atو subscriptصالحة فقط للسلسلة واملتجه والطابور واملصفوفة ؛ بينما تعد backغري صالحة للقائمة_اﻷمامية
يعد استدعاء frontأو backعلى أي حاوية فارغة خطأ برمجياً فادحاً كاستخدام فهرسة خارج النطاق
كل حاوية متسلسلة ،بما في ذلك املصفوفة ،تملك العضو مقدمة_ ، front •
وكلها باستثناء القائمة_اﻷمامية تملك العضو خلف_ .back •
مرجعا ألول وآخر عنرص ،على التوالي:
ً ستعيد تلك العمليات •
يحصل هذا الربنامج على مراجع ألول وآخر عنرص في cبطريقتني مختلفتني. •
النهج املبارش هو استدعاء مقدمة_ أو خلف_. •
أما بالشكل غري املبارش ،فيمكننا الحصول على مرجع لنفس العنرص عن طريق إلغاء مرجع إلى مكرر معاد •
من بداية_ أو التناقص ثم إلغاء املرجع عن املكرر املعاد من نهاية_.
هناك شيئان جديران باملالحظة في هذا الربنامج: •
أن مكرر نهاية_ يشري إلى عنرص (غري موجود) بعد آخر الحاوية. •
لجلب آخر عنرص ،فيجب علينا أوال ً مناقصة ذلك املكرر. •
النقطة املهمة األخرى هي أنه قبل استدعاء مقدمة_ أو خلف_ (أو إلغاء مرجع عن مكرري بداية_أو نهاية_) ، •
نتحقق أن cليست فارغة.
معرفة.
فإن كانت الحاوية فارغة ،فإن العمليات داخل ifستكون غري ّ •
The Access Members Return References أعضاء الوصول لعضو تعيد مراجع
األعضاء اليت تصل لعنارص في حاوية (مثالً ،مقدمة_ وخلف_ وفهرسة و )atستعيد مراجع.
فإن كانت الحاوية كائناً ثابتاً ،فإن اإلعادة ستكون مرجعاً لثابت. •
إن لم تكن الحاوية ثابتة ،فإن اإلعادة ستكون مرجعاً عادياً يمكن استخدامه لتغيري قيمة عنرص تم جلبه : •
{ ))(if (!c.empty
; c.front() = 42 // assigns 42 to the first element in c
;)( auto &v = c.back // get a reference to the last element
; v = 1024 // changes the element in c
;)( auto v2 = c.back )(// v2 is not a reference; it's a copy of c.back
; v2 = 0 // no change to the element in c
}
كالعادة ،إن استخدمنا autoلتخزين عائد من إحدى هذه الدوال وأردنا استخدام ذلك املتغري لتغيري •
نعرف متغرينا الخاص كنوع مرجعي.العنرص ،يجب أن نتذكر أن ّ
التمرين :9.23
-في الربنامج األول في هذا القسم في الصفحة ، 346ما هي قيم valو val2و val3و val4
-إن كان () c.sizeيساوي 1؟
التمرين :9.24
برنامجا يقوم بجلب أول عنرص في متجه باستخدام ، atعامل الفهرس ،مقدمة_ ،وبداية_.
ً -اكتب
-اخترب برنامجك على متجه فارغ.
محو عنارص من الطابور من غري مقدمته أو نهايته سيبطل جميع مكرراته ومراجعه ومؤرشاته. •
وستكون كل مكررات ومراجع ومؤرشات عنارص املتجه أو السلسلة باطلة من بعد نقطة املحو. •
تحذير
األعضاء اليت تمحو عنارص ال تفحص (وسيطاتها) .يجب على املربمج التأكد من وجود عنـ(ـا)رص قبل محوها.
تعمل الدالتان طرد_مقدمة pop_frontوطرد_خلف pop_backعلى إزالة أول وآخر عنرصين على التوالي.
أيضا طرد_مقدمة لديهما.
ومثلما ال توجد عملية دفع_للمقدمة لدى املتجه والسلسلة ،كذلك ال يوجد ً •
وباملثل ،لن يكون لدى القائمة_اﻷمامية طرد_خلف. •
مثل أعضاء الوصول لعنرص ،ﻻ يسمح باستخدام عملية طرد على الحاوية الفارغة. •
هذه العمليات تعيد فراغ .voidفإن كنت بحاجة إلى القيمة اليت توشك على طردها ،فيجب عليك تخزين •
تلك القيمة قبل القيام بالطرد :
{ ))(while (!ilist.empty
process(ilist.front()); // do something with the current top of ilist
ilist.pop_front(); // done; remove the first element
}
يشري املكرر elem1إلى أول عنرص نريد محوه ،ويشري elem2إلى آخر عنرص نريد إزالته. •
لحذف كل عنارص الحاوية ،يمكننا إما استدعاء clearأو تمرير املكررين بداية_ ونهاية_ إلى : erase •
التمرين :9.25
-في الربنامج املوجود في الصفحة 349والذي قام بمسح مجموعة من العنارص ،
ماذا يحدث إن تساوى elem1و elem2؟
ماذا لو كان elem2أو كال من elem1و elem2هو مكرر ما بعد النهاية؟
التمرين :9.26
-باستخدام التعريف التالي لـ ، iaانسخ iaإلى متجه وفي قائمة.
-استخدم صيغة املحو أحادية املكرر إلزالة العنارص ذات القيم الفردية من قائمتك والقيم الزوجية من املتجه.
لفهم سبب وجود إصدارات خاصة لعمليات القائمة_اﻷمامية إلضافة العنارص وإزالتها ،
فكر في ما ينبغي أن يحدث عندما نزيل عنرصًا من تسلسل مرتابط بشكل حر وفردي. •
فكما هو موضح في الشكل ، 9.1تؤدي إزالة عنرص إلى تغيري روابط ذلك التسلسل. •
في هذه الحالة ،إزالة التغيريات elem3 elem2؛ •
كان elem2قد أشار إلى ، elem3ولكن بعد إزالة ، elem3يشري elem2إلى .elem4 •
عندما نضيف عنرصًا أو نزيله ،سيختلف وريث ما قبل العنرص الذي أضفناه أو أزلناه. •
إلضافة عنرص أو إزالته ،سنحتاج إلى الوصول إلى العنرص السابق من أجل تحديث روابط هذا العنرص. •
ومع ذلك ،ترتابط القائمة_اﻷمامية بشكل حر ومنفرد. •
وفي قائمة ترتابط بشكل فردي ،ال توجد طريقة سهلة للوصول إلى عنرص سابق. •
لذلك ،تعمل عمليات إضافة عنارص أو إزالتها في القائمة_األمامية على تغيري ما بعد العنرص املحدد. •
وبهذه الطريقة ،سنتمكن دوماً من الوصول إلى العنارص املتأثرة بالتغيري. •
ونظرًا ألن هذه العمليات تترصف بشكل مختلف عن عمليات الحاويات األخرى ، •
فإن القائمة_اﻷمامية ال تعرِّف اإلدراج insertوﻻ الغرس emplaceوﻻ املسح .erase •
أعضاء (مدرجة في الجدول )9.8تسمى اإلدراج_بعد insert_afterوالغرس_بعد
ً تعرف
بل ّ •
emplace_afterواملسح_بعد .erase_after
فمثالً ،في رسمنا التوضيحي ،إلزالة ، elem3سنستدعي الـمسح_بعد على مكرر يشري إلى .elem2 •
.مكررا ملا قبل البدء
ً وتعيد، before_begin تعرف القائمة_اﻷمامية قبل_بداية
ّ ، ولدعم تلك العمليات •
.يتيح لنا هذا املكرر إضافة أو إزالة عنارص "بعد" عنرص غري موجود قبل أول عنرص في القائمة •
هنا ،يشري Currإلى العنرص الذي نتحقق منه ،ويشري prevإلى عنرص ما قبل البدء. •
نستدعي بداية_ لتهيئتها على ، currبحيث يتحقق أول تكرار ما إن كان أول عنرص زوجياً أم فردياً. •
مكررا إلى عنرص غري موجود قبل .curr
ً نقوم بتهيئة prevعلى قبل_بداية ،والذي يعيد •
فرديا ،نمرر prevإلى عملية املسح_بعد .erase_after ً عندما نجد عنرصًا •
هذا االستدعاء يمحو ما بعد العنرص املشار إليه بـ prev؛ أي أنه يمحو العنرص الذي يشري إليه .curr •
نعيد تعيني currعلى العائد من املسح_بعد ، •
ما يجعل currيشري إلى العنرص التالي في التسلسل ويرتكه دون تغيري ؛ •
سيظل prevيشري إلى العنرص قبل القيمة (الجديدة) لـ .curr •
إن لم يكن العنرص الذي يُشار إليه بواسطة currفردياً ،فيجب علينا تحريك كال املكررين ،وهو ما نقوم •
به في اآلخر.
التمرين :9.27
برنامج ا للبحث عن العنارص ذات القيمة الفردية وإزالتها في قائمة_أمامية <.>int
ً -اكتب
التمرين :9.28
-اكتب دالة تأخذ قائمة_أمامية <سلسلة> ووسيطتني إضافيتني من وسيطات السلسلة.
-يجب أن تجد الدالة السلسلة األولى وتدخل الثانية بعد األولى مبارشة.
-إن لم يتم العثور على السلسلة األولى ،فقم بإدراج السلسلة الثانية في آخر القائمة.
باستثناء املصفوفات كالعادة ،يمكننا استخدام تغيري_حجم ،املوضح في الجدول ، 9.9لتكبري حاوية أو تصغريها.
فإن كان حجمها الحالي أكرب من املطلوب ،سيتم حذف العنارص من جزئها الخلفي ؛ •
أما إن كان حجمها الحالي أقل من الحجم الجديد ،سيتم إضافة عنارص إلى الجزء الخلفي من الحاوية : •
تأخذ عملية تغيري_حجم وسيطة اختيارية لقيمة العنرص تستخدمها لتهيئة أي عنارص مضافة إلى الحاوية. •
إن كانت هذه الوسيطة غائبة ،فستكون العنارص املضافة ذات قيمة تمت تهيئتها . •
وإن كانت الحاوية تحتوي على عنارص من نوع فئة وسيضيف تغيري_حجم عنارص إضافية ، •
فيجب علينا توفري ُمهئي أو يجب أن يكون لنوع العنرص ُمنشئة افرتاضية. •
تحذير
إذا أدى تغيري_الحجم إلى تقليص الحاوية فستكون مكررات ومراجع ومؤرشات العنارص املحذوفة باطلة. •
يحتمل أن تغيري حجم حاوية املتجه والسلسلة والطابور سيبطل كل املكررات واملراجع واملؤرشات. •
التمرين : 9.29
-إن كانت vecتحتوي على 25عنرصًا ،فماذا يفعل )vec.resize(100؟
-ماذا لو كتبنا بعد ذلك ) vec.resize(10؟
التمرين :9.30
-ما هي القيود ،إن وجدت ،اليت يستخدمها إصدار تغيري الحجم الذي يأخذ مكان وسيطة واحدة في نوع العنرص؟
يمكن لعمليات تضيف أو تزيل العنارص من الحاوية أن تبطل مؤرشات أو مراجع أو مكررات لعنارص الحاوية.
املؤرش (أو املرجع أو املكرر) الذي تم إبطاله مؤرش لم يعد يشري إلى عنرص. •
برمجيا خطريًا ،
ً يعد استخدام مؤرش أو مرجع أو مكرر غري صالح خطأ •
ويحتمل أن يؤدي إلى نفس أنواع املشكالت مثل استخدام مؤرش غري مهيأ. •
بعد عملية تضيف عنارص إلى الحاوية
تكون مكررات ومؤرشات ومراجع املتجه أو السلسلة باطلة إن تم إعادة تخصيص الحاوية. •
-في حالة عدم حدوث إعادة تخصيص ،تظل املراجع غري املبارشة للعنارص قبل اإلدراج صالحة ؛
-أما تلك العنارص فستكون بعد اإلدراج باطلة وغري صالحة.
تكون مكررات ومؤرشات ومراجع الطابور باطلة إن أضفنا عنارص في أي مكان ما عدا املقدمة أو الخلفية. •
-فإن أضفنا في املقدمة أو الخلفية ،تبطل املكررات ،لكن لن تبطل املراجع واملؤرشات لعنارص موجودة.
تظل مكررات ومؤرشات ومراجع القائمة والقائمة_اﻷمامية صالحة (بما في ذلك مكررات ما بعد النهاية وما •
قبل البداية) ،
-لن يكون مفاجًئ ا أن إزالة عنارص من حاوية ،سيبطل مكررات ومؤرشات ومراجع للعنارص املزالة.
-فبعد كل يشء ،تم تدمري تلك العنارص.
بعد عملية تزيل عنرصًا ،
• تظل جميع مكررات أو مراجع أو مؤرشات القائمة أو القائمة_اﻷمامية اﻷخرى صالحة (بما في ذلك مكررات
ما بعد النهاية وما قبل البداية).
• ستكون جميع مكررات أو مراجع أو مؤرشات الطابور األخرى باطلة إن كانت العنارص املزالة في أي مكان ما
عدا املقدمة أو الخلفية.
-أما إن قمنا بإزالة عنارص من خلفية الطابور ،فسيتم إبطال مكرر ما بعد النهاية دون أن تتأثر املكررات
واملراجع واملؤرشات األخرى ؛ ولن تتأثر إن أزلنا من املقدمة أيضاً.
• كل مكررات أو مراجع أو مؤرشات عنارص املتجه أو السلسلة األخرى ستظل صالحة قبل نقطة اإلزالة.
مالحظة :يتم دوماً إبطال املكرر ما بعد النهاية عندما نزيل عنارص. •
تحذير
يعد استخدام مكرر أو مؤرش أو مرجع تم إبطال مفعوله خطًأ خطريًا في وقت التشغيل.
الحلقات اليت تضيف أو تزيل عنارص من متجه أو سلسلة أو طابور يجب أن تليب حقيقة معينة :
وهي أن املكررات أو املراجع أو املؤرشات قد يتم إبطالها. •
يجب أن يضمن الربنامج تحديث املكرر أو املرجع أو املؤرش في كل اجتياز عرب الحلقة. •
يعد تحديث مكرر أمرًا سهالً إن قامت الحلقة باستدعاء إدراج أو محو. •
تعيد هذه العمليات مكررات ،واليت يمكننا استخدامها إلعادة تخصيص املكرر : •
// silly loop to remove even-valued elements and insert a duplicate of odd-
valued elements
;}vector<int> vi = {0,1,2,3,4,5,6,7,8,9
auto iter = vi.begin(); // call begin, not cbegin because we're changing vi
{ ))(while (iter != vi.end
{ ) if (*iter % 2
;) iter = vi.insert(iter, *iter // duplicate the current element
iter += 2; // advance past this element and the one inserted before it
} else
;) iter = vi.erase(iter // remove even elements
// don't advance the iterator; iter denotes element after one we erased
}
يزيل هذا الربنامج العنارص ذات القيمة الزوجية ويكرر كل عنرص ذو قيمة فردية. •
نقوم بتحديث املكرر بعد كل من اإلدراج واملسح ألن أي من العمليتني قد تبطل املكرر. •
بعد استدعاء املحو ،ليست هناك حاجة ملزايدة املكرر ،ألن املكرر العائد من املحو يشري إلى العنرص التالي •
في التسلسل.
بعد استدعاء اإلدراج ،نقوم بمزايدة املكرر مرتني. •
مكررا إلى العنرص املدرج.
ً تذكر ،تقوم إدراج باإلدراج قبل املوضع املحدد لها وتعيد •
وبالتالي ،بعد استدعاء اﻹدراج ،ستشري iterإلى العنرص (املضاف حديثًا) أمام العنرص الذي نقوم •
بمعالجته.
نضيف اثنني لتخطي العنرص الذي أضفناه والعنرص الذي قمنا بمعالجته للتو. •
يؤدي القيام بذلك إلى وضع املكرر على العنرص التالي غري املعالج. •
عندما نضيف أو نزيل عنارص متجه أو سلسلة ،أو نضيف أو نزيل عنارص طابور باستثناء أول عنرص ،فإن املكرر
دائما باطالً وغري صالح.
ً املعاد من نهاية_ يكون
دائما نهاية_ بدال ً من استخدام نسخة
ً • وبالتالي ،يجب أن تستدعي الحلقات اليت تضيف العنارص أو تزيلها
مخزنة.
جزئيا ،عاد ًة ما يتم تنفيذ مكتبات يس ++القياسية بحيث يكون استدعاء () endعمليةً • ولهذا السبب
رسيعة ج ًدا.
• كمثال ،فكر في حلقة تعالج كل عنرص وتضيف عنرصًا جدي ًدا بعد األصل.
نريد أن تتجاهل الحلقة العنارص املضافة ،وأن تعالج العنارص األصلية فقط. •
بعد كل إدراج ،سنضع املكرر ليشري إلى العنرص األصلي التالي. •
إن حاولنا "تحسني" الحلقة ،من خالل تخزين املكرر املعاد من نهاية_ ،فسنواجه كارثة: •
تلميح
ال تقم بتخزين املكرر العائد من نهاية_ مؤق ًتا في حلقات تُدرج عنارص أو تحذفها في طابور أو سلسلة أو متجه.
بدال ً من تخزين مكرر نهاية_ ،ينبغي علينا إعادة حسابه بعد كل مدخالت:
// safer: recalculate end on each trip whenever loop adds/erases elements
{ ))(while (begin != v.end
// do some processing
++begin; // advance begin because we want to insert after this element
begin = v.insert(begin, 42); // insert the new value
++begin; // advance begin past the element we just added
}
التمرين :9.31
-ملاذا لن يعمل الربنامج املوجود في الصفحة 354إلزالة العنارص ذات القيمة الزوجية والعنارص الفردية املكررة في
قائمة أو قائمة_أمامية ؟
أيضا.
-قم بمراجعة الربنامج حىت يعمل على هذه األنواع ً
التمرين :9.32
-في الربنامج على الصفحة ، 354هل من الرشعي كتابة االستدعاء لإلدراج كما يلي؟
-إن لم يكن كذلك ،فلماذا؟
;)iter = vi.insert(iter, *iter++
التمرين :9.33
-في املثال األخري في هذا القسم ،ماذا سيحدث إن لم نقم بتعيني نتيجة املدخالت للبدء؟
برنامجا يغفل هذه املهمة ملعرفة ما إن كانت توقعاتك صحيحة.
ً -اكتب
التمرين :9.34
قيما فردية وزوجية ،فتوقع سلوك الحلقة التالية.
-بافرتاض أن viعبارة عن حاوية من intsتتضمن ً
برنامجا الختبار ما إن كانت توقعاتك صحيحة.
ً -بعد تحليل هذه الحلقة ،اكتب
;)(iter = vi.begin
))(while (iter != vi.end
) if (*iter % 2
;) iter = vi.insert(iter, *iter
; ++iter
. 9٫4كــــــــــيف ينمـــــــــو متــــــــــجه
9.4 How a vector Grows
لدعم الوصول العشوائي الرسيع ،يتم تخزين عنارص املتجه بشكل متجاور -كل عنرص مجاور للسابق.
في العادة ،ال يجب أن نهتم بكيفية تنفيذ نوع املكتبة ؛ كل ما يجب أن نهتم به هو كيفية استخدامه. •
ومع ذلك ،في حالة املتجهات والسالسل ،يترسب جزء من التنفيذ إلى واجهته. •
بالنظر إلى أن العنارص متجاورة ،وأن حجم الحاوية مرن ،
فكر في ما يجب أن يحدث عندما نضيف عنرصًا إلى متجه أو سلسلة: •
إن لم يكن هناك مكان لعنرص جديد ،فال يمكن للحاوية إضافة عنرص في مكان آخر في الذاكرة – فالعنارص •
يجب أن تكون متجاورة.
بدال ً من ذلك ،يجب أن تخصص الحاوية ذاكرة جديدة : •
لتحمل العنارص املوجودة باإلضافة إلى العنرص الجديد ، •
وتنقل العنارص من املوقع القديم إلى املساحة الجديدة ، •
• وتقوم بإضافة العنرص الجديد ،وإلغاء تخصيص الذاكرة القديمة.
• إن قام املتجه بتخصيص الذاكرة وإلغاء التخصيص في كل مرة نضيف فيها عنرصًا ،فسيكون األداء بطيًئ ا
بشكل غري مقبول.
لتجنب هذه التكاليف ،يستخدم منفذو املكتبات اسرتاتيجيات تخصيص تقلل من عدد مرات إعادة تخصيص الحاوية.
عندما يتعني عليهم الحصول على ذاكرة جديدة ، •
فإن تطبيقات املتجهات والسلسلة عاد ًة ما تخصص سعة تتجاوز الحجم املطلوب في لحظته. •
تحتفظ الحاوية بهذا التخزين في االحتياط وتستخدمه لتخصيص عنارص جديدة عند إضافتها. •
وبالتالي ،ليست هناك حاجة إلعادة تخصيص الحاوية لكل عنرص جديد. •
تعترب اسرتاتيجية التخصيص هذه أكرث كفاءة بكثري من إعادة تخصيص الحاوية كل مرة يتم فيها إضافة عنرص.
في الواقع ،يعد األداء جيداً بما يكفي بحيث أنه عملياً ينمو املتجه بكفاءة أكرث من القائمة أو الطابور ، •
بالرغم من أن املتجه يجب أن يحرك جميع عنارصه في كل مرة يعيد تخصيص الذاكرة. •
توفر أنواع املتجهات والسلسلة أعضاء ،موصوفة في الجدول ، 9.10تتيح لنا التفاعل مع جزء تخصيص الذاكرة من
التنفيذ.
• تخربنا عملية السعة عن عدد العنارص اليت يمكن للحاوية االحتفاظ بها قبل أن تخصص مساحة أكرب.
وتتيح لنا عملية الحجز إخبار الحاوية بعدد العنارص اليت يجب أن تكون مستعدة لالحتفاظ بها. •
ملحوظة
ال يغري الحجز عدد العنارص في الحاوية ؛ إذ يؤثر فقط على مقدار الذاكرة اليت يخصصها املتجه مسب ًقا.
يغري استدعاء الحجز سعة املتجه فقط إن تجاوزت املساحة املطلوبة السعة الحالية. •
أما إن كان الحجم املطلوب أكرب من السعة الحالية ،سيخصص الحجز على األقل سعة على (وقد يخصص •
أكرث من) الحجم املطلوب.
إن كان الحجم املطلوب أقل من أو يساوي السعة الحالية ،فلن يفعل الحجز شيًئ ا. •
تحديداً ،ال يؤدي استدعاء الحجز على حجم أصغر من السعة إلى إعادة الحاوية للذاكرة. •
وبالتالي ،بعد استدعاء الحجز ،ستكون السعة أكرب من أو تساوي الوسيطة اليت تم تمريرها للحجز. •
نتيجة لذلك ،لن يقلل استدعاء الحجز من مقدار املساحة اليت تستخدمها الحاوية. •
وباملثل ،فإن أعضاء تغيري الحجم ﻻ تغري إﻻ عدد العنارص في الحاوية ،وليس سعتها. •
• ال يمكننا استخدام تغيري الحجم لتقليل الذاكرة اليت تحتفظ بها الحاوية.
تحت املكتبة الجديدة ،يمكننا استدعاء قلّ ص_ليالئم shrink_to_fitلنطلب من طابور أو متجه أو سلسلة
إعادة ذاكرة غري رضورية.
• تشري هذه الدالة إلى أننا لم نعد بحاجة إلى أي سعة فائضة.
مع ذلك ،فإن التنفيذ حر في تجاهل هذا الطلب. •
فليس هناك ما يضمن أن استدعاء shrink_to_fitسيعيد الذاكرة. •
;vector<int> ivec
// size should be zero; capacity is implementation defined
<< cout )("ivec: size: " << ivec.size
<< ;" capacity: " << ivec.capacity() << endl
// give ivec 24 elements
)for (vector<int>::size_type ix = 0; ix != 24; ++ix
;)ivec.push_back(ix
// size should be 24; capacity will be >= 24 and is implementation defined
)(cout << "ivec: size: " << ivec.size
;<< " capacity: " << ivec.capacity() << endl
هنا ،تشري املخرجات إلى أن استدعاء الحجز قد خصص بالضبط املساحة اليت طلبناها:
قد نستخدم بعد ذلك هذه السعة املحجوزة على النحو التالي:
ونظر ًا ألننا استخدمنا السعة املحجوزة فقط ،فال داعي أن يقوم املتجه بأي تخصيص. •
في الواقع ،طاملا لم تتجاوز أي عملية سعة املتجه ،يجب أال يعيد املتجه تخصيص عنارصه. •
إن أضفنا اآلن عنرصًا آخر ،فسيتعني على املتجه إعادة تخصيص نفسه:
يشري إلى أن تنفيذ املتجه هذا يبدو أنه يتبع اسرتاتيجية ملضاعفة سعته الحالية في كل مرة يتعني عليه •
تخصيص تخزين جديد.
يمكننا استدعاء shrink_to_fitلنطالب بإعادة الذاكرة اليت تتجاوز الحجم املطلوب الحالي إلى النظام: •
استدعاء shrink_to_fitليس سوى طلب ؛ فليس هناك ما يضمن أن املكتبة ستعيد الذاكرة. •
ملحوظة
ال يجوز إعادة تخصيص املتجه إال عندما يقوم املستخدم بإجراء عملية إدراج حيث يساوي الحجم السعة ، •
أو عند استدعاء تغيري الحجم أو الحجز بقيمة تتجاوز السعة الحالية. •
يعود مقدار الذاكرة املخصصة بعد املقدار املحدد إلى التنفيذ. •
كل تنفيذ مطلوب التباع إسرتاتيجية تضمن كفاءة استخدام دفع_للخلف إلضافة عنارص إلى املتجه. •
من الناحية الفنية ،ينبغي أال يزيد وقت تنفيذ إنشاء متجه بالعنرص nعن طريق استدعاء دفع_للخلف على •
nمرة على متجه فارغ في بداية_ أكرث من مضاعف ثابت لـ .n
التمرين :9.36
هل يمكن أن تقل سعة الحاوية عن حجمها؟
التمرين :9.37
ملاذا ال تحتوي القائمة أو املصفوفة على عضو سعة؟
التمرين :9.38
برنامج ا الستكشاف كيفية نمو املتجهات في املكتبة اليت تستخدمها.
ً اكتب
التمرين :9.39
ارشح ما يفعله جزء الربنامج التالي:
;vector<string> svec
;)svec.reserve(1024
;string word
)while (cin >> word
;) svec.push_back(word
;)svec.resize(svec.size()+svec.size()/2
التمرين :9.40
-إن كان الربنامج في التمرين السابق يقرأ 256كلمة ،فما هي سعته املحتملة بعد تغيري حجمه؟
-ماذا لو كانت 512؟ 1000؟ 1،048؟
. 9٫5عملــــــــــيات سلــــــسلــــــة إضــــــــــافيــــــة
9.5 Additional string Operations
يوفر نوع السلسلة عدة عمليات إضافية خالف تلك العمليات الشائعة في الحاويات املتسلسلة.
الجزء األكرب من هذه العمليات اإلضافية إما تدعم تفاعالً وثيقاً بني فئة السلسلة ومصفوفات أحرف النمط C •
أو تضيف إصدارات تتيح لنا استخدام الفهارس كبديل عن املكررات. •
أنماطا متكررة.
ً تعرف مكتبة السلسلة عد ًدا كبريًا من الدوال .لحسن الحظ ،تستخدم هذه الدوال
ّ
وبالنظر إلى عدد الدوال املدعومة ،يمكن أن يكون هذا القسم مذهالً عند القراءة األولى ؛ •
لذلك قد يرغب القراء في االطالع على تلك الدوال .لكن بمجرد معرفة أنواع العمليات املتاحة ، •
سيمكنهم العودة لالطالع على تفاصيل أكرث عندما يحتاجون إلى استخدام عملية معينة. •
تأخذ املنشئات اليت تأخذ سلسلة أو مؤرشاً لحرف ثابت وسيطات إضافية (اختيارية) تتيح لنا تحديد عدد •
األحرف املراد نسخها.
أيضا تحديد فهرس أين يبدأ النسخ :
فعندما نمرر سلسلة ،يمكننا ً •
في العادة عندما ننئش سلسلة من مؤرش لحرف ثابت ، •
يتم أن تكون املصفوفة اليت يجب أن يكون املؤرش يشري إليها منتهية بحرف خال ؛ •
ويتم نسخ األحرف إلى القيمة الفارغة. •
أيضا عد ًدا ،فال يلزم إنهاء املصفوفة بحرف خال.
إن مررنا ً •
إن لم نمرر عد ًدا ولم يكن هناك أي قيمة فارغة ،أو كان العدد املحدد أكرب من حجم املصفوفة ، •
معرفة.
فإن العملية تكون غري ّ •
عندما نقوم بالنسخ من سلسلة ،يمكننا توفري موضع بدء اختياري وعدد.
يجب أن يكون موضع البداية أقل من أو يساوي حجم السلسلة املحددة. •
إن كان املوضع أكرب من الحجم ،فإن املُنشئة تطرح االستثناء خارج_النطاق .out_of_range •
بدءا من املوضع املحدد.
عندما نمرر العد ،يتم نسخ عدد من األحرف ً ، •
وبغض النظر عن عدد األحرف اليت نطلبها ،تنسخ املكتبة حىت حجم السلسلة ،لكن ليس أكرث. •
تعيد عملية السلسلة الفرعية (املوضحة في الجدول )9.12سلسلة عبارة عن نسخة السلسلة األصلية أو جزء منها.
يمكننا تمرير موضع بدء اختياري للمجموعة الفرعية والعد : •
التمرين :9.41
برنامجا يقوم بتهيئة سلسلة على متجه <.>char
ً اكتب
التمرين :9.42
-نظر ًا ألنك تريد قراءة حرف في كل مرة في سلسلة ،وأنت تعلم أنك بحاجة إلى قراءة 100حرف على األقل ،
-فكيف يمكنك تحسني أداء برنامجك؟
يدعم نوع السلسلة عوامل التعيني للحاويات املتسلسلة وعمليات تعيني assignوإدراج insertومسح .erase
أيضا إصدارات إضافية من اإلدراج واملسح.
يعرف ً
وكذلك ّ •
فهرسا.
ً وإضافة إلى إصدارات اإلدراج واملسح اليت تأخذ مكررات ،توفر السلسلة إصدارات تأخذ •
يشري الفهرس إلى عنرص البداية املراد مسحه أو املوضع الذي يجب إدراج القيم املحددة قبله: •
هنا نقوم أوال ً باستبدال محتويات sعن طريق استدعاء التعيني. •
األحرف اليت نخصصها في sهي األحرف السبعة اليت تبدأ بالحرف الذي يشري إليه .cp •
يجب أن يكون عدد األحرف اليت نطلبها أقل من عدد األحرف ، •
مساويا له (باستثناء حرف النهاية الصفري) في املصفوفة اليت يشري إليها .cp
ً أو أن يكون •
عندما نستدعي إدراج على ، sسنقول إننا نريد إدراج أحرف قبل العنرص (غري املوجود) في ])(.s[size •
في تلك الحالة ،نقوم بنسخ األحرف اليت تبدأ بسبعة أحرف بعد cpحىت النهاية الخالية. •
أيض ا تحديد األحرف املراد إدراجها أو تعيينها كأنها قادمة من سلسلة أخرى أو سلسلة فرعية منها:
يمكننا ً •
string s = "some string", s2 = "some other string";
s.insert(0, s2); // insert a copy of s2 before position 0 in s
// insert s2.size() characters from s2 starting at s2[0] before s[0]
s.insert(0, s2, 0, s2.size());
. يمكنهما تغيري محتويات سلسلة، _ إلحاق_ واستبدال، تعر ف فئة السلسلة عضوين إضافيتني
ّ
. هذه الدوال9.13 يلخص الجدول •
: عملية إلحاق_ تعترب طريقة مخترصة لإلدراج من النهاية •
s.append
Append args to s. Return a reference to s.
(args)
Remove range of characters from s and replace them with the
s.replace characters formed by args. Range is either an index and a
(range, args) length or a pair of iterators into s.
return a reference to s.
args can be one of the following; append and assign can use all forms.
str must be distinct from s and iterators b and e may not refer to s.
n, c n copies of character c.
initializer
Comma-separated list of characters enclosed in braces.
list
args for replace and insert depend on how range or pos is specialized.
yes yes no no cp
Initialize
no yes no yes
list
. يكون النص الذي أدخلناه بنفس حجم النص الذي أزلناه، _في استدعاء استبدال •
:يمكننا إدراج سلسلة أكرب أو أصغر •
"s.replace(11, 3, "Fifth"); // s == "C++ Primer Fifth Ed.
في هذه االستدعاء نزيل ثالثة أحرف لكن نضيف خمسة في مكانها. •
الدوال إلحاق_ ،وتعيني_ ،وإدراج_ ،واستبدال_ املدرجة في الجدول 9.13تملك عدة إصدارات زائدة التعبئة.
تختلف وسيطاتها بحسب كيفية تحديد األحرف املراد إضافتها وأي جزء من السلسلة يجب تغيريه. •
لحسن الحظ ،تشرتك هذه الدوال في واجهة مشرتكة. •
ال تحتاج الدوال تعيني_ وإلحاق_ إلى تحديد جزء السلسلة الذي تم تغيريه : •
دائما إلى آخرها.
ً دائما محتويات السلسلة بالكامل ويضيف إلحاق_ً يستبدل تعيني_ •
توفر دوال استبدال_ طريقتني لتحديد نطاق الحروف املراد إزالتها. •
فيمكننا تحديد هذا النطاق من خالل املوضع والطول ،أو عن طريق نطاق مكرر. •
تمنحنا دوال إدراج_ طريقتني لتعريف نقطة اإلدراج: •
إما باستخدام الفهرس وإما باستخدام مكرر. •
في كل حالة ،يتم إدراج العنـ (ــا) رص الجديدة أمام فهرس أو مكرر محدد. •
هناك عدة طرق لتحديد أحرف عند إضافتها إلى سلسلة ؛ حيث يمكن أن تؤخذ اﻷحرف الجديدة ...
من سلسلة أخرى ،من مؤرش حرف ،من قائمة أحرف محاطة بأقواس ،أو كحرف وعدد. •
عندما تأتي األحرف من سلسلة أو مؤرش حرف ، •
يمكن تمرير وسيطات إضافية للتحكم في ما إن كنا ننسخ بعض تلك اﻷحرف أو كلها من الوسيطة. •
ال تدعم كل الدوال جميع نسخ هذه الوسيطات.
فعلى سبيل املثال ،ال يوجد إصدار من إدراج_ يأخذ فهرساً وقائمة ُمهئي. •
وباملثل ،إن أردنا تعريف نقطة اإلدراج باستخدام مكرر ، •
فال يمكننا تمرير مؤرش حرف كمصدر لألحرف الجديدة. •
التمرين :9.43
-اكتب دالة تأخذ ثالث سالسل ، s ،و ، oldValو .newValباستخدام املكررات ،
-تحل دالتا اإلدراج واملحو محل جميع مثيالت oldValاليت تظهر في sبواسطة .newVal
-اخترب دالتك عن طريق استخدامها الستبدال اختصارات شائعة ،
-مثل استبدال " "thoبـ " "thoughواستبدال " "thruبـ "."through
التمرين :9.44
أعد كتابة الدالة السابقة باستخدام فهرس واستبدل.
التمرين :9.45
اسما وسلسلتني آخرتني تمثالن بادئة ،
ً -اكتب دالة تأخذ سلسلة تمثل
-مثل " ".Mrأو " ".Mrsوالحقة ،مثل " ".Jrأو "."III
-باستخدام املكررات ودوال اإلدراج واإللحاق ،
-قم بإنشاء سلسلة جديدة وإعادتها مع إضافة الالحقة والبادئة إلى االسم املحدد.
التمرين :9.46
-أعد كتابة التمرين السابق باستخدام موضع وطول إلدارة األوتار .هذه املرة استخدم فقط دالة اإلدراج.
توفر فئة السلسلة ست دوال بحث مختلفة ،لكل منها أربع نسخ زائدة التعبئة.
يصف الجدول 9.14أعضاء البحث ووسيطاتها. •
تقوم كل عملية من عمليات البحث هذه بإعادة قيمة string::size_typeتمثل فهرس أين صادف •
التطابق.
إن لم يكن هناك تطابق ،تقوم الدالة بإعادة عضو ثابت باسم .string::npos •
تُعرِّف املكتبة nposعلى أنها string::size_typeتمت تهيئتها على القيمة .1- •
وألن nposهو نوع بال_إشارة ،فإن هذا املُهئي يعين أن nposيساوي أكرب حجم قد تحتويه أي سلسلة. •
تعيد عمليات البحث هذه فهرساً للحرف املطلوب أو nposإن لم يتم العثور عليه
تحذير
string name("AnnaBelle");
auto pos1 = name.find("Anna"); // pos1 == 0
."AnnaBelle" " فيAnna" الفهرس الذي توجد عنده السلسلة الفرعية، 0 تعيد القيمة •
.البحث (وعمليات السالسل األخرى) حساسة لحالة األحرف •
: فإن الحالة مهمة، عندما نبحث عن قيمة في السلسلة •
string lowercase("annabelle");
pos1 = lowercase.find("Anna"); // pos1 == npos
;)"string dept("03714p3
'// returns 5, which is the index to the character 'p
;)auto pos = dept.find_first_not_of(numbers
يتم تنفيذ عمليات البحث اليت استخدمناها حىت اآلن من اليسار إلى اليمني.
توفر املكتبة عمليات مماثلة تقوم بالبحث من اليمني إلى اليسار. •
يبحث العضو rfindعن آخر مكرر -أي أقىص اليمني -للسلسلة الفرعية املشار إليها : •
;)"string river("Mississippi
;)"auto first_pos = river.find("is // returns 1
;)"auto last_pos = river.rfind("is // returns 4
فهرسا بقيمة ، 1مما يشري إلى بداية " "isاألولى ،
ً findتعيد •
بينما تعيد rfindمؤرشًا بقيمة ، 4مما يشري إلى بداية آخر ظهور لـ "."is •
وباملثل ،تترصف الدوال find_lastمثل داالت ، find_first •
باستثناء أنها تعرض آخر تطابق بدال ً من األول : •
فيبحث find_last_ofعن آخر حرف يطابق أي عنرص من عنارص سلسلة البحث. •
يبحث find_last_not_ofعن آخر حرف ال يتطابق مع أي عنرص من عنارص سلسلة البحث. •
تأخذ كل عملية من هذه العمليات وسيطة ثانية اختيارية تشري إلى املوضع داخل السلسلة لبدء البحث. •
التمرين :9.47
برنامجا يبحث عن كل حرف رقمي ثم كل حرف أبجدي في السلسلة "."ab2c3d7R4E6
ً -اكتب
-اكتب نسختني من الربنامج.
-يجب أن يستخدم األول ، find_first_of
-ويجب أن يستخدم الثاني .find_first_not_of
التمرين :9.48
-بالنظر إلى تعريفات األسماء واألرقام في الصفحة ، 365
-ما الذي يعيده البحث عن (االسم)؟
التمرين :9.49
-يكون للحرف صاعد إن كان جزء من الحرف يمتد فوق السطر ،كما هو حال dأو .f
-يكون للحرف سليل إن امتد جزء من الحرف أسفل السطر ،كما هو حال pأو .g
برنامجا يقرأ مل ًفا يحتوي على كلمات ويبلغ عن أطول كلمة ال تحتوي على صاعدة وال سفلية.
ً -اكتب
إضافة إلى العوامل العالئقية ،توفر مكتبة السلسلة مجموعة دوال مقارنة تشبه دالة مكتبة اليس .strcmp
ومثل ، strcmpتعيد s.compareصفرًا أو قيمة موجبة أو سالبة ، •
اعتما ًدا على ما إن كانت sتساوي أو أكرب من أو أقل من السلسلة املكونة من الوسيطات املحددة. •
كما هو موضح في الجدول ، 9.15هناك ستة إصدارات للمقارنة. •
بناء على ما إن كنا نقارن بني سلسلتني أو سلسلة ومجموعة أحرف.
ً تختلف الوسيطات •
في كلتا الحالتني ،قد نقارن السلسلة بأكملها أو جزء منها. •
int i = 42;
string s = to_string(i); // converts int i to its character representation
double d = stod(s); // converts string s to floating-point
هنا نستدعي to_stringلتحويل 42إلى تمثيل السلسلة املقابل لها ، •
ثم نستدعي stodلتحويل تلك السلسلة إلى العائمة العرشية •
يجب أن يكون أول حرف ليس مسافة بيضاء في سلسلة نحولها إلى قيمة رقمية حر ًفا قد يظهر في رقم: •
ملحوظة
إن كان ال يمكن تحويل السلسلة إلى رقم ،فإن هذه الداالت تطرح االستثناء غري صالح للوسيطة . •
إن كان التحويل يولد قيمة ال يمكن تمثيلها ،فسيتم رفع اﻻستثناء خارج_النطاق .out_of_range •
التمرين :9.50
قيما أعداد صحيحة.
برنامجا ملعالجة متجه <سلسلة> تمثل عنارصه ً
ً -اكتب
-أنتج مجموع كل العنارص في هذا املتجه.
-قم بتغيري الربنامج بحيث يكون مجموع السالسل اليت تمثل القيم عائمة عرشية.
التمرين :9.51
-اكتب فئة بها ثالثة أعضاء بال_إشارة تمثل السنة والشهر واليوم.
تاريخا.
ً -اكتب ُمنشئة تأخذ سلسلة تمثل
-يجب أن تتعامل امل ُنشئة مع مجموعة متنوعة من تنسيقات التاريخ ،
-مثل 1يناير 1900و 1/1/1900و 1يناير 1900وما إلى ذلك.
مكيــــــــفات الحــــــــــاويات. 9٫6
9.6 Container Adaptors
، فارغا
ً املُنشئة االفرتاضية اليت تنئش كائنًا:يعرف كل مكيف ُمنشئتني
ّ
.• واملنشئة اليت تأخذ حاوية ويهئي املكيف عن طريق نسخ الحاوية املحددة
:حزمة جديدة على النحو التالي
ُ لتهيئةdeq يمكننا استخدام، >int< هو طابورdeq بافرتاض أن، ًفمثال •
الحزمة.
الحزمة في عنوان ُ
يتم تعريف نوع ُ
الحزم:
الحزم في الجدول .9.18يوضح الربنامج التالي استخدام ُ
يتم رسد العمليات اليت يوفرها ُ
Removes but does not returns, the top elements from the
)(s.pop
stack.
فاإلعالن. . .
حزمة فارغة تحتوي على عنارص عدد صحيح. يعرف intStackعلى أنه ُ
ّ •
بدءا من الصفر.
تضيف حلقة forعرشة عنارص ،وتبدأ كل منها في العدد الصحيح التالي بالتسلسل ً •
الحزمة
الحزمة حىت تصبح ُ
الحزمة بأكملها ،وتفحص القيمة األعلى وتطردها من ُ
تتكرر حلقة whileخالل ُ •
فارغة.
يعر ف كل مكيف حاوية عملياته الخاصة من حيث العمليات اليت يوفرها نوع الحاوية األسايس.
ّ •
يمكننا استخدام عمليات املكيف فقط وال يمكننا استخدام عمليات نوع الحاوية األساسية .مثالً ، •
يستدعي دفع_للخلف على كائن طابور الذي يعتمد عليه .intStack •
الحزمة تُنفذ باستخدام طابور ،إال أنه ليس لدينا وصول مبارش إلى عمليات الطابور.
بالرغم من أن ُ •
الحزمة املسماة دفع_ .push
حزمة ؛ بل ،يجب أن نستخدم عملية ُ فال يمكننا استدعاء دفع_للخلف على ُ •
يستخدم مكيف الصف الطابور افرتاضياً ،ويمكنه استخدام املتجه أو القائمة كذلك. •
يستخدم مكيف أولوية_الصف املتجه افرتاضياً ،ويمكنه استخدام الطابور كذلك. •
Removes but does not returns, the front elements or
)(q.pop highest-priority element from the queue or priority_queue,
respectively.
)(q.front Returns but does not remove, the front or back elements.
)(q.back Valid only for queue.
تستخدم مكتبة الصف سياسة فيفو :ما يدخل أوال ً يخرج أوال ً (.)FIFO : FirstInFirstOut
• حيث يتم وضع الكائنات اليت تدخل الصف في الخلف وتتم إزالة الكائنات اليت تغادره من املقدمة.
يعد املطعم الذي يُجلس األشخاص برتتيب وصولهم مثاال ً على صف فيفو .FIFO •
تتيح لنا خاصية أولوية_الصف تحديد أولوية بني العنارص املوجودة في الصف. •
حيث توضع العنارص املضافة حديثًا في مقدمة كل العنارص ذات األولوية األقل. •
فاملطعم الذي يُجلس األشخاص وف ًقا لوقت حجزهم بغض النظر عن وقت وصولهم ،مثال ألولوية_الصف. •
افرتاضياً ،تستخدم املكتبة عامل نوع العنرص > لتحديد األولويات النسبية. •
سنتعلم كيفية تجاوز هذا اإلعداد االفرتايض في الفقرة .11.2.2 •
التمرين :9.52
حزمة ملعالجة التعبريات ذات األقواس.
-استخدم ُ
مفتوحا ،الحظ أنه تم رؤيته.
ً قوسا
ً -عندما ترى
قوسا مغل ًقا بعد قوس مفتوح ،
ً -عندما ترى
الحزمة.
-اطرد العنارص ألسفل وقم بتضمني قوس الفتح خارج ُ
الحزمة لإلشارة إلى أنه تم استبدال تعبري بني قوسني.
-قم بدفع قيمة إلى ُ
ملخــــــــــص الفصــــــــــل
Chapter Summary
قد نضيف عنارص إلى الحاوية دون القلق بشأن مكان تخزين العنارص.
الحاوية نفسها تدير تخزينها. •
تحكما أكرث تفصيالً في إدارة الذاكرة من خالل أعضاء الحجز والسعة.
ً يوفر كل من املتجه والسلسلة •
مكيف :
نوع مكتبة أو دالة أو مكرر يجعله يترصف كنوع آخر ،كنظري لنوعه أو
adaptor دالته أو مكرره.
الحزمة والصف وأولوية_الصف.ُ للحاويات: متسلسلة مكيفات هناك ثالثة
يعرف كل مكيف واجهة جديدة أعلى نوع الحاوية املتسلسل األسايس.ّ
مصفوفة :
مصفوفة املكتبة هي حاوية متسلسلة ثابتة الحجم.
array لتعريف مصفوفة ،يجب أن نعطي الحجم إضافة إلى تحديد نوع العنرص.
يمكن الوصول إلى العنارص في املصفوفة من خالل فهرسها املوضعي.
يدعم الوصول العشوائي الرسيع إلى العنارص.
بداية_:
مكررا يشري ألول عنرص في الحاوية – إن وجد –،
ً عملية حاوية تعيد
begin
أو مكرر مابعد_نهاية إن كانت الحاوية فارغة.
يعتمد ما إن كان املكرر املعاد ثابتاً على نوع الحاوية.
بداية_ثابتة :
cbegin عملية حاوية تعيد مكرراً ثابتاً يشري ألول عنرص في الحاوية ،إن وجد ،
أو يعيد مكرر مابعد_نهاية إن كانت الحاوية فارغة.
نهاية_ثابتة :
cend عملية حاوية تعيد مكرراً ثابتاً يشري لعنرص (غري موجود) بعد نهاية
الحاوية.
حاوية :
نوع يحتوي على مجموعة كائنات من نوع معني .فكل نوع حاوية مكتبة
container عبارة عن قالب.
لتعريف حاوية ،يجب علينا تحديد نوع العنارص املخزنة في تلك الحاوية.
باستثناء املصفوفة ،تكون حاويات املكتبة متغرية الحجم.
طابور:
حاوية متسلسلة .يمكن الوصول إلى عنارصها من خالل مؤرش موضع ،
كما يدعم الوصول العشوائي الرسيع إلى تلك العنارص.
deque
يشبه املتجه من جميع النواحي إﻻ أنه يدعم اإلدراج الرسيع والحذف من
مقدمة وآخر الحاوية وال ينقل عنارصه نتيجة لعمليات اإلدراج أو الحذف
في أي من الطرفني.
نهاية_:
end مكررا يشري إلى عنرص (غري موجود) بعد نهاية الحاوية. عملية حاوية تعيد
ً
يعتمد ما إن كان املكرر املعاد ثاب ًتا على نوع الحاوية.
قائمة_أمامية :
حاوية متسلسلة تمثل قائمة ترتابط بشكل منفرد وحر.
بدءا من عنرص
يمكن الوصول إلى عنارص القائمة_اﻷمامية بالتسلسل فقط ؛ ً
معني ،
وال يمكن الوصول إلى عنرص آخر إال من خالل اجتياز كل عنرص بينهما.
املكررات في القائمة_اﻷمامية ال تدعم التناقص (.)-
forward_list تدعم القائمة_اﻷمامية اإلدراج الرسيع (أو الحذف) في أي مكان فيها.
وعلى عكس الحاويات األخرى ،تحدث عمليات اإلدراج والحذف بعد موضع
مكرر معني.
نتيجة لذلك ،تحتوي القائمة_اﻷمامية على مكرر "قبل_بداية" ليتماىش مع
املكرر العادي.
مكررات القائمة_اﻷمامية تبقى صالحة عند إضافة عنارص جديدة.
وعند إزالة عنرص ،يتم إبطال مكرر ذلك العنرص فقط.
نطاق املكرر:
مجموعة عنارص يُشار إليها بزوج من املكررات.
يشري املكرر األول إلى أول عنرص في التسلسل ،ويشري الثاني إلى ما بعد
آخر عنرص فيه.
فارغا ،فسيكون املكرران متساويان ؛
ً إن كان النطاق
iterator range
(والعكس صحيح -فإن كان املكرران غري متساويان ،فإنهما يشريان إلى
نطاق غري فارغ).
فارغا ،فيجب أن يكون من املمكن الوصول إلى املكرر
ً إن لم يكن النطاق
الثاني عن طريق مزايدة املكرر األول بشكل متكرر.
ومن خالل زيادة املكرر ،سنتمكن من معالجة كل عنرص في التسلسل.
مكرر_قبل_البداية :
مكرر يشري إلى عنرص (غري موجود) قبل بداية القائمة_اﻷمامية.
off-the-beginning iterator
يعود من عضو القائمة_اﻷمامية .before_begin
مثل مكرر نهاية_ ،ال يسمح بإلغاء املرجع عنه.
أولوية_الصف :
مكيف للحاويات املتسلسلة ينتج عنه صف يتم فيها إدراج العنارص ،
priority_queue
ليس في نهايته ولكن وف ًقا ملستوى أولوية محدد.
افرتاضياً ،يتم تحديد تلك األولوية باستخدام عامل نوع العنرص أقل من.
صف :
queue نوعا يتيح لنا إضافة عنارص إلى الخلف
ً ينتج املتسلسلة للحاويات مكيف
وإزالتها من املقدمة.
حاوية متسلسلة:
sequential container نوع يحتوي على مجموعة مرتبة من الكائنات من نوع واحد.
يتم الوصول إلى العنارص في الحاوية املتسلسلة حسب املوضع.
حزمة :
ُ
stack نوعا يتيح لنا إضافة وإزالة العنارص من
ً ينتج املتسلسلة للحاويات مكيف
طرف واحد فقط.
متجه :
حاوية متسلسلة .يمكن الوصول إلى عنارصه من خالل فهرسها املوضعي.
يدعم الوصول العشوائي الرسيع إلى العنارص.
يمكننا إضافة عنارص متجه أو إزالتها بكفاءة فقط من الخلف.
vector
قد تؤدي إضافة عنارص إلى متجه إلى إعادة تخصيصه ،وهو ما يؤدي إلى
إبطال كل مكرراته.
تؤدي إضافة (أو إزالة) عنرص في منتصف املتجه إلى إبطال كل مكررات
عنارصه بعد نقطة اإلدراج (أو الحذف).