You are on page 1of 68

‫الفصــــــــــل ‪ .

9‬الحــــــــــاويــــــــــات الـمتســــــــــلســــــلة‬
‫‪Chapter 9. Sequential Containers‬‬

‫الـمحتويات‬
‫‪Contents‬‬

‫‪9.1 Overview of Sequential Containers‬‬ ‫‪ 9٫1‬الحاويات املتسلسلة ‪ :‬نظرة عامة‬

‫‪9.2 Container Library Overview‬‬ ‫‪ 9٫2‬مكتبـــة الحاويـــة ‪ :‬نظرة عامة‬

‫‪9.3 Sequential Container Operations‬‬ ‫‪ 9٫3‬عمليات الحاوية املتسلسلة‬

‫‪9.4 How a vector Grows‬‬ ‫‪ 9٫4‬كيف ينمو متجه‬

‫‪9.5 Additional string Operations‬‬ ‫‪ 9٫5‬عمليات سلسلة إضافية‬

‫‪9.6 Container Adaptors‬‬ ‫‪ 9٫6‬مكيفات الحاوية‬

‫‪Chapter Summary‬‬ ‫ملخــــــص الفصــــــل‬

‫‪Defined Terms‬‬ ‫مصطلحــــــات معرفــــــة‬

‫يتوسع هذا الفصل في موضوعات الفصل الثالث ويكمل مناقشتنا للحاويات املتسلسلة في املكتبة القياسية‪.‬‬
‫حيث ترتيب العنارص في الحاوية املتسلسلة يتوافق مع املواضع اليت يتم فيها إضافة عنارص إلى الحاوية‪.‬‬ ‫•‬
‫أيض ا عدة حاويات تجميعية ‪ ،‬تحتوي على عنارص يعتمد موضعها على مفتاح مرتبط بكل‬ ‫تعرف املكتبة ً‬
‫ّ‬ ‫•‬
‫عنرص‪.‬‬
‫سنغطي العمليات الخاصة بالحاويات التجميعية في الفصل الحادي عرش‪.‬‬ ‫•‬
‫تشرتك فئات الحاوية في واجهة مشرتكة ‪ ،‬واليت توسع كل حاوية بطريقتها الخاصة‪.‬‬
‫هذه الواجهة املشرتكة تجعل املكتبة أسهل في التعلم ؛‬ ‫•‬
‫فما نتعلمه عن نوع من الحاويات سينطبق على نوع آخر‪.‬‬ ‫•‬
‫يقدم كل نوع من الحاويات مجموعة مختلفة من مقايضات األداء والدوال‪.‬‬ ‫•‬
‫تحتوي الحاوية على مجموعة من الكائنات من نوع محدد‪.‬‬
‫تسمح الحاويات املتسلسلة للمربمج بالتحكم في الرتتيب الذي يتم به تخزين العنارص والوصول إليها‪.‬‬ ‫•‬
‫هذا الرتتيب ال يعتمد على قيم العنارص ؛ بل يتوافق مع املوضع الذي يتم فيه وضع العنارص في الحاوية‪.‬‬ ‫•‬
‫على النقيض من ذلك ‪،‬‬ ‫•‬
‫بناء على قيمة مفتاح‪.‬‬
‫ً‬ ‫تخزن الحاويات التجميعية مرتبة وغري مرتبة – سنغطيها في الفصل ‪ – 11‬عنارصها‬ ‫•‬
‫أيضا ثالثة مكيفات للحاويات ‪،‬‬
‫توفر املكتبة ً‬ ‫•‬
‫يتكيف كل منها مع نوع الحاوية من خالل تعريف واجهة مختلفة لعمليات الحاوية‪.‬‬ ‫•‬
‫سنغطي املكيفات في ختام هذا الفصل‪.‬‬ ‫•‬

‫ملحوظة‬

‫يبين هذا الفصل على املواد املشمولة في الفصل الثاني والثالث والرابع‪ .‬سنفرتض أنك على دراية بتلك املواد‪.‬‬
‫‪ . 9٫1‬الحــــــــــاويات الـمتــــــــــسلسلة ‪ :‬نظــــــــــرة عــــــــامة‬
‫‪9.1 Overview of the Sequential Containers‬‬

‫رسيعا إلى عنارصها‪.‬‬


‫ً‬ ‫تسلسليا‬
‫ً‬ ‫توفر جميع الحاويات املتسلسلة ‪ ،‬املدرجة في الجدول ‪ ، 9.1‬وصوال ً‬
‫• مع ذلك ‪ ،‬تقدم هذه الحاويات مقايضات أداء مختلفة بالنسبة إلى‬
‫تكاليف إضافة أو حذف العنارص إلى الحاوية‬ ‫•‬
‫تكاليف إجراء الوصول غري املتسلسل إلى عنارص الحاوية‬ ‫•‬

‫الجدول ‪ .9.1‬أنواع الحاويات املتسلسلة‬

‫‪Flexible-size array. Support fast random access. Inserting‬‬


‫‪vector‬‬
‫‪or deleting elements other than at the back may be slow.‬‬

‫‪Double-ended deque. Support fast random access. Fast insert‬‬


‫‪deque‬‬
‫‪or delete at front or back.‬‬

‫‪Doubly linked list. Support only bidirectional sequential‬‬


‫‪list‬‬
‫‪access. Fast insert or delete at any point in the list.‬‬

‫‪Singly linked list. Support only sequential access in one‬‬


‫‪forward_list‬‬
‫‪direction. Fast insert or delete at any point in the list.‬‬

‫‪Fixed-size array. Support fast random access. Can NOT add or‬‬
‫‪array‬‬
‫‪remove elements.‬‬

‫‪A specialized container, similar to vector that contain‬‬


‫‪string‬‬ ‫‪characters. Fast random access. Fast insert or delete at the‬‬
‫‪back.‬‬

‫باستثناء املصفوفة ‪ ،‬واليت هي حاوية ذات حجم ثابت ‪ ،‬توفر الحاويات إدارة ذاكرة فعالة ومرنة‪.‬‬
‫يمكننا إضافة وإزالة العنارص ‪ ،‬وزيادة حجم الحاوية وتقليصها‪.‬‬ ‫•‬
‫فاالسرتاتيجيات اليت تستخدمها الحاويات لتخزين عنارصها لها تأثري متأصل – وأحيا ًنا مهم – على كفاءة‬ ‫•‬
‫تلك العمليات‪.‬‬
‫أيضا على ما إن كانت حاوية معينة توفر عملية معينة‪.‬‬
‫في بعض الحاالت ‪ ،‬تؤثر هذه االسرتاتيجيات ً‬ ‫•‬
‫فعلى سبيل املثال ‪ ،‬السلسلة واملتجه يحتفظان بعنارصهما في ذاكرة متجاورة‪.‬‬ ‫•‬
‫ونظرًا ألن العنارص متجاورة ‪ ،‬فمن السهل حوسبة عنوان العنرص من الفهرس الخاص به‪.‬‬ ‫•‬
‫ومع ذلك ‪ ،‬فإن إضافة عنارص أو إزالتها في منتصف إحدى هذه الحاويات يستغرق وق ًتا‪:‬‬ ‫•‬
‫يجب نقل جميع العنارص بعد إدراجها أو إزالتها للحفاظ على االتصال‪.‬‬ ‫•‬
‫عالوة على ذلك ‪ ،‬قد تتطلب إضافة عنرص في بعض األحيان تعيني مساحة تخزين إضافية‪.‬‬ ‫•‬
‫في هذه الحالة ‪ ،‬يجب نقل كل عنرص إلى التخزين الجديد‪.‬‬ ‫•‬
‫تم تصميم حاويات القائمة والقائمة_اﻷمامية لترسيع إضافة عنرص أو إزالته في أي مكان من الحاوية‪.‬‬
‫في املقابل ‪ ،‬ال تدعم هذه األنواع وصوال ً عشوائياً إلى العنارص‪:‬‬ ‫•‬
‫• ال يمكننا الوصول إلى عنرص إال من خالل مكرر عرب الحاوية‪.‬‬
‫• عالوة على ذلك ‪ ،‬غالبًا ما تكون سعة الذاكرة لهذه الحاويات كبرية – عند مقارنتها باملتجه والطابور‬
‫واملصفوفة‪.‬‬
‫الطابور عبارة عن بنية بيانات أكرث تعقي ًدا‪ .‬يدعم مثل السلسلة واملتجه الوصول العشوائي الرسيع‪.‬‬
‫وكما هو حال السلسلة واملتجه ‪ ،‬فإن إضافة عنارص أو إزالتها في منتصفه عملية مكلفة (محتملة)‪.‬‬ ‫•‬
‫مع ذلك ‪ ،‬فإن إضافة أو إزالة عنارص في أي من طرفيه تعد عملية رسيعة ‪ ،‬يمكن مقارنتها بإضافة عنرص‬ ‫•‬
‫إلى قائمة أو قائمة_أمامية‪.‬‬

‫تمت إضافة أنواع املصفوفة والقائمة_اﻷمامية مع املعيار الجديد‪.‬‬


‫استخداما من املصفوفات املدمجة‪.‬‬
‫ً‬ ‫املصفوفة بديل أكرث أماناً وأسهل‬ ‫•‬
‫حجما ثاب ًتا‪.‬‬
‫ً‬ ‫تمتلك مصفوفات املكتبة مثل املصفوفات املدمجة‬ ‫•‬
‫ونتيجة لذلك ‪ ،‬ال تدعم مصفوفة املكتبة عمليات إضافة وإزالة عنارص أو تغيري حجم الحاوية‪.‬‬ ‫•‬
‫قُصد بالقائمة األمامية أن تكون قابلة للمقارنة مع أفضل قائمة مكتوبة بخط اليد ومرتبطة فردياً‪.‬‬ ‫•‬
‫بالتالي ‪ ،‬ال تحتوي القائمة_اﻷمامية على عملية حجم ألن تخزين أو حساب حجمها سيتطلب تكاليف‬ ‫•‬
‫إضافية مقارنة بقائمة مكتوبة بخط اليد‪.‬‬
‫بالنسبة للحاويات األخرى ‪ ،‬فقد ضمنت املكتبة أن تكون عملية الحجم رسيعة وثابتة الوقت‪.‬‬ ‫•‬

‫ملحوظة‬

‫ألسباب سنرشحها في الفقرة ‪، 13.6‬‬ ‫•‬


‫أصبحت حاويات املكتبة الجديدة أرسع بأشواط مما كانت عليه في إصدارات سابقة‪.‬‬ ‫•‬
‫أداء جي ًدا (وعادة ما تكون أفضل) حىت من البدائل األكرث دقة‪.‬‬
‫ً‬ ‫من شبه املؤكد أن تؤدي حاويات املكتبة‬ ‫•‬
‫يجب أن تستخدم برامج يس‪ ++‬الحديثة حاويات املكتبة بدال ً من هياكل بدائية كاملصفوفات‪.‬‬ ‫•‬

‫تحديد الحاوية املتسلسلة اليت سيتم استخدامها‬


‫‪Deciding Which Sequential Container to Use‬‬

‫تلميح‬

‫عادة ‪ ،‬من األفضل استخدام املتجه ما لم يكن هناك سبب وجيه لتفضيل حاوية أخرى‪.‬‬

‫هناك بعض القواعد األساسية اليت تنطبق على اختيار الحاوية املراد استخدامها ‪:‬‬
‫ما لم يكن لديك سبب الستخدام حاوية أخرى ‪ ،‬استخدم متجهاً‪.‬‬ ‫•‬
‫إن كان برنامجك يحتوي على الكثري من العنارص الصغرية واألمور املتعلقة باملساحة ‪،‬‬ ‫•‬
‫فال تستخدم القائمة أو القائمة_اﻷمامية‪.‬‬ ‫•‬
‫متجها أو الطابور‪.‬‬
‫ً‬ ‫عشوائيا إلى العنارص ‪ ،‬فاستخدم‬
‫ً‬ ‫إن كان الربنامج يتطلب وصوال ً‬ ‫•‬
‫إن احتاج الربنامج إلى إدراج عنارص أو حذفها في منتصف الحاوية ‪ ،‬فاستخدم قائمة أو قائمة_أمامية‪.‬‬ ‫•‬
‫إن احتاج الربنامج إلى إدراج عنارص أو حذفها في املقدمة والخلفية ‪ ،‬لكن ليس في املنتصف ‪ ،‬استخدم‬ ‫•‬
‫الطابور‪.‬‬
‫أما إن كان الربنامج يحتاج إلى إدراج عنارص في منتصف الحاوية فقط أثناء قراءة املدخالت ‪ ،‬وبالتالي يحتاج‬
‫وصوال ً عشوائياً إلى العنارص ‪:‬‬
‫• أوال ً ‪ ،‬حدد ما إن كنت تحتاج بالفعل إلى إضافة عنارص في منتصف الحاوية‪.‬‬
‫غالبا سيكون من األسهل اإللحاق بمتجه ثم استدعاء دالة املكتبة فرز (سنغطيها في فقرة ‪، )10.2.3‬‬
‫ً‬ ‫•‬
‫وذلك إلعادة ترتيب الحاوية عند االنتهاء من املدخالت‪.‬‬ ‫•‬
‫إن كان ال بد من اإلدراج في املنتصف ‪ ،‬ففكر في استخدام قائمة ملرحلة املدخالت‪.‬‬ ‫•‬
‫وبمجرد اكتمال مرحلة املدخالت تلك ‪ ،‬انسخ تلك القائمة إلى متجه‪.‬‬ ‫•‬
‫ماذا لو كان الربنامج يحتاج وصوال ً عشوائياً ويحتاج إلى مدخالت وحذف عنارص في منتصف الحاوية؟‬
‫سيعتمد هذا القرار على التكلفة النسبية للوصول إلى العنارص في قائمة أو قائمة_أمامية …‬ ‫•‬
‫في مقابل تكلفة إدراج أو حذف عنارص في متجه أو طابور‪.‬‬ ‫•‬
‫لكن بشكل عام ‪ ،‬ستحدد العملية السائدة للتطبيق اختيار نوع الحاوية (سواء كان ذلك وصوال ً أكرث أو مزيداً‬ ‫•‬
‫من اإلدراج أو الحذف)‪.‬‬
‫رضوريا‪.‬‬
‫ً‬ ‫في مثل تلك الحاالت ‪ ،‬يحتمل أن يكون اختبار األداء للتطبيق باستخدام كلتا الحاويتني‬ ‫•‬

‫أفضل املمارسات‬

‫إن لم تكن متأك ًدا من الحاوية اليت يجب استخدامها ‪،‬‬ ‫•‬
‫فاكتب كودك بحيث ال يستخدم إال عمليات مشرتكة بني كل من املتجهات والقوائم ‪:‬‬ ‫•‬
‫استخدم املكرر ‪ ،‬وليس الفهارس ‪ ،‬وتجنب الوصول العشوائي إلى العنارص‪.‬‬ ‫•‬
‫بهذه الطريقة سيكون من السهل استخدام متجه أو قائمة حسب الرضورة‪.‬‬ ‫•‬

‫تمارين القسم ‪9.1‬‬

‫التمرين ‪:9.1‬‬
‫‪ -‬ما هو األنسب ‪ -‬متجه ‪ ،‬أم طابور ‪ ،‬أم قائمة ‪ -‬ملهام الربنامج التالية؟‬
‫‪ -‬ارشح األساس املنطقي الختيارك‪.‬‬
‫‪ -‬إن لم يكن هناك سبب لتفضيل حاوية أو أخرى ‪ ،‬فرس لم ال‪.‬‬
‫أبجديا عند مدخالتها‪.‬‬
‫ً‬ ‫(أ) قراءة عدد ثابت من الكلمات ‪ ،‬مع مدخالتها في الحاوية‬
‫‪ -‬سرنى في الفصل التالي أن الحاويات التجميعية هي األنسب لهذه املشكلة‪.‬‬
‫(ب) قراءة عدد غري معروف من الكلمات‪.‬‬
‫‪ -‬إدراج الكلمات الجديدة دوما يكون في الخلف‪ .‬وإزالة القيمة التالية من األمام‪.‬‬
‫(ج) قراءة عدد غري معروف من أعداد صحيحة من ملف‪.‬‬
‫‪ -‬فرز األرقام ثم طباعتها على املخرجات القياسية‪.‬‬
‫ نظــــــــــرة عــــــــامة‬: ‫ مكتبــــــــة الحــــــــــاوية‬. 9٫2
9.2 Container Library Overview

:‫نوعا من التسلسل الهرمي‬


ً ‫تشكل العمليات على أنواع الحاويات‬
.‫ ) بواسطة جميع أنواع الحاويات‬9.2 ‫• يتم توفري بعض العمليات (الجدول‬

‫ عمليات الحاويات‬.9.2 ‫الجدول‬

Type Aliases

iterator Type of the iterator for this container type

Iterator type that can read but not change its


const_iterator
elements
Unsigned integral type big enough to hold the size of
size_type
the largest possible container of this container type
Signed integral type big enough to hold the distance
difference_type
between to iterators

value_type Element type

reference Element’s lvalue type; synonym for value_type&

const_reference Element’s const lvalue type(i.e., const value type&)

Construction

C c; Default constructor, empty container(array)

C c1(c2); Construct c1 as a copy of c2

Copy elements from the range denoted by iterators b


C c(b, e);
and e; (not valid for array)

C c{a,b,c…}; List initialize c

Assignment and swap

c1 = c2 Replace elements in c1 with those in c2

Replace elements in c1 with those in the list(not


c1 = {a,b,c…}
valid for array)
a.swap(b) Swap elements in a with those in b

swap(a,b) Equivalent to a.swap(b)

Size

c.size() Number of elements in c (not valid for forward_list)

c.max_size() Maximum number of elements c can hold

c.empty() False if c has any elements, true otherwise

Add/Remove Elements(not valid for array)

Note: the interface to these operations varies by container type

c.insert(args) Copy element(s) as specified by args into c

c.emplace(inits) Use inits to construct an element in c

c.erase(args) Remove element(s) specified by args

c.clear() Remove all elements from c; return void

Equality and Relational Operators

==, != Equality valid for all container types

Relationals(not valid for unordered associative


<, <=, >, >=
containers)

Obtain Iterators

c.begin(), Return iterator to the first, one past the last


c.end() element in c
c.cbegin(),
Return const_iterator
c.cend()

Additional Members of Reversible Containers(not valid for forward_list)

reverse_iterator Iterator that addresses elements in reverse order


const_reverse_
Reverse iterator that cannot write the elements
iterator
c.rbegin(), Return iterator to the first, one past the last
c.rend() element in c
c.crbegin(),
Return const_reverse_iterator
c.crend()

، ) ‫ أدناه‬9.3 ‫هناك عمليات أخرى خاصة باملتسلسلة ( الجدول‬ •


.)11.8 ‫ وعمليات أخرى للحاويات غري املرتبة (جدول‬، )11.7 ‫وعمليات خاصة بالتجميعية (جدول‬ •

‫ تعريف الحاويات وتهيئتها‬.9.3 ‫الجدول‬

Default constructor. If C is array, then the elements


C c;
in c are default-initialized; otherwise c is empty.

C1 is copy of c2. C1 and c2 must have the same type


C c1(c2) (i.e., they must be the same container type and hold
C c1 = c2 the same element type; for array must also have the
same size).

C is a copy of the elements in the initializer list.


Type of elements in the list must be compatible with
C c{a,b,c…}
the element type of C. for array, any missing
C c={a,b,c…}
elements are
value-initialized.

C is a copy of the elements in the range denoted by


iterators b and e. type of the elements must be
C c(b, e)
compatible with the element type of C. (Not valid for
array.)

Constructor that take a size are valid for sequential containers only
(not including array)

Seq has n value initialized elements; this


C seq(n)
constructor is explicit. (not valid for string)

C seq(n, t) Seq has n elements with value t.

.‫ال تزال بعض العمليات اﻷخرى شائعة في مجموعة فرعية أصغر من الحاويات‬ •
.‫ سنغطي الجوانب املشرتكة بني جميع الحاويات‬، ‫في هذا القسم‬ •
‫ثم يركز الجزء املتبقي من هذا الفصل فقط على الحاويات املتسلسلة ؛‬ •
‫بينما نغطي العمليات الخاصة بالحاويات التجميعية في الفصل الحادي عرش‪.‬‬ ‫•‬

‫بشكل عام ‪ ،‬يتم تعريف كل حاوية في ملف عنوان يحمل نفس اسم النوع‪.‬‬
‫هذا يعين أن الطابور موجود في العنوان طابور ‪ deque‬والقائمة في العنوان قائمة ‪ … list‬إلخ‪.‬‬ ‫•‬
‫الحاويات عبارة عن قوالب فئة ‪.‬‬ ‫•‬
‫وكما هو الحال مع املتجهات ‪ ،‬يجب علينا توفري معلومات إضافية إلنشاء نوع حاوية محدد‪.‬‬ ‫•‬
‫بالنسبة ملعظم الحاويات ‪ ،‬وليس كلها فإن املعلومات اليت يجب أن نقدمها هي نوع العنرص‪:‬‬ ‫•‬

‫‪list<Sales_data>   // list that holds Sales_data objects‬‬


‫‪deque<double>      // deque that holds doubles‬‬

‫القيود على أنواع ربما تحملها حاوية‬


‫‪Constraints on Types That a Container Can Hold‬‬

‫يمكن استخدام أي نوع تقريباً كنوع لعنرص حاوية متسلسلة‪.‬‬


‫تحديداً ‪ ،‬يمكننا تعريف حاوية نوع عنرصها هو نفسه حاوية أخرى‪.‬‬ ‫•‬
‫تماما كما نفعل مع أي نوع حاوية آخر‪:‬‬
‫ً‬ ‫نعرف مثل تلك الحاويات‬
‫ّ‬ ‫•‬
‫نحدد نوع العنرص (في هذه الحالة نوع حاوية) داخل أقواس الزاوية‪:‬‬ ‫•‬

‫;‪vector<vector<string>> lines‬‬ ‫‪// vector of vectors‬‬

‫خطوط ‪ lines‬هنا عبارة عن متجه تكون عنارصه متجهات سالسل‪.‬‬ ‫•‬

‫ملحوظة‬

‫قد تتطلب برامج الرتجمة األقدم مسافة بني قويس الزاوية ‪ ،‬مثالً ‪.vector<vector<string< < :‬‬

‫تقريبا في حاوية ‪،‬‬


‫ً‬ ‫وعلى الرغم من أنه يمكننا تخزين أي نوع‬ ‫•‬
‫إال أن بعض عمليات الحاوية تفرض متطلبات خاصة بها على نوع العنرص‪.‬‬ ‫•‬
‫يمكننا تعريف حاوية لنوع ال يدعم متطلبات عملية محددة ‪،‬‬ ‫•‬
‫ولكن ال يمكننا استخدام عملية إال إن كان نوع العنرص يليب متطلبات تلك العملية‪.‬‬ ‫•‬
‫على سبيل املثال ‪ ،‬تستخدم ُمنشئة حاوية متسلسلة تأخذ وسيطة حجم ُمنشئة افرتاضية لنوع العنرص‪.‬‬ ‫•‬
‫ال تحتوي بعض الفئات على ُمنشئة افرتاضية‪.‬‬ ‫•‬
‫يمكننا تعريف حاوية تحتوي على كائنات من ذلك النوع ‪،‬‬ ‫•‬
‫لكن ال يمكننا إنشاء مثل هذه الحاويات باستخدام عدد العنارص فقط‪:‬‬ ‫•‬

‫‪// assume noDefault is a type without a default constructor‬‬


‫‪vector<noDefault> v1(10, init); // ok: element initializer supplied‬‬
‫‪vector<noDefault> v2(10); // error: must supply element initializer‬‬

‫بينما نصف عمليات الحاوية ‪ ،‬سنالحظ قيوداً إضافية ‪ ،‬إن وجدت ‪ ،‬تضعها كل عملية حاوية على نوع العنرص‪.‬‬

‫تمارين القسم ‪9.2‬‬

‫التمرين ‪:9.2‬‬
‫عرف قائمة تحتوي على عنارص طابور تحمل ‪.ints‬‬
‫ّ‬

‫‪9.2.1. Iterators‬‬ ‫‪ 9٫2٫1‬املكررات‬

‫كما هو الحال مع الحاويات ‪ ،‬فإن املكررات لها واجهة مشرتكة ‪:‬‬


‫إن كان املكرر يوفر عملية ‪ ،‬فسيتم دعم العملية بنفس الطريقة لكل مكرر يوفر هذه العملية‪.‬‬ ‫•‬
‫على سبيل املثال ‪ ،‬جميع املكررات في أنواع الحاويات القياسية تسمح لنا بالوصول إلى عنرص من حاوية ‪،‬‬ ‫•‬
‫وكلها تفعل ذلك من خالل توفري عامل إلغاء املرجع‪.‬‬ ‫•‬
‫تعرف جميعها عامل الزتايد لالنتقال من عنرص آلخر‪.‬‬
‫وباملثل ‪ ،‬فإن املكررات الخاصة بحاويات املكتبة ّ‬ ‫•‬
‫باستثناء واحد ‪ ،‬تدعم مكررات الحاوية جميع العمليات املدرجة في الجدول‪.‬‬
‫االستثناء هو أن مكررات القائمة_اﻷمامية ال تدعم عامل التناقص (‪.)-‬‬ ‫•‬
‫تنطبق العمليات الحسابية للمكرر املدرجة في الجدول ‪ 3.7‬فقط على مكررات السلسلة واملتجه والطابور‬ ‫•‬
‫واملصفوفة‪.‬‬
‫ال يمكننا استخدام هذه العمليات على املكررات ألي من أنواع الحاويات األخرى‪.‬‬ ‫•‬

‫‪Iterator Ranges‬‬ ‫نطاقات املكرر‬

‫ملحوظة‬

‫يعد نطاق املكرر مفهوماً أساسياً في املكتبة القياسية‪.‬‬

‫يتم اإلشارة إلى نطاق املكرر بزوج من املكررات يشري كل منهما إلى عنرص ‪ ،‬أو ما بعد آخر عنرص في نفس الحاوية‪.‬‬
‫يُشار إلى هذين املكررين ‪ ،‬غالباً باسم بداية_ ونهاية_ ‪ -‬أو (بشكل مضلل تقريباً) باألول واألخري ‪-‬‬ ‫•‬
‫حيث يحددان نطاقاً من عنارص حاوية‪.‬‬ ‫•‬
‫تسمية األخري ‪ ،‬بالرغم من استخدامه بشكل شائع ‪ ،‬مضلل قليالً ‪،‬‬ ‫•‬
‫ألن املكرر الثاني ال يشري بداية_ إلى آخر عنرص في النطاق‪.‬‬ ‫•‬
‫بل يشري إلى نقطة تأتي بعد آخر عنرص‪.‬‬ ‫•‬
‫تشمل عنارص النطاق العنرص املشار إليه أوال ً وكل عنرص من أول النطاق إلى األخري دون أن يشمل األخري‪.‬‬ ‫•‬
‫يسمى نطاق العنرص هذا بالنطاق الشامل لليسار‪ .‬الكود الريايض القيايس ملثل هذا النطاق هو‬ ‫•‬

‫)‪[ begin, end‬‬


‫ليشري إلى أن النطاق يبدأ ببداية_‪ begin‬وينتهي بـ نهاية_ ‪ ، end‬دون أن يشمل نهاية_ ‪. end‬‬ ‫•‬
‫يجب أن يشري مكررا بداية_ ونهاية_ إلى نفس الحاوية‪.‬‬ ‫•‬
‫قد يكون مكرر نهاية_ مساوياً لبداية_ لكن يجب أال يشري إلى عنرص قبل الذي يُشري إليه بداية_‪.‬‬ ‫•‬

‫متطلبات املكررات لتشكيل نطاق املكرر‬

‫يشكل املكرران ‪ ،‬بداية_ونهاية_‪ ،‬نطاق مكرر ‪ ،‬إذا ‪:‬‬


‫كانا يشريان إلى عنارص من نفس الحاوية ‪ ،‬أو ما بعد نهاية_واحدة ‪ ،‬و‬ ‫•‬
‫أمكن الوصول إلى نهاية_عن طريق مزايدة بداية_بشكل متكرر‪ .‬بمعىن آخر ‪ ،‬يجب أال تسبق نهاية_بداية‪.‬‬ ‫•‬

‫تحذير‬

‫ال يستطيع املرتجم تنفيذ هذه املتطلبات‪ .‬األمر مرتوك لنا للتأكد من أن برامجنا تتبعها‪.‬‬

‫آثار الربمجة باستخدام النطاق الشامل لليسار‬


‫‪Programming Implications of Using Left-Inclusive Ranges‬‬

‫تستخدم املكتبة النطاقات الشاملة لليسار ألن لها ثالث خصائص مالئمة‪.‬‬
‫فبافرتاض أن بداية_ونهاية_تدالن على نطاق مكرر صالح ‪ ،‬إذن‬ ‫•‬
‫إن كانت بداية_تساوي نهاية_‪ ،‬فإن النطاق فارغ‬ ‫•‬
‫إن كانت بداية_ال تساوي نهاية_‪ ،‬فهناك عنرص واحد على األقل في النطاق ‪ ،‬وتشري بداية_ألول عنرص فيه‬ ‫•‬
‫يمكننا أن نزايد بداية_عد ًدا من املرات حىت تتساوى بداية_مع نهاية_‬ ‫•‬
‫هذه الخصائص تعين أنه يمكننا كتابة حلقات بأمان مثل ما يلي ملعالجة مجموعة من العنارص ‪:‬‬ ‫•‬

‫{ )‪while (begin != end‬‬


‫;‪    *begin = val‬‬ ‫‪// ok: range isn't empty so begin denotes an element‬‬
‫;‪    ++begin‬‬ ‫‪// advance the iterator to get the next element‬‬
‫}‬

‫بالنظر إلى أن بداية_ونهاية_تشكالن نطاق مكرر صالح ‪،‬‬ ‫•‬


‫فارغا‪ .‬وفي هذه الحالة ‪ ،‬نخرج من الحلقة‪.‬‬
‫ً‬ ‫فإننا نعلم أنه إن تساوت بداية_مع نهاية_‪ ،‬فالنطاق يكون‬ ‫•‬
‫أما إن كان النطاق غري فارغ ‪ ،‬فنحن نعلم أن بداية_تشري لعنرص في ذلك النطاق غري الفارغ‪.‬‬ ‫•‬
‫لذلك ‪ ،‬داخل بنية ‪ ، while‬نعلم أنه من اآلمن إلغاء اإلشارة املرجعية عن بداية_؛‬ ‫•‬
‫وذلك ألن بداية_يجب أن تشري إلى عنرص‪.‬‬ ‫•‬
‫أيضا أن الحلقة ستنتهي عند نهاية‪.‬‬
‫أخريًا ‪ ،‬نظرًا ألن تزايد بداية_هو بنية الحلقة ‪ ،‬فنحن نعلم ً‬ ‫•‬

‫تمارين القسم ‪9.2.1‬‬

‫التمرين ‪: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) /* ... */‬‬

‫‪9.2.2. Container Type Members‬‬ ‫‪ 9٫2٫2‬أعضاء نوع الحاوية‬

‫تعرف كل حاوية عدة أنواع ‪ ،‬كما هو موضح في جدول ‪.9.2‬‬


‫ّ‬
‫املعرفة بالحاوية‪ ، size_type :‬واملكرر ‪ ،‬واملكرر_الثابت ‪.‬‬
‫ّ‬ ‫فقد استخدمنا بالفعل ثالثة من هذه األنواع‬ ‫•‬
‫إضافة إلى أنواع املكرر اليت استخدمناها ‪ ،‬توفر معظم الحاويات مكررات عكسية‪.‬‬ ‫•‬
‫املكرر العكيس باختصار هو مكرر يتجه للخلف عرب الحاوية ويعكس معىن عملياته‪.‬‬ ‫•‬
‫فمثالً ‪ ،‬يؤدي إعطاء ‪ ++‬على مكرر عكيس إلى العنرص السابق‪.‬‬ ‫•‬
‫سيكون لدينا املزيد لنقوله حول املكررات العكسية في الفقرة ‪.10.4.3‬‬ ‫•‬
‫تسمح لنا أسماء النوع املستعارة املتبقية باستخدام نوع العنارص املخزنة في حاوية دون معرفة ما هية النوع‪.‬‬
‫فإن احتجنا إلى نوع العنرص ‪ ،‬فإننا نشري إلى نوع الحاوية ‪.value_type‬‬ ‫•‬
‫وإن احتجنا إلى مرجع لذلك النوع ‪ ،‬فإننا نستخدم املرجع أو ‪.const_reference‬‬ ‫•‬
‫هذه األسماء املستعارة ذات الصلة بالعنارص مفيدة للغاية في الربامج الشاملة ‪ ،‬وسنغطيها في الفصل ‪.16‬‬ ‫•‬
‫الستخدام أحد هذه األنواع ‪ ،‬يجب علينا تسمية الفئة اليت هم أعضاء فيها‪:‬‬

‫>‪// iter is the iterator type defined by list<string‬‬


‫;‪list<string>::iterator iter‬‬
‫>‪// count is the difference_type type defined by vector<int‬‬
‫;‪vector<int>::difference_type count‬‬

‫تستخدم هذه اإلعالنات عامل النطاق لتخرب بأننا نريد عضو املكرر لفئة قائمة<سلسلة> و‬ ‫•‬
‫املعرف بواسطة متجه <‪ ، >int‬على التوالي‪.‬‬ ‫ّ‬ ‫‪difference_type‬‬
‫قسم التدريبات ‪9.2.2‬‬

‫تمرين ‪:9.7‬‬
‫ما هو النوع الذي يجب استخدامه كمؤرش في متجه ‪ints‬؟‬

‫التمرين ‪:9.8‬‬
‫ما النوع الذي يجب استخدامه لقراءة العنارص املوجودة في قائمة السالسل؟ ولكتابتها؟‬

‫‪9.2.3. begin and end Members‬‬ ‫‪ 9٫2٫3‬اﻷعضاء بداية_ ونهاية_‬

‫ينتج عن عملييت بداية_ونهاية_ مكرران يشريان ﻷول عنرص وآخر عنرص في الحاوية‪.‬‬
‫غالباً ما يستخدم هذان املكرران لتشكيل نطاق مكرر يشمل كل العنارص املوجودة في الحاوية‪.‬‬ ‫•‬
‫وكما هو مبني في الجدول ‪ ، 9.2‬هناك العديد من اإلصدارات من بداية_ ونهاية_ ‪:‬‬ ‫•‬
‫فاإلصدارات اليت تحتوي على ‪ r‬تعترب مكررات عكسية (سنغطيها في فقرة ‪.)10.4.3‬‬ ‫•‬
‫أما تلك اليت تبدأ بحرف ‪ c‬فتعيد اإلصدار الثابت للمكرر ذي الصلة‪:‬‬ ‫•‬
‫الدوال اليت ال تبدأ بحرف ‪ c‬تعترب زائدة التعبئة‪ .‬هذا يعين أنه يوجد في الواقع عضوان باسم "بداية_"‪.‬‬
‫أحدهما عضو ثابت يقوم بإعادة نوع مكرر حاوية ثابت‪.‬‬ ‫•‬
‫أما اآلخر فغري ثابت ويعيد نوع مكرر حاوية‪.‬‬ ‫•‬
‫واألمر نفسه بالنسبة لـ ‪ rbegin‬و ‪ end‬و ‪.rend‬‬ ‫•‬
‫مكررا‪.‬‬
‫ً‬ ‫عندما نستدعي إحدى تلك األعضاء على كائن غري ثابت ‪ ،‬نحصل على اإلصدار الذي يعيد‬ ‫•‬
‫وﻻ نحصل على نسخة ثابتة من املكررات إﻻ عندما نستدعي هذه الدوال على كائن ثابت‪.‬‬ ‫•‬
‫وكما هو حال املؤرشات واملراجع لثابت ‪ ،‬يمكننا تحويل مكرر عادي إلى الثابت املقابل ‪ ،‬لكن ليس العكس‪.‬‬ ‫•‬
‫تم تقديم إصدارات ‪ c‬بواسطة املعيار الجديد لدعم استخدام النوع التلقائي مع بداية_ ونهاية_ ‪.auto‬‬
‫ففي املايض ‪ ،‬لم يكن لدينا خيار سوى تعريف نوع املكرر الذي نريده‪:‬‬ ‫•‬
‫عندما نستخدم ‪ auto‬مع بداية_ أو نهاية_ ‪ ،‬سيعتمد نوع املكرر الذي نحصل عليه على نوع الحاوية‪.‬‬ ‫•‬
‫أما كيف نعزتم استخدام ذلك املكرر فغري ذي صلة‪.‬‬ ‫•‬
‫تتيح لنا إصدارات ‪ c‬الحصول على مكرر_ثابت برصف النظر عن نوع الحاوية‪.‬‬ ‫•‬

‫أفضل املمارسات‬

‫عندما ال تكون هناك حاجة إلى حق الوصول للكتابة ‪ ،‬استخدم بداية_ث ‪ cbegin‬ونهاية_ث ‪.cend‬‬

‫قسم التدريبات ‪9.2.3‬‬

‫تمرين ‪: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‬‬

‫‪ 9٫2٫4‬تعريف وتهيئة حاوية‬


‫‪9.2.4. Defining and Initializing a Container‬‬

‫يعرف كل نوع حاوية ُمنشئة افرتاضية‪.‬‬


‫ّ‬
‫املعرف‪.‬‬
‫ّ‬ ‫وباستثناء املصفوفة ‪ ،‬تنئش املُنشئة االفرتاضية حاوية فارغة من النوع‬ ‫•‬
‫وباستثناء املصفوفة (أيضاً)‪ ،‬تأخذ املنشئات األخرى وسيطات تحدد حجم الحاوية والقيم األولية للعنارص‪.‬‬ ‫•‬

‫تهيئة حاوية كنسخة من حاوية أخرى‬


‫‪Initializing a Container as a Copy of Another Container‬‬

‫هناك طريقتان إلنشاء حاوية جديدة كنسخة من أخرى‪:‬‬


‫يمكننا نسخ الحاوية مبارشة ‪ ،‬أو يمكننا نسخ مجموعة عنارص يشري إليها زوج مكررات (ما عدا املصفوفة)‪.‬‬ ‫•‬
‫إلنشاء حاوية كنسخة من حاوية أخرى ‪ ،‬يجب أن تتطابق أنواع الحاويتني وأنواع العنارص‪.‬‬ ‫•‬
‫عندما نجتاز املكررات ‪ ،‬ال يوجد رشط بأن تكون أنواع الحاويات متطابقة‪.‬‬ ‫•‬
‫عالوة على ذلك ‪ ،‬قد تختلف أنواع العنارص في الحاويات الجديدة واألصلية ؛‬ ‫•‬
‫طاملا كان من املمكن تحويل العنارص اليت نقوم بنسخها إلى نوع عنرص الحاوية اليت نقوم بتهيئتها ‪:‬‬ ‫•‬

‫‪// 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‬يمكننا كتابة‬ ‫•‬

‫‪// copies up to but not including the element denoted by it‬‬


‫;)‪deque<string> authList(authors.begin(), it‬‬

‫‪List Initialization‬‬ ‫تهيئة القائمة‬

‫بموجب املعيار الجديد ‪ ،‬يمكننا تهيئة حاوية تهيئة قائمة ‪:‬‬

‫‪// each container has three elements, initialized from given initializers‬‬
‫;}"‪list<string> authors = {"Milton", "Shakespeare", "Austen‬‬
‫;}"‪vector<const char*> articles = {"a", "an", "the‬‬

‫عندما نفعل ذلك ‪ ،‬نحدد رصاحة قيمة لكل عنرص في الحاوية‪.‬‬ ‫•‬
‫أيضا حجم الحاوية بشكل ضمين‪:‬‬
‫بالنسبة ألنواع أخرى غري املصفوفة ‪ ،‬تحدد تهيئة القائمة ً‬ ‫•‬
‫ستحتوي الحاوية على عدد عنارص بنفس عدد املُهئي‪.‬‬ ‫•‬

‫املنشئات املرتبطة بحجم الحاوية املتسلسلة‬


‫‪Sequential Container Size-Related Constructors‬‬

‫باإلضافة إلى امل ُ ِ‬


‫نش ئات اليت تشرتك فيها الحاويات املتسلسلة مع الحاويات التجميعية ‪،‬‬
‫ومهئي عنرص (اختياري)‪.‬‬
‫أيضا تهيئة الحاويات املتسلسلة على حجم ُ‬
‫يمكننا (بخالف املصفوفة) ً‬ ‫•‬
‫إن لم نوفر ُمهئي عنرص ‪ ،‬فإن املكتبة تُنئش قيمة ُمهيأة لنا ‪:‬‬ ‫•‬

‫‪vector<int> ivec(10, -1);      // 10 int elements, each initialized to -1‬‬


‫"!‪list<string> svec(10, "hi!");  // 10 strings; each element is "hi‬‬
‫‪forward_list<int> ivec(10);    // 10 elements, each initialized to 0‬‬
‫‪deque<string> svec(10);        // 10 elements, each an empty string‬‬

‫يمكننا استخدام ُمنشئة تأخذ وسيطة حجم إن كان نوع العنرص مدمجاً أو فئة لها ُمنشئة افرتاضية‪.‬‬ ‫•‬
‫أما إن كان نوع العنرص ال يملك ُمنشئة افرتاضية ‪ ،‬فيجب تعريف ُمهئي عنرص واضح مع الحجم‪.‬‬ ‫•‬

‫ملحوظة‬

‫املُنشئات اليت تأخذ حجماً تعد صالحة فقط للحاويات املتسلسلة ؛ لن يتم دعمها في الحاويات التجميعية‪.‬‬
‫‪Library arrays Have Fixed Size‬‬ ‫مصفوفات املكتبة حجمها ثابت‬

‫جزءا من نوعها ‪ ،‬فإن حجم مصفوفة املكتبة جزء من نوعها كذلك‪.‬‬


‫ً‬ ‫مثلما يكون حجم املصفوفة املدمجة‬
‫أيضا حجم الحاوية ‪:‬‬
‫سنعرف ً‬
‫ّ‬ ‫نعرف مصفوفة ‪ ،‬باإلضافة إلى تعريف نوع عنرصها ‪،‬‬
‫عندما ّ‬ ‫•‬

‫‪array<int, 42>    // type is: array that holds 42 ints‬‬


‫‪array<string, 10> // type is: array that holds 10 strings‬‬

‫والستخدام نوع مصفوفة ‪ ،‬يجب تعريف نوع العنرص وحجمه‪:‬‬

‫‪array<int, 10>::size_type i; // array type includes element type and size‬‬


‫‪array<int>::size_type j;     // error: array<int> is not a type‬‬

‫وألن الحجم جزء من نوع املصفوفة ‪ ،‬فإنها ال تدعم منشئات الحاوية العادية‪.‬‬ ‫•‬
‫تعرف تلك املنشئات ‪ ،‬ضمناً أو رصاحة ‪ ،‬حجم الحاوية‪.‬‬
‫ّ‬ ‫•‬
‫سيكون ذلك التعريف زائداً عن الحاجة (بأحسن األحوال) وعرضة للخطأ ‪،‬‬ ‫•‬
‫• بسبب السماح للمستخدمني بتمرير وسيطة حجم إلى ُمنشئة مصفوفة‪.‬‬
‫تعرفها املصفوفة‪.‬‬
‫أيضا على سلوك املنشئات اليت ّ‬
‫تؤثر طبيعة املصفوفات ذات الحجم الثابت ً‬
‫لكن على عكس الحاويات األخرى ‪ ،‬فإن املصفوفة اليت لها ُمنشئة افرتاضية ليست فارغة ‪:‬‬ ‫•‬
‫فهي تحتوي على عدد عنارص بنفس حجمها‪.‬‬ ‫•‬
‫تماما مثل العنارص في املصفوفة املدمجة‪.‬‬
‫ً‬ ‫هذه العنارص ستكون مهيأة افرتاضياً‬ ‫•‬
‫إن هيئنا املصفوفة تهيئة قائمة ‪ ،‬فيجب أن يكون عدد املهيئات مساوياً لحجم املصفوفة أو أقل‪.‬‬ ‫•‬
‫فإن كان هناك عدد املهيئات أقل من حجم املصفوفة ‪،‬‬ ‫•‬
‫سيتم استخدام املُهيئات للعنارص األولى وسيتم تهيئة أية عنارص متبقية‪.‬‬ ‫•‬
‫في كال الحالتني ‪ ،‬إن كان نوع العنرص نوع فئة ‪ ،‬يجب أن يكون للفئة ُمنشئة افرتاضية تسمح بتهيئة قيمة‪:‬‬ ‫•‬

‫‪array<int, 10> ia1;  // ten default-initialized ints‬‬


‫‪array<int, 10> ia2 = {0,1,2,3,4,5,6,7,8,9};  // list initialization‬‬
‫‪array<int, 10> ia3 = {42};  // ia3[0] is 42, remaining elements are 0‬‬

‫تجدر اإلشارة إلى بالرغم من أننا ال نستطيع نسخ أو تعيني كائنات أنواع املصفوفات املدمجة ‪ ،‬فال يوجد‬ ‫•‬
‫مثل هذا التقييد على املصفوفة ‪:‬‬

‫;}‪int digs[10] = {0,1,2,3,4,5,6,7,8,9‬‬


‫‪int cpy[10] = digs;  // error: no copy or assignment for built-in arrays‬‬
‫;}‪array<int, 10> digits = {0,1,2,3,4,5,6,7,8,9‬‬
‫‪array<int, 10> copy = digits;  // ok: so long as array types match‬‬

‫كما هو الحال مع أي حاوية ‪ ،‬يجب أن يكون للمهئي نفس نوع الحاوية اليت نقوم بإنشائها‪.‬‬ ‫•‬
‫بالنسبة إلى املصفوفات ‪ ،‬يجب أن يكون نوع العنرص والحجم متماثلني ‪،‬‬ ‫•‬
‫ذلك ألن حجم املصفوفة جزء من نوعها‪.‬‬ ‫•‬

‫قسم التدريبات ‪9.2.4‬‬

‫التمرين ‪:9.11‬‬
‫‪ -‬اعرض مثاال ً لكل طريقة من الطرق الست إلنشاء متجه وتهيئته‪.‬‬
‫‪ -‬ارشح القيم اليت يحتوي عليها كل متجه‪.‬‬

‫التمرين ‪:9.12‬‬
‫‪ -‬ارشح االختالفات بني منشئة تأخذ حاوية لنسخها ومنشئة تأخذ مكررين‪.‬‬

‫التمرين ‪:9.13‬‬
‫‪ -‬كيف تقوم بتهيئة املتجه <‪ >double‬من قائمة <‪>int‬؟ من متجه <‪>int‬؟‬
‫‪ -‬اكتب الكود للتحقق من إجاباتك‪.‬‬

‫‪9.2.5. Assignment and swap‬‬ ‫‪ 9٫2٫5‬التعيني واملبادلة‬

‫تعمل العامالت ذات الصلة بالتعيني ‪ ،‬املدرجة في الجدول ‪( 9.4‬أدناه) على الحاوية بأكملها‪.‬‬
‫يستبدل عامل التعيني النطاق الكامل للعنارص في الحاوية اليرسى بنسخ من عنارص املعامل األيمن‪:‬‬ ‫•‬

‫‪c1 = c2;      // replace contents of c1 with a copy of elements in c2‬‬


‫‪c1 = {a,b,c}; // after assignment c1 has size 3‬‬

‫بعد أول تعيني ‪ ،‬الحاويات اليمىن واليرسى ستكون متساوية‪.‬‬ ‫•‬


‫أما إن لم يكن حجم الحاويات متسا ٍو ‪ ،‬فبعد التعيني سيكون لكلتا الحاويتني حجم املعامل األيمن‪.‬‬ ‫•‬
‫بعد التعيني الثاني ‪ ،‬يكون حجم ‪ c1‬هو ‪ ، 3‬وهو عدد القيم املتوفرة في القائمة ذات اﻷقواس‪.‬‬ ‫•‬
‫وعلى عكس املصفوفات املدمجة ‪ ،‬يسمح نوع مصفوفة املكتبة بالتعيني‪.‬‬ ‫•‬
‫لكن يجب أن يكون للمعامالت اليمىن واليرسى نفس النوع‪:‬‬ ‫•‬

‫;}‪array<int, 10> a1 = {0,1,2,3,4,5,6,7,8,9‬‬


‫‪array<int, 10> a2 = {0}; // elements all have value 0‬‬
‫‪a1 = a2;  // replaces elements in a1‬‬
‫‪a2 = {0}; // error: cannot assign to array from braced list‬‬
، ‫ونظرًا ألن حجم املعامل األيمن قد يختلف عن حجم املعامل األيرس‬ •
.‫فإن نوع املصفوفة ال يدعم وال يسمح بالتعيني على قائمة القيم املقوسة‬ •

‫ عمليات تعيني الحاويات‬.9.4 ‫الجدول‬

Replace the elements in c1 with copies of the elements


c1 = c2
c2. C1 and c2 must be the same type.

Replace the elements in c1 with copies of the elements


c = {a,b,c …}
in initializer list. (NOT valid for array.)
Exchanges elements in c1 with those in c2. C1 and c2
swap(c1,c2)
must be the same type. Swap is usually much faster than
c1.swap(c2)
copying elements from c2 to c1.

assign operations not valid for associative containers or array

Replace the elements in seq with those in the range


seq.assign(b,e) denoted by iterators b and e. the iterators b and e
must not refer to elements in seq.
Replace the elements in seq with those in the
seq.assign(i1)
initializer list i1.

seq.assign(n,t) Replace elements in seq with n elements with value t.

‫تحذير‬

‫تؤدي العمليات املرتبطة بالتعيني إلى إبطال املكررات واملراجع واملؤرشات في الحاوية اليرسى‬
.‫ وباستثناء املصفوفات يتم تبديل الحاويات اليت تشري إليها‬.‫ ستظل صالحة بعد املبادلة‬، ‫ما عدا السلسلة‬

)‫استخدام التعيني (للحاويات املتسلسلة فقط‬


Using assign (Sequential Containers Only)

.‫يتطلب عامل التعيني أن يكون للمعامالت اليرسى واليمىن نفس النوع‬


.‫حيث يقوم بنسخ العنارص كلها من املعامل األيمن إلى املعامل األيرس‬ •
‫ يتيح لنا التعيني على نوع‬assign ‫أيضا عض ًوا باسم‬ً )‫تعرف الحاويات املتسلسلة (باستثناء املصفوفة‬ّ •
.‫ أو التعيني على تسلسل حاوية‬، ً‫مختلف برشط أن يكون متوافقا‬
.‫تستبدل عملية التعيني العنارص كلها في الحاوية اليرسى (تنسخها من) العنارص املحددة بوسيطاتها‬ •
: ‫ من متجه على قائمة سلسلة‬char* ‫ لتعيني نطاق قيم مؤرش حرف‬assign ‫ يمكننا استخدام‬، ً‫فمثال‬ •

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‬عدد العنارص والقيم اليت ستحتوي عليها الحاوية‪.‬‬ ‫•‬

‫تحذير‬

‫نظراً ﻷن العنارص املوجودة قد استبدلت ‪،‬‬ ‫•‬


‫يجب أال تشري مكررات يتم تمريرها لـ ‪ assign‬إلى الحاوية اليت قمنا باستدعاء ‪ assign‬عليها‪.‬‬ ‫•‬

‫النسخة الثانية من ‪ assign‬تأخذ قيمة عدد صحيح وقيمة عنرص‪.‬‬ ‫•‬


‫حيث يستبدل العنارص في الحاوية بعدد محدد من العنارص ‪ ،‬لكل منها قيمة العنرص املحددة‪:‬‬ ‫•‬

‫;)(‪// equivalent to slist1.clear‬‬


‫;)"!‪// followed by slist1.insert(slist1.begin(), 10, "Hiya‬‬
‫‪list<string> slist1(1);     // one element, which is the empty string‬‬
‫! ‪slist1.assign(10, "Hiya!"); // ten elements; each one is Hiya‬‬

‫‪Using swap‬‬ ‫استخدام املبادلة‬

‫تقوم عملية املبادلة بتبادل محتويات حاويتني من نفس النوع‪ .‬بعد استدعاء مبادلة ‪ ،‬يتم مبادلة العنارص في‬
‫الحاويتني ‪:‬‬

‫‪vector<string> svec1(10); // vector with ten elements‬‬


‫‪vector<string> svec2(24); // vector with 24 elements‬‬
‫;)‪swap(svec1, svec2‬‬

‫بعد املبادلة ‪ ،‬يحتوي ‪ svec1‬على ‪ 24‬عنرص سلسلة بينما سيحتوي ‪ svec2‬على عرشة‪.‬‬ ‫•‬
‫باستثناء املصفوفات ‪ ،‬فإن مبادلة حاويتني تضمن املكتبة رسعته ؛‬ ‫•‬
‫إذ ﻻ يتم تبديل العنارص نفسها ؛ بل يتم تبديل هياكل البيانات الداخلية‪.‬‬ ‫•‬

‫ملحوظة‬

‫باستثناء املصفوفة ‪ ،‬ال تنسخ مبادلة أو تحذف أو تدرج أية عنارص وهي مضمونة العمل في وقت ثابت‪.‬‬

‫حقيقة عدم تحريك العنارص تعين أنه – وباستثناء السلسلة – لن يتم إبطال مكرر أو مراجع أو مؤرش في الحاويات‪.‬‬
‫بل ستشري إلى نفس العنارص كما كانت قبل املبادلة‪.‬‬ ‫•‬
‫ومع ذلك ستكون تلك العنارص بعد املبادلة في حاوية مختلفة‪.‬‬ ‫•‬
‫فمثالً ‪ ،‬إن كانت ‪ iter‬تشري إلى سلسلة في الفهرس ]‪ svec1[3‬قبل املبادلة ‪،‬‬ ‫•‬
‫فستشري إلى العنرص في الفهرس ]‪ svec2[3‬بعد املبادلة‪.‬‬ ‫•‬
‫وبشكل مختلف عن الحاويات ‪ ،‬قد تؤدي مبادلة على سلسلة إلى إبطال مكررات ومراجع ومؤرشات‪.‬‬ ‫•‬
‫وعلى عكس الطريقة اليت تترصف بها مبادلة مع الحاويات األخرى ‪،‬‬ ‫•‬
‫فإن مبادلة مصفوفتني سيؤدي إلى تبادل العنارص‪.‬‬ ‫•‬
‫نتيجة لذلك ‪ ،‬يتطلب مبادلة مصفوفتني وق ًتا يتناسب مع عدد العنارص في املصفوفة‪.‬‬ ‫•‬
‫بعد مبادلة ‪ ،‬ستظل املؤرشات واملراجع واملكررات مرتبطة بنفس العنرص الذي تشري إليه قبل التبادل‪.‬‬ ‫•‬
‫بالطبع ‪ ،‬تم تبادل قيمة ذلك العنرص بالعنرص املقابل في املصفوفة األخرى‪.‬‬ ‫•‬

‫في املكتبة الجديدة ‪ ،‬تقدم الحاويات إصداري مبادلة لألعضاء وغري األعضاء‪.‬‬
‫عرفت اإلصدارات السابقة للمكتبة إصدار العضو من املبادلة فقط‪.‬‬
‫ّ‬ ‫•‬
‫تعترب مبادلة لغري األعضاء ذات أهمية قصوى في الربامج الشاملة‪.‬‬ ‫•‬
‫ولكن كعادة ‪ ،‬من األفضل استخدام نسخة مبادلة لغري األعضاء‪.‬‬ ‫•‬

‫قسم التدريبات ‪9.2.5‬‬

‫التمرين ‪:9.14‬‬
‫برنامجا لتعيني العنارص من قائمة مؤرشات ‪ char‬إلى سالسل أحرف نمط ‪ C‬إلى متجه من السالسل‪.‬‬
‫ً‬ ‫‪ -‬اكتب‬

‫‪9.2.6. Container Size Operations‬‬ ‫‪ 9٫2٫6‬عمليات حجم الحاوية‬

‫باستثناء واحد ‪ ،‬تحتوي أنواع الحاويات على ثالث عمليات تتعلق بالحجم‪.‬‬
‫يعيد العضو حجم ‪ size‬عدد العنارص املوجودة في الحاوية ؛‬ ‫•‬
‫ويعيد العضو فارغ ‪ empty‬قيمة منطقية صحيحة إن كان الحجم صفرًا وخطأ بخالف ذلك ؛‬ ‫•‬
‫بينما يعيد العضو حجم_أقىص ‪ max_size‬عد ًدا أكرب من أو يساوي عنارص قد تحتويها حاوية ذلك النوع‪.‬‬ ‫•‬
‫ألسباب سنرشحها في القسم التالي ‪ ،‬توفر القائمة_اﻷمامية الحجم األقىص والفارغ ‪ ،‬لكن ليس الحجم‪.‬‬ ‫•‬

‫‪9.2.7. Relational Operators‬‬ ‫‪ 9٫2٫7‬العوامل العالئقية‬

‫يدعم كل نوع حاوية عوامل التساوي (== و=!) ؛‬


‫وتدعم كل الحاويات باستثناء التجميعية غري املرتبة العوامل العالئقية أيضاً (> ‪.)=< ،< ، = >،‬‬ ‫•‬
‫يجب أن تكون املعامالت اليمىن واليرسى من نفس نوع الحاوية وأن تحتوي عنارص من نفس النوع‪.‬‬ ‫•‬
‫أي أنه يمكننا مقارنة متجه <‪ >int‬بمتجه <‪ >int‬آخر فقط‪.‬‬ ‫•‬
‫فال يمكننا مقارنة متجه <‪ >int‬بقائمة <‪ >int‬أو متجه <‪.>double‬‬ ‫•‬
‫تؤدي املقارنة بني حاويتني إلى إجراء مقارنة زوجية للعنارص‪.‬‬ ‫•‬
‫تعمل هذه العوامل بشكل مشابه لعوامل سلسلة العالئقية ‪:‬‬ ‫•‬
‫فإن كانت كلتا الحاويتني بنفس الحجم وكل العنارص متساوية ‪ ،‬فإن الحاويتني متساويتان ؛ وإال فالعكس‪.‬‬ ‫•‬
‫وإن كانت الحاويتان ذات أحجام مختلفة ولكن كل عنرص من عنارص األصغر يساوي العنرص املقابل لألكرب ‪،‬‬ ‫•‬
‫فستكون الحاوية األصغر أصغر من األخرى‪.‬‬
‫أما إن لم تكن أي من الحاويتني تسلسالً فرعياً أولياً عن األخرى ‪،‬‬ ‫•‬
‫فستعتمد املقارنة على العنارص غري املتكافئة األولى‪.‬‬ ‫•‬
‫ستوضح األمثلة التالية كيفية عمل هذه العوامل ‪:‬‬ ‫•‬

‫;} ‪vector<int> v1 = { 1, 3, 5, 7, 9, 12‬‬


‫;} ‪vector<int> v2 = { 1, 3, 9‬‬
‫;} ‪vector<int> v3 = { 1, 3, 5, 7‬‬
‫;} ‪vector<int> v4 = { 1, 3, 5, 7, 9, 12‬‬
‫]‪v1 < v2  // true; v1 and v2 differ at element [2]: v1[2] is less than v2[2‬‬
‫;‪v1 < v3  // false; all elements are equal, but v3 has fewer of them‬‬
‫)(‪v1 == v4 // true; each element is equal and v1 and v4 have the same size‬‬
‫‪v1 == v2 // false; v2 has fewer elements than v1‬‬

‫العوامل العالئقية تستخدم عوامل عنرصها العالئقية‬


‫‪Relational Operators Use Their Element’s Relational Operator‬‬

‫ملحوظة‬

‫ال يمكننا استخدام عامل عالئقي ملقارنة حاويتني إال إن تم تعريف عامل املقارنة املناسب لنوع العنرص‪.‬‬

‫تستخدم عوامل تساوي الحاوية عامل == عنرصها ‪ ،‬وتستخدم العوامل العالئقية عامل > عنرصها‪.‬‬
‫فإن كان نوع العنرص ال يدعم العامل املطلوب ‪ ،‬فال يمكننا استخدام العمليات املقابلة في حاويات تحتوي‬ ‫•‬
‫على ذلك النوع‪.‬‬
‫عرفناه في الفصل ‪ 7‬ﻻ عملية == وﻻ > ‪.‬‬ ‫يعرف نوع بيانات_املبيعات الذي ّ‬
‫مثالً ‪ ،‬ال ّ‬ ‫•‬
‫لذلك ‪ ،‬ال يمكننا مقارنة حاويتني تحتويان عنارص بيانات_مبيعات ‪:‬‬ ‫•‬

‫;‪vector<Sales_data> storeA, storeB‬‬


‫‪if (storeA < storeB) // error: Sales_data has no less-than operator‬‬

‫قسم التدريبات ‪9.2.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‬‬

‫تختلف الحاويات املتسلسلة والتجميعية في كيفية تنظيم عنارصهما‪.‬‬


‫تؤثر تلك االختالفات على كيفية تخزين العنارص والوصول إليها وإضافتها وإزالتها‪.‬‬ ‫•‬
‫غطى القسم السابق العمليات املشرتكة لجميع الحاويات (تلك املدرجة في الجدول ‪.)9.2‬‬ ‫•‬
‫سنغطي العمليات الخاصة بالحاويات املتسلسلة في الجزء املتبقي من هذا الفصل‪.‬‬ ‫•‬

‫‪ 9٫3٫1‬إضافة عنارص إلى حاوية متسلسلة‬


‫‪9.3.1. Adding Elements to a Sequential Container‬‬

‫باستثناء املصفوفة ‪ ،‬توفر جميع حاويات املكتبة إدارة مرنة للذاكرة‪.‬‬


‫حيث يمكننا إضافة أو إزالة العنارص حيوياً بتغيري حجم الحاوية في وقت التشغيل‪.‬‬ ‫•‬
‫يرسد الجدول ‪ 9.5‬العمليات اليت تضيف عنارص إلى حاوية متسلسلة (غري املصفوفة)‪.‬‬ ‫•‬

‫الجدول ‪ .9.5‬عمليات تضيف عنارص إلى حاوية متسلسلة‬

‫تغري هذه العمليات من حجم الحاوية وبالتالي ﻻ تدعمها مصفوفات املكتبة‬ ‫•‬

‫تمتلك القائمة_اﻷمامية نسخها الخاصة من اﻹدراج ‪ insert‬والغرس ‪.emplace‬‬ ‫•‬

‫تعد العمليتان ‪ push_back , emplace_back‬غري صالحتني للقائمة_اﻷمامية ‪،‬‬ ‫•‬

‫وكذلك تعد العمليتان ‪ push_front , emplace_front‬غري صالحتني للمتجه والسلسلة‪.‬‬ ‫•‬

‫‪Creates an element with value t or constructed‬‬


‫)‪c.push_back(t‬‬
‫‪from args at the end of c.‬‬
‫)‪c.emplace_back(args‬‬
‫‪Return void.‬‬

‫‪Creates an element with value t or constructed‬‬


‫)‪c.push_front(t‬‬
‫‪from args at the front of c.‬‬
‫)‪c.emplace_front(args‬‬
‫‪Return void.‬‬

‫‪Creates an element with value t or constructed‬‬


‫)‪c.insert(p,t‬‬ ‫‪from args before the element donated by iterator p.‬‬
‫)‪c.emplace(p,args‬‬ ‫‪Return an iterator referring to the element‬‬
‫‪that was added.‬‬

‫‪Insert n elements with value t before the element‬‬


‫‪donated by iterator p.‬‬
‫)‪c.insert(p,n,t‬‬
‫;‪Return an iterator to the first element inserted‬‬
‫‪if n is zero, returns p.‬‬
‫‪Inserts the elements from the range donated by‬‬
‫‪iterators b and e before the element donated by‬‬
‫‪iterator p.‬‬
‫)‪c.insert(p,b,e‬‬
‫‪b and e may not refer to elements in c.‬‬
‫‪Return an iterator to the first element inserted if‬‬
‫‪the range is empty, return p‬‬

‫‪il is a braced list of element values.‬‬


‫‪Inserts the given values before the element denoted‬‬
‫)‪c.insert(p,il‬‬ ‫‪by the iterator p.‬‬
‫;‪return an iterator to the first inserted element‬‬
‫‪if the list is empty, returns p.‬‬

‫تحذير‬

‫يحتمل أن تؤدي إضافة عنارص إلى متجه أو سلسلة أو طابور إلى إبطال مكررات ومراجع ومؤرشات في الحاوية‬ ‫•‬

‫عندما نستخدم هذه العمليات ‪ ،‬يجب أن نتذكر أن الحاويات تستخدم اسرتاتيجيات مختلفة لتخصيص‬ ‫•‬
‫العنارص وأن هذه االسرتاتيجيات تؤثر على األداء‪.‬‬
‫تتطلب إضافة عنارص في أي مكان نقل عنارص إﻻ في نهاية_ متجه أو سلسلة ‪ ،‬أو في أي مكان ما عدا‬ ‫•‬
‫مقدمة أو خلفية طابور ‪.‬‬
‫عالوة على ذلك ‪ ،‬قد تؤدي إضافة عنارص إلى متجه أو سلسلة إلى إعادة تخصيص الكائن بأكمله‪.‬‬ ‫•‬
‫تتطلب إعادة تخصيص كائن ما تخصيص ذاكرة جديدة ونقل العنارص من املساحة القديمة إلى الجديدة‪.‬‬ ‫•‬

‫‪Using push_back‬‬ ‫استخدام دفع_للخلف‬

‫في الفقرة ‪ 3.3.2‬رأينا أن دفع_للخلف ‪ push_back‬تلحق عنرصًا بالجزء الخلفي من متجه‪.‬‬


‫وباستثناء املصفوفة والقائمة_اﻷمامية ‪ ،‬فإن كل حاوية متسلسلة (تشمل نوع السلسلة) تدعم دفع_للخلف‪.‬‬ ‫•‬
‫على سبيل املثال ‪ ،‬تقرأ الحلقة التالية سلسلة واحدة في كل مرة إلى كلمة‪:‬‬ ‫•‬

‫‪// read from standard input, putting each word onto the end of container‬‬
‫;‪string word‬‬
‫)‪while (cin >> word‬‬
‫;)‪    container.push_back(word‬‬

‫يؤدي استدعاء دفع_للخلف إلى إنشاء عنرص جديد في آخر الحاوية ‪،‬‬ ‫•‬
‫ما يؤدي إلى زيادة في حجم الحاوية مقدارها ‪.1‬‬ ‫•‬
‫قيمة هذا العنرص هي نسخة من الكلمة‪.‬‬ ‫•‬
‫ويمكن أن يكون نوع الحاوية أياً من قائمة ‪ ،‬أو متجه ‪ ،‬أو طابور‪.‬‬ ‫•‬
‫ونظر ًا ألن السلسلة حاوية من األحرف ‪ ،‬فيمكننا استخدام دفع_للخلف إلضافة أحرف إلى آخر السلسلة ‪:‬‬ ‫•‬

‫)‪void pluralize(size_t cnt, string &word‬‬


‫{‬
‫)‪    if (cnt > 1‬‬
‫'‪        word.push_back('s');  // same as word += 's‬‬
‫}‬

‫عنارص الحاوية عبارة عن نسخ ‪Container Elements Are Copies‬‬ ‫مفهوم رئييس ‪:‬‬

‫عندما نستخدم كائنًا لتهيئة حاوية ‪ ،‬أو إدراج كائن في حاوية ‪،‬‬ ‫•‬
‫يتم وضع نسخة من قيمة هذا الكائن في الحاوية ‪ ،‬وليس الكائن نفسه‪.‬‬ ‫•‬
‫مثلما نقوم بتمرير كائن إلى معامل غري مرجعي ‪،‬‬ ‫•‬
‫ال توجد عالقة بني العنرص في الحاوية والكائن الذي نشأت منه تلك القيمة‪.‬‬ ‫•‬
‫لن تؤثر التغيريات الالحقة على العنرص في الحاوية على الكائن األصلي ‪ ،‬والعكس صحيح‪.‬‬ ‫•‬

‫‪Using push_front‬‬ ‫استخدام دفع_للمقدمة‬

‫إضافة إلى دفع_للخلف ‪ ،‬تدعم حاويات القائمة والقائمة_اﻷمامية والطابور عملية مماثلة تسمى دفع_للمقدمة‪.‬‬
‫تُدخل هذه العملية عنرصًا جدي ًدا في مقدمة الحاوية ‪:‬‬ ‫•‬

‫;‪list<int> ilist‬‬
‫‪// add elements to the start of ilist‬‬
‫)‪for (size_t ix = 0; ix != 4; ++ix‬‬
‫;)‪    ilist.push_front(ix‬‬

‫تضيف هذه الحلقة العنارص ‪ 3 ، 2 ، 1 ، 0‬إلى مقدمة القائمة‪.‬‬ ‫•‬


‫يتم إدراج كل عنرص في املقدمة الجديدة للقائمة‪.‬‬ ‫•‬
‫هذا يعين أنه عندما نضيف ‪ ، 1‬فإنه يظهر أمام ‪ ، 0‬و ‪ 2‬أمام ‪ ، 1‬وهكذا دواليك‪.‬‬ ‫•‬
‫وهكذا ‪ ،‬فإن العنارص املضافة في حلقة مثل هذه تنتهي برتتيب عكيس‪.‬‬ ‫•‬
‫بعد تنفيذ هذه الحلقة ‪ ،‬ستحمل ‪i‬القائمة التسلسل ‪.3،2،1،0‬‬ ‫•‬
‫رسيعا لعنارصه ‪ ،‬يوفر العضو دفع_للمقدمة بالرغم من أن‬
‫ً‬ ‫عشوائيا‬
‫ً‬ ‫الحظ أن الطابور كاملتجه فكما يوفر وصواًل‬
‫املتجه ال يفعل ذلك‪.‬‬
‫• يضمن الطابور إدراج العنارص وحذفها في وقت ثابت في مقدمة الحاوية ونهايتها‪.‬‬
‫كما هو حال املتجه ‪ ،‬فإن إدراج عنارص أخرى غري املقدمة أو الخلفية من طابور قد يكون عملية مكلفة‪.‬‬ ‫•‬

‫إضافة عنارص في نقطة محددة من الحاوية‬


‫‪Adding Elements at a Specified Point in the Container‬‬

‫توفر عمليتا دفع_للخلف و دفع_للمقدمة طر ًقا مالئمة إلدراج عنرص واحد في آخر أو مقدمة الحاوية املتسلسلة‪.‬‬
‫بشكل عام ‪ ،‬تسمح لنا العنارص املدرجة بإدراج صفر أو أكرث من العنارص في أي نقطة في الحاوية‪.‬‬ ‫•‬
‫يتم دعم أعضاء اإلدراج للمتجه و طابور والقائمة والسلسلة‪.‬‬ ‫•‬
‫نسخا متخصصة من هذه األعضاء سنغطيها في الفقرة ‪.9.3.4‬‬
‫ً‬ ‫تقدم القائمة_اﻷمامية‬ ‫•‬
‫كررا كوسيطة أولى لها‪.‬‬
‫تأخذ كل دالة من الدوال إدراج ‪ُ insert‬م ً‬
‫يشري املكرر إلى مكان وضع العنرص (العنارص) في الحاوية‪.‬‬ ‫•‬
‫يمكن أن يشري إلى أي موضع في الحاوية ‪ ،‬بما في ذلك واحد بعد آخر الحاوية‪.‬‬ ‫•‬
‫ونظرًا ألن املكرر قد يشري إلى عنرص غري موجود من نهاية_الحاوية ‪،‬‬ ‫•‬
‫وألنه من املفيد أن يكون لديك طريقة إلدراج العنارص في بداية_الحاوية ‪،‬‬ ‫•‬
‫يتم إدراج العنرص (العنارص) قبل املوضع الذي يشري إليه املكرر‪.‬‬ ‫•‬
‫على سبيل املثال ‪ ،‬هذه الجملة‬

‫‪slist.insert(iter, "Hello!"); // insert "Hello!" just before iter‬‬

‫تدرج سلسلة ذات قيمة "‪ "Hello‬قبل العنرص الذي يشري إليه ‪ iter‬مبارش ًة‪.‬‬ ‫•‬
‫بالرغم من أن بعض الحاويات ال تحتوي على عملية دفع_للمقدمة ‪،‬‬ ‫•‬
‫فال توجد قيود مماثلة على إدراج‪.‬‬ ‫•‬
‫يمكننا إدراج عنارص في مقدمة الحاوية دون القلق بشأن ما إن كانت الحاوية بها دفع_للمقدمة أم ال ‪:‬‬ ‫•‬

‫;‪vector<string> svec; list<string> slist‬‬


‫;)"!‪// equivalent to calling slist.push_front("Hello‬‬
‫;)"!‪slist.insert(slist.begin(), "Hello‬‬
‫)(‪// no push_front on vector but we can insert before begin‬‬
‫‪// warning: inserting anywhere but at end of vector might be slow‬‬
‫;)"!‪svec.insert(svec.begin(), "Hello‬‬

‫تحذير‬

‫من الرشعي اﻹدراج من أي مكان في متجه أو طابور أو سلسلة‪ .‬مع ذلك ‪ ،‬فالقيام بذلك قد يكون عملية مكلفة‪.‬‬

‫‪Inserting a Range of Elements‬‬ ‫إدراج نطاق عنارص‬

‫تتشابه وسيطات إدراج واليت تظهر بعد وسيطة املكرر األولية مع ُمنشئة الحاوية اليت تأخذ نفس املعلمات‪.‬‬
‫اإلصدار الذي يأخذ عدد العنارص والقيمة يضيف عد ًدا محدداً من العنارص املتطابقة قبل املوضع املحدد ‪:‬‬ ‫•‬

‫;)"‪svec.insert(svec.end(), 10, "Anna‬‬

‫يقوم هذا الكود بإدراج عرشة عنارص في آخر ‪ 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‬‬

‫عندما نمرر زوج مكررات ‪ ،‬قد ال يشري املكرران إلى نفس الحاوية كتلك اليت نضيف إليها العنارص‪.‬‬ ‫•‬
‫مكررا ﻷول عنرص تم إدراجه‪.‬‬
‫ً‬ ‫بموجب املعيار الجديد ‪ ،‬فإن إصدارات إدراج اليت تأخذ عد ًدا أو نطا ًقا ستعيد‬ ‫•‬
‫(في اإلصدارات السابقة للمكتبة ‪ ،‬كانت هذه العمليات تعيد باطالً‪).‬‬ ‫•‬
‫فارغا ‪ ،‬فلن يتم إدراج أي عنارص ‪ ،‬وتقوم العملية بإعادة املعلمة األولى‪.‬‬
‫ً‬ ‫إن كان النطاق‬ ‫•‬

‫‪Using the Return from insert‬‬ ‫استخدام املعاد من إدراج‬

‫يمكننا استخدام القيمة املعادة بواسطة ‪ insert‬إلدراج العنارص بشكل متكرر في موضع محدد من الحاوية ‪:‬‬

‫;‪list<string> 1st‬‬
‫;)(‪auto iter = 1st.begin‬‬
‫)‪while (cin >> word‬‬
‫‪   iter = 1st.insert(iter, word); // same as calling push_front‬‬

‫ملحوظة‬

‫من املهم أن نفهم كيف تعمل هذه الحلقة ‪ -‬تحديداً ‪ ،‬لفهم سبب تكافؤ الحلقة مع استدعاء دفع_للمقدمةي‪.‬‬

‫قبل الحلقة ‪ ،‬نقوم بتهيئة ‪ iter‬على ()‪.1st.begin‬‬ ‫•‬


‫يأخذ أول استدعاء إلدراج السلسلة اليت قرأناها للتو ويضعها أمام العنرص الذي يشري إليه املكرر‪.‬‬ ‫•‬
‫القيمة اليت يعيدها اإلدراج هي مكرر يشري إلى هذا العنرص الجديد‪.‬‬ ‫•‬
‫نقوم بتعيني هذا املكرر إلى ‪ iter‬ونكرر ‪ ، while‬ونقرأ كلمة أخرى‪.‬‬ ‫•‬
‫وطاملا أن هناك كلمات إلدراجها ‪ ،‬فإن كل اجتياز خالل ‪ while‬تُدرج عنرصًا جدي ًدا قبل املكرر وتعيد‬ ‫•‬
‫تخصيص موقع العنرص املُدرج حديثًا للمكرر ذلك‪.‬‬
‫ذلك العنرص سيكون العنرص األول (الجديد)‪.‬‬ ‫•‬
‫وبالتالي ‪ ،‬يقوم كل مكرر بإدراج عنرص قبل أول عنرص في القائمة‪.‬‬ ‫•‬

‫‪Using the Emplace Operations‬‬ ‫استخدام عمليات غرس_‬


‫قدم املعيار الجديد ثالثة أعضاء جدد – غرس_للمقدمة ‪ emplace_front‬و غرس ‪ emplace‬و غرس_للخلف‬
‫‪ - emplace_back‬تقوم بإنشاء العنارص بدال ً من نسخها‪.‬‬
‫تتوافق تلك العمليات مع عمليات دفع_للمقدمة و إدراج و دفع_للخلف ؛‬ ‫•‬
‫حيث تسمح لنا بوضع عنرص في مقدمة الحاوية ‪ ،‬أمام موضع محدد ‪ ،‬أو في الخلفية ‪ ،‬على التوالي‪.‬‬ ‫•‬
‫عند استدعاء العضو دفع أو إدراج ‪ ،‬فإننا نمرر كائنات من نوع العنرص ويتم نسخ الكائنات إلي الحاوية‪.‬‬ ‫•‬
‫بينما استدعاء العضو غرس ‪ ،‬يمرر وسيطات إلى ُمنشئة من نوع العنرص‪.‬‬ ‫•‬
‫تستخدم األعضاء غرس هذه الوسيطات إلنشاء عنرص مبارشة في فضاء تديره الحاوية‪.‬‬ ‫•‬
‫على سبيل املثال ‪ ،‬بافرتاض أن ‪ c‬يحمل عنارص بيانات_املبيعات ‪:‬‬ ‫•‬

‫‪// construct a Sales_data object at the end of c‬‬


‫‪// uses the three-argument Sales_data constructor‬‬
‫;)‪c.emplace_back("978-0590353403", 25, 15.99‬‬
‫‪// error: there is no version of push_back that takes three arguments‬‬
‫;)‪c.push_back("978-0590353403", 25, 15.99‬‬
‫‪// ok: we create a temporary Sales_data object to pass to push_back‬‬
‫;))‪c.push_back(Sales_data("978-0590353403", 25, 15.99‬‬

‫استدعاء غرس_للخلف واستدعاء دفع_للخلف الثاني كالهما ينشئان كائنات بيانات_مبيعات جديدة‪.‬‬ ‫•‬
‫في استدعاء غرس_للخلف ‪ ،‬يتم إنشاء هذا الكائن مبارشة في مساحة تديرها الحاوية‪.‬‬ ‫•‬
‫محليا يتم دفعه إلى الحاوية‪.‬‬
‫ً‬ ‫يُنئش استدعاء دفع_للخلف كائنًا مؤق ًتا‬ ‫•‬
‫تختلف وسيطات دالة غرس اعتما ًدا على نوع العنرص‪.‬‬ ‫•‬
‫ويجب أن تتطابق تلك الوسيطات مع ُمنشئة من نوع العنرص‪:‬‬ ‫•‬

‫‪// iter refers to an element in c, which holds Sales_data elements‬‬


‫‪c.emplace_back(); // uses the Sales_data default constructor‬‬
‫)‪c.emplace(iter, "999-999999999"); // uses Sales_data(string‬‬
‫‪// uses Sales_data constructor that takes an ISBN, a count, and a price‬‬
‫;)‪c.emplace_front("978-0590353403", 25, 15.99‬‬

‫ملحوظة‬

‫تقوم دوال غرس بإنشاء عنارص في الحاوية‪ .‬يجب أن تتطابق وسيطات هذه الدوال مع ُمنشئة لنوع العنرص‪.‬‬

‫قسم التدريبات ‪9.3.1‬‬

‫التمرين ‪:9.18‬‬
‫برنامج ا لقراءة سلسلة من السالسل من املدخالت القياسية في طابور‪.‬‬
‫ً‬ ‫‪ -‬اكتب‬
‫‪ -‬استخدم املكررات لكتابة حلقة لطباعة العنارص في طابور‪.‬‬

‫التمرين ‪:9.19‬‬
‫‪ -‬أعد كتابة الربنامج من التمرين السابق الستخدام قائمة‪.‬‬
‫‪ -‬ضع قائمة بالتغيريات اليت احتجت إلى إجرائها‪.‬‬

‫التمرين ‪:9.20‬‬
‫برنامجا لنسخ العنارص من قائمة <‪ >int‬إلى اثنني من طابور‪.s‬‬
‫ً‬ ‫‪ -‬اكتب‬
‫‪ -‬يجب أن تدخل العنارص ذات القيمة الزوجية في جزء واحد والعنارص الفردية في اآلخر‪.‬‬

‫التمرين ‪:9.21‬‬
‫‪ -‬ارشح كيف ستعمل الحلقة من الصفحة ‪ 345‬اليت استخدمت اإلعادة من املدخالت إلضافة عنارص إلى القائمة إن‬
‫قمنا بإدراجها في متجه بدال ً من ذلك‪.‬‬

‫التمرين ‪:9.22‬‬
‫‪ -‬بافرتاض أن ‪ iv‬متجه لـ ‪، ints‬‬
‫‪ -‬فما الخطأ في الربنامج التالي؟ كيف يمكنك تصحيح املشكلة (املشاكل)؟‬

‫;‪vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size()/2‬‬


‫)‪while (iter != mid‬‬
‫)‪    if (*iter == some_val‬‬
‫;)‪        iv.insert(iter, 2 * some_val‬‬

‫‪9.3.2. Accessing Elements‬‬ ‫‪ 9٫3٫2‬الوصول إلى العنارص‬

‫يرسد الجدول ‪ 9.6‬العمليات اليت يمكننا استخدامها للوصول إلى العنارص في حاوية متسلسلة‪.‬‬
‫معرفة إن كانت الحاوية فارغة وﻻ تحتوي على عنارص‪.‬‬
‫تكون عمليات الوصول غري ّ‬

‫الجدول ‪ .9.6‬عمليات الوصول إلى العنارص في حاوية متسلسلة‬

‫عوامل ‪ at‬و ‪ subscript‬صالحة فقط للسلسلة واملتجه والطابور واملصفوفة ؛ بينما تعد ‪ back‬غري صالحة للقائمة_اﻷمامية‬

‫‪Returns a reference to the last element in c.‬‬


‫)(‪c.back‬‬
‫‪Undefined if c is empty.‬‬
‫‪Returns a reference to the first element in c.‬‬
‫)(‪c.front‬‬
‫‪Undefined if c is empty.‬‬
‫‪Returns a reference to the element indexed by the unsigned‬‬
‫]‪c[n‬‬
‫‪integral value n. undefined if n >= c.size().‬‬
‫‪Returns a reference to the element indexed by n. if the‬‬
‫)‪c.at(n‬‬
‫‪index is out of range, throws an out_of_range exception.‬‬
‫تحذير‬

‫يعد استدعاء ‪ front‬أو ‪ back‬على أي حاوية فارغة خطأ برمجياً فادحاً كاستخدام فهرسة خارج النطاق‬

‫كل حاوية متسلسلة ‪ ،‬بما في ذلك املصفوفة ‪ ،‬تملك العضو مقدمة_ ‪، front‬‬ ‫•‬
‫وكلها باستثناء القائمة_اﻷمامية تملك العضو خلف_ ‪.back‬‬ ‫•‬
‫مرجعا ألول وآخر عنرص ‪ ،‬على التوالي‪:‬‬
‫ً‬ ‫ستعيد تلك العمليات‬ ‫•‬

‫‪// check if there elements before dereferencing an iterator or calling‬‬


‫‪front or back‬‬
‫{ ))(‪if (!c.empty‬‬
‫‪    // val and val2 are copies of the value of the first element in c‬‬
‫;)(‪    auto val = *c.begin(), val2 = c.front‬‬
‫‪    // val3 and val4 are copies of the of the last element in c‬‬
‫;)(‪    auto last = c.end‬‬
‫‪    auto val3 = *(--last); // can't decrement forward_list iterators‬‬
‫‪    auto val4 = c.back();  // not supported by forward_list‬‬
‫}‬

‫يحصل هذا الربنامج على مراجع ألول وآخر عنرص في ‪ 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‬لتخزين عائد من إحدى هذه الدوال وأردنا استخدام ذلك املتغري لتغيري‬ ‫•‬
‫نعرف متغرينا الخاص كنوع مرجعي‪.‬‬‫العنرص ‪ ،‬يجب أن نتذكر أن ّ‬

‫‪Subscripting and Safe Random Access‬‬ ‫الفهرسة والوصول العشوائي اﻵمن‬

‫أيضا عامل فهرسة‪.‬‬


‫رسيعا (سلسلة ومتجه و طابور ومصفوفة) ً‬
‫ً‬ ‫عشوائيا‬
‫ً‬ ‫توفر الحاويات اليت توفر نفاذاً‬
‫كما رأينا ‪ ،‬يأخذ عامل الفهرسة فهرساً ويعيد مرجعاً إلى العنرص في هذا املوضع في الحاوية‪.‬‬ ‫•‬
‫يجب أن يكون الفهرس "في النطاق" (أي أكرب من أو يساوي ‪ 0‬وأقل من حجم الحاوية)‪.‬‬ ‫•‬
‫األمر مرتوك للربنامج للتأكد من صحة الفهرس ؛ فعامل الفهرسة ال يتحقق من نطاق الفهرس‪.‬‬ ‫•‬
‫برمجيا خطريًا ‪ ،‬لكنه خطأ لن يكتشفه املرتجم‪.‬‬
‫ً‬ ‫يعد استخدام قيمة خارج النطاق لفهرس خطأ‬ ‫•‬
‫إن أردنا التأكد من أن فهرسنا صالح ‪ ،‬فيمكننا استخدام العضو ‪ at‬بدال ً من ذلك‪.‬‬
‫سيعمل العضو ‪ at‬مثل عامل الفهرسة ‪ ،‬لكن إن كان الفهرس غري صالح ‪،‬‬ ‫•‬
‫فسيصدر اﻻستثناء خارج_النطاق‪: out_of_range‬‬ ‫•‬

‫‪vector<string> svec; // empty vector‬‬


‫;]‪cout << svec[0‬‬ ‫!‪// run-time error: there are no elements in svec‬‬
‫;)‪cout << svec.at(0‬‬ ‫‪// throws an out_of_range exception‬‬

‫قسم التدريبات ‪9.3.2‬‬

‫التمرين ‪:9.23‬‬
‫‪ -‬في الربنامج األول في هذا القسم في الصفحة ‪ ، 346‬ما هي قيم ‪ val‬و ‪ val2‬و ‪ val3‬و ‪val4‬‬
‫‪ -‬إن كان ()‪ c.size‬يساوي ‪ 1‬؟‬

‫التمرين ‪:9.24‬‬
‫برنامجا يقوم بجلب أول عنرص في متجه باستخدام ‪ ، at‬عامل الفهرس ‪ ،‬مقدمة_ ‪ ،‬وبداية_‪.‬‬
‫ً‬ ‫‪ -‬اكتب‬
‫‪ -‬اخترب برنامجك على متجه فارغ‪.‬‬

‫‪9.3.3. Erasing Elements‬‬ ‫‪ 9٫3٫3‬محو العنارص‬

‫أيضا عدة طرق ملحوها‪.‬‬


‫كما توجد عدة طرق إلضافة عنارص إلى حاوية (غري املصفوفة) ‪ ،‬فهناك ً‬
‫يتم رسد هذه األعضاء في الجدول ‪.9.7‬‬
‫الجدول ‪ .9.7‬عمليات املحو على الحاويات املتسلسلة‬

‫تمتلك القائمة_اﻷمامية نسختها الخاصة من املحو ‪. erase‬‬ ‫•‬

‫ستغري هذه العمليات حجم الحاوية ولذا لن تدعمها املصفوفة‪،‬‬ ‫•‬

‫ﻻ تصلح ‪ pop_back‬للقائمة_األمامية ؛ وﻻ تصلح ‪ pop_front‬للمتجه وﻻ السلسلة‪.‬‬ ‫•‬

‫‪Removes last elements in c.‬‬


‫)(‪c.pop_back‬‬
‫‪Undefined if c is empty. Return void.‬‬

‫‪Removes first elements in c.‬‬


‫)(‪c.pop_front‬‬
‫‪Undefined if c is empty. Return void.‬‬

‫‪Removes the elements denoted by the iterator p and‬‬


‫‪returns an iterator to the element after the one deleted‬‬
‫)‪c.erase(p‬‬
‫‪or the off-the-end iterator if p denotes the last‬‬
‫‪element. Undefined if p is the off-the-end iterator.‬‬

‫‪Removes the range of elements denoted by the iterators b‬‬


‫‪and e. Returns an iterator to the element after the last‬‬
‫)‪c.erase(b,e‬‬
‫‪one that was deleted, or an off-the-end iterator if e is‬‬
‫‪itself an off-the-end iterator.‬‬

‫)(‪c.clear‬‬ ‫‪Removes all the elements in c. Return void.‬‬

‫محو عنارص من الطابور من غري مقدمته أو نهايته سيبطل جميع مكرراته ومراجعه ومؤرشاته‪.‬‬ ‫•‬

‫وستكون كل مكررات ومراجع ومؤرشات عنارص املتجه أو السلسلة باطلة من بعد نقطة املحو‪.‬‬ ‫•‬

‫تحذير‬

‫األعضاء اليت تمحو عنارص ال تفحص (وسيطاتها)‪ .‬يجب على املربمج التأكد من وجود عنـ(ـا)رص قبل محوها‪.‬‬

‫‪The pop_front and pop_back Members‬‬ ‫اﻷعضاء طرد_مقدمة وطرد_خلف‬

‫تعمل الدالتان طرد_مقدمة ‪ 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‬‬
‫}‬

‫محو عنرص من داخل الحاوية‬


‫‪Removing an Element from within the Container‬‬

‫تقوم أعضاء املسح بإزالة العنـ(ـا)رص عند نقطة محددة في الحاوية‪.‬‬


‫فيمكننا حذف عنرص واحد يُشار إليه بواسطة مكرر أو نطاق عنارص ممزية بزوج من املكررات‪.‬‬ ‫•‬
‫مكررا يشري إلى موقع ملا بعد آخر عنرص تمت إزالته‪.‬‬
‫ً‬ ‫نموذجي املسح كالهما يعيدان‬ ‫•‬
‫مكررا يشري إلى ‪.j‬‬
‫ً‬ ‫بمعىن ‪ ،‬إن كان ‪ j‬هو العنرص الذي يلي ‪ ، i‬فإن محو (‪ )i‬سيعيد‬ ‫•‬
‫على سبيل املثال ‪ ،‬تمحو الحلقة التالية العنارص الفردية في القائمة ‪:‬‬

‫;}‪list<int> lst = {0,1,2,3,4,5,6,7,8,9‬‬


‫;)(‪auto it = lst.begin‬‬
‫))(‪while (it != lst.end‬‬
‫‪    if (*it % 2)           // if the element is odd‬‬
‫‪        it = lst.erase(it);  // erase this element‬‬
‫‪    else‬‬
‫;‪        ++it‬‬

‫مع كل تكرار ‪ ،‬نتحقق ما إن كان العنرص الحالي فردياً‪.‬‬ ‫•‬


‫إن كان فردياً ‪ ،‬فسنمحو ذلك العنرص ‪ ،‬ونضبط ‪ it‬ليشري إلى ما بعد العنرص الذي محوناه‪.‬‬ ‫•‬
‫إن كانت ‪ *it‬زوجية ‪ ،‬فإننا نزايد ‪ it‬حىت نلقي نظرة على العنرص التالي في التكرار الذي يليه‪.‬‬ ‫•‬

‫‪Removing Multiple Elements‬‬ ‫محو عنارص متعددة‬

‫يتيح لنا إصدار زوج‪-‬املكرر للمحو حذف نطاق من العنارص ‪:‬‬

‫‪// delete range of elements between two iterators‬‬


‫‪// returns iterator to element just after last removed element‬‬
‫‪elem1 = slist.erase(elem1, elem2); // after call elem1 == elem2‬‬

‫يشري املكرر ‪ elem1‬إلى أول عنرص نريد محوه ‪ ،‬ويشري ‪ elem2‬إلى آخر عنرص نريد إزالته‪.‬‬ ‫•‬
‫لحذف كل عنارص الحاوية ‪ ،‬يمكننا إما استدعاء ‪ clear‬أو تمرير املكررين بداية_ ونهاية_ إلى ‪: erase‬‬ ‫•‬

‫‪slist.clear(); // delete all the elements within the container‬‬


‫‪slist.erase(slist.begin(), slist.end()); // equivalent‬‬
‫قسم التدريبات ‪9.3.3‬‬

‫التمرين ‪:9.25‬‬
‫‪ -‬في الربنامج املوجود في الصفحة ‪ 349‬والذي قام بمسح مجموعة من العنارص ‪،‬‬
‫ماذا يحدث إن تساوى ‪ elem1‬و ‪elem2‬؟‬
‫ماذا لو كان ‪ elem2‬أو كال من ‪ elem1‬و ‪ elem2‬هو مكرر ما بعد النهاية؟‬

‫التمرين ‪:9.26‬‬
‫‪ -‬باستخدام التعريف التالي لـ ‪ ، ia‬انسخ ‪ ia‬إلى متجه وفي قائمة‪.‬‬
‫‪ -‬استخدم صيغة املحو أحادية املكرر إلزالة العنارص ذات القيم الفردية من قائمتك والقيم الزوجية من املتجه‪.‬‬

‫‪ 9٫3٫4‬عمليات القائمة_اﻷمامية املتخصصة‬


‫‪9.3.4. Specialized forward_list Operations‬‬

‫لفهم سبب وجود إصدارات خاصة لعمليات القائمة_اﻷمامية إلضافة العنارص وإزالتها ‪،‬‬
‫فكر في ما ينبغي أن يحدث عندما نزيل عنرصًا من تسلسل مرتابط بشكل حر وفردي‪.‬‬ ‫•‬
‫فكما هو موضح في الشكل ‪ ، 9.1‬تؤدي إزالة عنرص إلى تغيري روابط ذلك التسلسل‪.‬‬ ‫•‬
‫في هذه الحالة ‪ ،‬إزالة التغيريات ‪elem3 elem2‬؛‬ ‫•‬
‫كان ‪ elem2‬قد أشار إلى ‪ ، elem3‬ولكن بعد إزالة ‪ ، elem3‬يشري ‪ elem2‬إلى ‪.elem4‬‬ ‫•‬

‫الشكل ‪ .9.1‬عمليات القائمة_اﻷمامية املتخصصة‬

‫عندما نضيف عنرصًا أو نزيله ‪ ،‬سيختلف وريث ما قبل العنرص الذي أضفناه أو أزلناه‪.‬‬ ‫•‬
‫إلضافة عنرص أو إزالته ‪ ،‬سنحتاج إلى الوصول إلى العنرص السابق من أجل تحديث روابط هذا العنرص‪.‬‬ ‫•‬
‫ومع ذلك ‪ ،‬ترتابط القائمة_اﻷمامية بشكل حر ومنفرد‪.‬‬ ‫•‬
‫وفي قائمة ترتابط بشكل فردي ‪ ،‬ال توجد طريقة سهلة للوصول إلى عنرص سابق‪.‬‬ ‫•‬
‫لذلك ‪ ،‬تعمل عمليات إضافة عنارص أو إزالتها في القائمة_األمامية على تغيري ما بعد العنرص املحدد‪.‬‬ ‫•‬
‫وبهذه الطريقة ‪ ،‬سنتمكن دوماً من الوصول إلى العنارص املتأثرة بالتغيري‪.‬‬ ‫•‬
‫ونظرًا ألن هذه العمليات تترصف بشكل مختلف عن عمليات الحاويات األخرى ‪،‬‬ ‫•‬
‫فإن القائمة_اﻷمامية ال تعرِّف اإلدراج ‪ insert‬وﻻ الغرس ‪ emplace‬وﻻ املسح ‪.erase‬‬ ‫•‬
‫أعضاء (مدرجة في الجدول ‪ )9.8‬تسمى اإلدراج_بعد ‪ insert_after‬والغرس_بعد‬
‫ً‬ ‫تعرف‬
‫بل ّ‬ ‫•‬
‫‪ emplace_after‬واملسح_بعد ‪.erase_after‬‬
‫فمثالً ‪ ،‬في رسمنا التوضيحي ‪ ،‬إلزالة ‪ ، elem3‬سنستدعي الـمسح_بعد على مكرر يشري إلى ‪.elem2‬‬ ‫•‬
.‫مكررا ملا قبل البدء‬
ً ‫ وتعيد‬، before_begin ‫تعرف القائمة_اﻷمامية قبل_بداية‬
ّ ، ‫ولدعم تلك العمليات‬ •
.‫يتيح لنا هذا املكرر إضافة أو إزالة عنارص "بعد" عنرص غري موجود قبل أول عنرص في القائمة‬ •

‫ عمليات إدراج العنارص أو إزالتها في قائمة_أمامية‬.9.8 ‫الجدول‬

Iterator denoting the non-existent element just


lst.before_begin() before the beginning of the list.
lst.cbefore_begin() This iterator may not be de-referenced.
cbefore_begin() returns a const_iterator.

Inserts element(s) after the one denoted by


iterator p.
lst.insert_after(p,t) t is an object, n is a count, b and e are
lst.insert_after(p,n,t) iterators denoting a range (b and e must not refer
lst.insert_after(p,b,e) to lst), il is a braced list.
lst.insert_after(p,il) Returns an iterator to the last inserted element.
If the range is empty, return p.
Undefined if p is the off-the-end iterator.

Uses args to construct an element after the one


denoted by iterator p.
emplace_after(p,args)
Return an iterator to the new element.
Undefined if p is the off-the-end iterator.

Removes the element after the one denoted by


iterator p or the range of elements from the one
after the iterator b up to but not including the
one denoted by e.
lst.erase_after(p)
Returns an iterator to the element after the one
lst.erase_after(b,e)
deleted or the off-the-end iterator if there is no
such element.
Undefined if p denotes the last element in lst or
is the off-the-end iterator.

- ‫ يتعني علينا تتبع مكررين‬، ‫عندما نضيف عنارص أو نزيلها في قائمة_أمامية‬ •


.‫أحدهما لعنرص نتحقق منه وآخر لعنرص سابق له‬ •
: ‫ سنقوم بإعادة كتابة الحلقة اليت أزالت عنارص ذات قيمة فردية مستخدمني قائمة_أمامية‬، ‫كمثال‬ •

forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};


auto prev = flst.before_begin(); // denotes element "off the start" of flst
auto curr = flst.begin();        // denotes the first element in flst
while (curr != flst.end()) {     // while there are still elements to process
    if (*curr % 2)                   // if the element is odd
        curr = flst.erase_after(prev); // erase it and move curr
    else {
        prev = curr;   // move the iterators to denote the next
‫‪        ++curr;        // element and one before the next element‬‬
‫}‪    ‬‬
‫}‬

‫هنا ‪ ،‬يشري ‪ Curr‬إلى العنرص الذي نتحقق منه ‪ ،‬ويشري ‪ prev‬إلى عنرص ما قبل البدء‪.‬‬ ‫•‬
‫نستدعي بداية_ لتهيئتها على ‪ ، curr‬بحيث يتحقق أول تكرار ما إن كان أول عنرص زوجياً أم فردياً‪.‬‬ ‫•‬
‫مكررا إلى عنرص غري موجود قبل ‪.curr‬‬
‫ً‬ ‫نقوم بتهيئة ‪ prev‬على قبل_بداية ‪ ،‬والذي يعيد‬ ‫•‬
‫فرديا ‪ ،‬نمرر ‪ prev‬إلى عملية املسح_بعد ‪.erase_after‬‬ ‫ً‬ ‫عندما نجد عنرصًا‬ ‫•‬
‫هذا االستدعاء يمحو ما بعد العنرص املشار إليه بـ ‪ prev‬؛ أي أنه يمحو العنرص الذي يشري إليه ‪.curr‬‬ ‫•‬
‫نعيد تعيني ‪ curr‬على العائد من املسح_بعد ‪،‬‬ ‫•‬
‫ما يجعل ‪ curr‬يشري إلى العنرص التالي في التسلسل ويرتكه دون تغيري ؛‬ ‫•‬
‫سيظل ‪ prev‬يشري إلى العنرص قبل القيمة (الجديدة) لـ ‪.curr‬‬ ‫•‬
‫إن لم يكن العنرص الذي يُشار إليه بواسطة ‪ curr‬فردياً ‪ ،‬فيجب علينا تحريك كال املكررين ‪ ،‬وهو ما نقوم‬ ‫•‬
‫به في اآلخر‪.‬‬

‫قسم التدريبات ‪9.3.4‬‬

‫التمرين ‪:9.27‬‬
‫برنامج ا للبحث عن العنارص ذات القيمة الفردية وإزالتها في قائمة_أمامية <‪.>int‬‬
‫ً‬ ‫‪ -‬اكتب‬

‫التمرين ‪:9.28‬‬
‫‪ -‬اكتب دالة تأخذ قائمة_أمامية <سلسلة> ووسيطتني إضافيتني من وسيطات السلسلة‪.‬‬
‫‪ -‬يجب أن تجد الدالة السلسلة األولى وتدخل الثانية بعد األولى مبارشة‪.‬‬
‫‪ -‬إن لم يتم العثور على السلسلة األولى ‪ ،‬فقم بإدراج السلسلة الثانية في آخر القائمة‪.‬‬

‫‪9.3.5. Resizing a Container‬‬ ‫‪ 9٫3٫5‬تغيري_حجم حاوية‬

‫باستثناء املصفوفات كالعادة ‪ ،‬يمكننا استخدام تغيري_حجم ‪ ،‬املوضح في الجدول ‪ ، 9.9‬لتكبري حاوية أو تصغريها‪.‬‬
‫فإن كان حجمها الحالي أكرب من املطلوب ‪ ،‬سيتم حذف العنارص من جزئها الخلفي ؛‬ ‫•‬
‫أما إن كان حجمها الحالي أقل من الحجم الجديد ‪ ،‬سيتم إضافة عنارص إلى الجزء الخلفي من الحاوية ‪:‬‬ ‫•‬

‫‪list<int> ilist(10, 42); // ten ints: each has value 42‬‬


‫‪ilist.resize(15);     // adds five elements of value 0 to back of ilist‬‬
‫‪ilist.resize(25, -1); // adds ten elements of value -1 to back of ilist‬‬
‫‪ilist.resize(5);      // erases 20 elements from back of ilist‬‬

‫تأخذ عملية تغيري_حجم وسيطة اختيارية لقيمة العنرص تستخدمها لتهيئة أي عنارص مضافة إلى الحاوية‪.‬‬ ‫•‬
‫إن كانت هذه الوسيطة غائبة ‪ ،‬فستكون العنارص املضافة ذات قيمة تمت تهيئتها ‪.‬‬ ‫•‬
‫وإن كانت الحاوية تحتوي على عنارص من نوع فئة وسيضيف تغيري_حجم عنارص إضافية ‪،‬‬ ‫•‬
‫فيجب علينا توفري ُمهئي أو يجب أن يكون لنوع العنرص ُمنشئة افرتاضية‪.‬‬ ‫•‬

‫الجدول ‪ .9.9‬عمليات حجم الحاوية املتسلسلة‬

‫عملية تغيري_الحجم غري صالحة للمصفوفة‬

‫‪Resize c so that it has n elements. If n < c.size(), the‬‬


‫)‪c.resize(n‬‬ ‫‪excess elements are discarded.‬‬
‫‪If new elements must be added, they are value initialized.‬‬

‫‪Resize c to have n elements.‬‬


‫)‪c.resize(n, t‬‬
‫‪Any elements added have value t.‬‬

‫تحذير‬

‫إذا أدى تغيري_الحجم إلى تقليص الحاوية فستكون مكررات ومراجع ومؤرشات العنارص املحذوفة باطلة‪.‬‬ ‫•‬

‫يحتمل أن تغيري حجم حاوية املتجه والسلسلة والطابور سيبطل كل املكررات واملراجع واملؤرشات‪.‬‬ ‫•‬

‫قسم التدريبات ‪9.3.5‬‬

‫التمرين ‪: 9.29‬‬
‫‪ -‬إن كانت ‪ vec‬تحتوي على ‪ 25‬عنرصًا ‪ ،‬فماذا يفعل )‪vec.resize(100‬؟‬
‫‪ -‬ماذا لو كتبنا بعد ذلك )‪ vec.resize(10‬؟‬

‫التمرين ‪:9.30‬‬
‫‪ -‬ما هي القيود ‪ ،‬إن وجدت ‪ ،‬اليت يستخدمها إصدار تغيري الحجم الذي يأخذ مكان وسيطة واحدة في نوع العنرص؟‬

‫‪ 9٫3٫6‬عمليات الحاوية قد تبطل املكررات‬


‫‪9.3.6. Container Operations May Invalidate Iterators‬‬

‫يمكن لعمليات تضيف أو تزيل العنارص من الحاوية أن تبطل مؤرشات أو مراجع أو مكررات لعنارص الحاوية‪.‬‬
‫املؤرش (أو املرجع أو املكرر) الذي تم إبطاله مؤرش لم يعد يشري إلى عنرص‪.‬‬ ‫•‬
‫برمجيا خطريًا ‪،‬‬
‫ً‬ ‫يعد استخدام مؤرش أو مرجع أو مكرر غري صالح خطأ‬ ‫•‬
‫ويحتمل أن يؤدي إلى نفس أنواع املشكالت مثل استخدام مؤرش غري مهيأ‪.‬‬ ‫•‬
‫بعد عملية تضيف عنارص إلى الحاوية‬
‫تكون مكررات ومؤرشات ومراجع املتجه أو السلسلة باطلة إن تم إعادة تخصيص الحاوية‪.‬‬ ‫•‬
‫‪ -‬في حالة عدم حدوث إعادة تخصيص ‪ ،‬تظل املراجع غري املبارشة للعنارص قبل اإلدراج صالحة ؛‬
‫‪ -‬أما تلك العنارص فستكون بعد اإلدراج باطلة وغري صالحة‪.‬‬
‫تكون مكررات ومؤرشات ومراجع الطابور باطلة إن أضفنا عنارص في أي مكان ما عدا املقدمة أو الخلفية‪.‬‬ ‫•‬
‫‪ -‬فإن أضفنا في املقدمة أو الخلفية ‪ ،‬تبطل املكررات ‪ ،‬لكن لن تبطل املراجع واملؤرشات لعنارص موجودة‪.‬‬
‫تظل مكررات ومؤرشات ومراجع القائمة والقائمة_اﻷمامية صالحة (بما في ذلك مكررات ما بعد النهاية وما‬ ‫•‬
‫قبل البداية) ‪،‬‬
‫‪ -‬لن يكون مفاجًئ ا أن إزالة عنارص من حاوية ‪ ،‬سيبطل مكررات ومؤرشات ومراجع للعنارص املزالة‪.‬‬
‫‪ -‬فبعد كل يشء ‪ ،‬تم تدمري تلك العنارص‪.‬‬
‫بعد عملية تزيل عنرصًا ‪،‬‬
‫• تظل جميع مكررات أو مراجع أو مؤرشات القائمة أو القائمة_اﻷمامية اﻷخرى صالحة (بما في ذلك مكررات‬
‫ما بعد النهاية وما قبل البداية)‪.‬‬
‫• ستكون جميع مكررات أو مراجع أو مؤرشات الطابور األخرى باطلة إن كانت العنارص املزالة في أي مكان ما‬
‫عدا املقدمة أو الخلفية‪.‬‬
‫‪ -‬أما إن قمنا بإزالة عنارص من خلفية الطابور ‪ ،‬فسيتم إبطال مكرر ما بعد النهاية دون أن تتأثر املكررات‬
‫واملراجع واملؤرشات األخرى ؛ ولن تتأثر إن أزلنا من املقدمة أيضاً‪.‬‬
‫• كل مكررات أو مراجع أو مؤرشات عنارص املتجه أو السلسلة األخرى ستظل صالحة قبل نقطة اإلزالة‪.‬‬
‫مالحظة ‪ :‬يتم دوماً إبطال املكرر ما بعد النهاية عندما نزيل عنارص‪.‬‬ ‫•‬

‫تحذير‬

‫يعد استخدام مكرر أو مؤرش أو مرجع تم إبطال مفعوله خطًأ خطريًا في وقت التشغيل‪.‬‬

‫‪Advice: Managing Iterators‬‬ ‫نصيحة‪ :‬إدارة املكررات‬

‫مرجعا أو مؤرشًا ) لعنرص حاوية ‪،‬‬


‫ً‬ ‫مكررا ( أو‬
‫ً‬ ‫عندما تستخدم‬ ‫•‬
‫صالحا خالله‪.‬‬
‫ً‬ ‫فمن األفضل تصغري جزء الربنامج الذي يجب أن يبقى املكرر‬ ‫•‬
‫ذلك نظرًا ألن اﻷكواد اليت تضيف عنارص أو تزيلها إلى حاوية يمكن أن تبطل املكررات ‪،‬‬ ‫•‬
‫فأنت بحاجة إلى التأكد من إعادة تخصيص موضع املكرر ‪ ،‬حسب االقتضاء ‪ ،‬بعد كل عملية تغري حاوية‬ ‫•‬
‫هذه النصيحة مهمة بشكل خاص للمتجهات ‪ ،‬السالسل ‪ ،‬والطابور‪.‬‬ ‫•‬

‫حلقات كتابة تغري حاوية‬


‫‪Writing Loops That Change a Container‬‬

‫الحلقات اليت تضيف أو تزيل عنارص من متجه أو سلسلة أو طابور يجب أن تليب حقيقة معينة ‪:‬‬
‫وهي أن املكررات أو املراجع أو املؤرشات قد يتم إبطالها‪.‬‬ ‫•‬
‫يجب أن يضمن الربنامج تحديث املكرر أو املرجع أو املؤرش في كل اجتياز عرب الحلقة‪.‬‬ ‫•‬
‫يعد تحديث مكرر أمرًا سهالً إن قامت الحلقة باستدعاء إدراج أو محو‪.‬‬ ‫•‬
‫تعيد هذه العمليات مكررات ‪ ،‬واليت يمكننا استخدامها إلعادة تخصيص املكرر ‪:‬‬ ‫•‬

‫‪// 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‬إلى العنرص (املضاف حديثًا) أمام العنرص الذي نقوم‬ ‫•‬
‫بمعالجته‪.‬‬
‫نضيف اثنني لتخطي العنرص الذي أضفناه والعنرص الذي قمنا بمعالجته للتو‪.‬‬ ‫•‬
‫يؤدي القيام بذلك إلى وضع املكرر على العنرص التالي غري املعالج‪.‬‬ ‫•‬

‫تجنب تخزين املكرر املعاد من نهاية_‬


‫‪Avoid Storing the Iterator Returned from end‬‬

‫عندما نضيف أو نزيل عنارص متجه أو سلسلة ‪ ،‬أو نضيف أو نزيل عنارص طابور باستثناء أول عنرص ‪ ،‬فإن املكرر‬
‫دائما باطالً وغري صالح‪.‬‬
‫ً‬ ‫املعاد من نهاية_ يكون‬
‫دائما نهاية_ بدال ً من استخدام نسخة‬
‫ً‬ ‫• وبالتالي ‪ ،‬يجب أن تستدعي الحلقات اليت تضيف العنارص أو تزيلها‬
‫مخزنة‪.‬‬
‫جزئيا ‪ ،‬عاد ًة ما يتم تنفيذ مكتبات يس‪ ++‬القياسية بحيث يكون استدعاء ()‪ end‬عملية‬‫ً‬ ‫• ولهذا السبب‬
‫رسيعة ج ًدا‪.‬‬
‫• كمثال ‪ ،‬فكر في حلقة تعالج كل عنرص وتضيف عنرصًا جدي ًدا بعد األصل‪.‬‬
‫نريد أن تتجاهل الحلقة العنارص املضافة ‪ ،‬وأن تعالج العنارص األصلية فقط‪.‬‬ ‫•‬
‫بعد كل إدراج ‪ ،‬سنضع املكرر ليشري إلى العنرص األصلي التالي‪.‬‬ ‫•‬
‫إن حاولنا "تحسني" الحلقة ‪ ،‬من خالل تخزين املكرر املعاد من نهاية_ ‪ ،‬فسنواجه كارثة‪:‬‬ ‫•‬

‫‪// disaster: the behavior of this loop is undefined‬‬


‫‪auto begin = v.begin(),‬‬
‫‪                    end = v.end(); // bad idea, saving value of end iterator‬‬
‫{ )‪while (begin != end‬‬
‫‪    // do some processing‬‬
‫‪    // insert new value and reassign begin, which otherwise would be invalid‬‬
‫;‪    ++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‬‬
‫}‬

‫معرف‪ .‬في العديد من التطبيقات ‪ ،‬سنحصل على حلقة ال نهائية‪.‬‬


‫سلوك هذا الكود غري ّ‬ ‫•‬
‫تكمن املشكلة في أننا قمنا بتخزين القيمة املعادة من خالل عملية نهاية_ في متغري محلي يسمى ‪.end‬‬ ‫•‬
‫أضفنا عنرصًا في بنية الحلقة‪.‬‬ ‫•‬
‫تؤدي إضافة عنرص إلى إبطال املكرر املخزن في نهاية_‪.‬‬ ‫•‬
‫لن يشري هذا املكرر إلى عنرص في ‪ v‬ولن يشري بعد اآلن إلى آخر عنرص في ‪.v‬‬ ‫•‬

‫تلميح‬

‫ال تقم بتخزين املكرر العائد من نهاية_ مؤق ًتا في حلقات تُدرج عنارص أو تحذفها في طابور أو سلسلة أو متجه‪.‬‬

‫بدال ً من تخزين مكرر نهاية_ ‪ ،‬ينبغي علينا إعادة حسابه بعد كل مدخالت‪:‬‬

‫‪// 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.3.6‬‬

‫التمرين ‪: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‬‬

‫لدعم الوصول العشوائي الرسيع ‪ ،‬يتم تخزين عنارص املتجه بشكل متجاور ‪ -‬كل عنرص مجاور للسابق‪.‬‬
‫في العادة ‪ ،‬ال يجب أن نهتم بكيفية تنفيذ نوع املكتبة ؛ كل ما يجب أن نهتم به هو كيفية استخدامه‪.‬‬ ‫•‬
‫ومع ذلك ‪ ،‬في حالة املتجهات والسالسل ‪ ،‬يترسب جزء من التنفيذ إلى واجهته‪.‬‬ ‫•‬
‫بالنظر إلى أن العنارص متجاورة ‪ ،‬وأن حجم الحاوية مرن ‪،‬‬
‫فكر في ما يجب أن يحدث عندما نضيف عنرصًا إلى متجه أو سلسلة‪:‬‬ ‫•‬
‫إن لم يكن هناك مكان لعنرص جديد ‪ ،‬فال يمكن للحاوية إضافة عنرص في مكان آخر في الذاكرة – فالعنارص‬ ‫•‬
‫يجب أن تكون متجاورة‪.‬‬
‫بدال ً من ذلك ‪ ،‬يجب أن تخصص الحاوية ذاكرة جديدة ‪:‬‬ ‫•‬
‫لتحمل العنارص املوجودة باإلضافة إلى العنرص الجديد ‪،‬‬ ‫•‬
‫وتنقل العنارص من املوقع القديم إلى املساحة الجديدة ‪،‬‬ ‫•‬
‫• وتقوم بإضافة العنرص الجديد ‪ ،‬وإلغاء تخصيص الذاكرة القديمة‪.‬‬
‫• إن قام املتجه بتخصيص الذاكرة وإلغاء التخصيص في كل مرة نضيف فيها عنرصًا ‪ ،‬فسيكون األداء بطيًئ ا‬
‫بشكل غري مقبول‪.‬‬
‫لتجنب هذه التكاليف ‪ ،‬يستخدم منفذو املكتبات اسرتاتيجيات تخصيص تقلل من عدد مرات إعادة تخصيص الحاوية‪.‬‬
‫عندما يتعني عليهم الحصول على ذاكرة جديدة ‪،‬‬ ‫•‬
‫فإن تطبيقات املتجهات والسلسلة عاد ًة ما تخصص سعة تتجاوز الحجم املطلوب في لحظته‪.‬‬ ‫•‬
‫تحتفظ الحاوية بهذا التخزين في االحتياط وتستخدمه لتخصيص عنارص جديدة عند إضافتها‪.‬‬ ‫•‬
‫وبالتالي ‪ ،‬ليست هناك حاجة إلعادة تخصيص الحاوية لكل عنرص جديد‪.‬‬ ‫•‬
‫تعترب اسرتاتيجية التخصيص هذه أكرث كفاءة بكثري من إعادة تخصيص الحاوية كل مرة يتم فيها إضافة عنرص‪.‬‬
‫في الواقع ‪ ،‬يعد األداء جيداً بما يكفي بحيث أنه عملياً ينمو املتجه بكفاءة أكرث من القائمة أو الطابور ‪،‬‬ ‫•‬
‫بالرغم من أن املتجه يجب أن يحرك جميع عنارصه في كل مرة يعيد تخصيص الذاكرة‪.‬‬ ‫•‬

‫‪Members to Manage Capacity‬‬ ‫أعضاء ﻹدارة السعة‬

‫توفر أنواع املتجهات والسلسلة أعضاء ‪ ،‬موصوفة في الجدول ‪ ، 9.10‬تتيح لنا التفاعل مع جزء تخصيص الذاكرة من‬
‫التنفيذ‪.‬‬
‫• تخربنا عملية السعة عن عدد العنارص اليت يمكن للحاوية االحتفاظ بها قبل أن تخصص مساحة أكرب‪.‬‬
‫وتتيح لنا عملية الحجز إخبار الحاوية بعدد العنارص اليت يجب أن تكون مستعدة لالحتفاظ بها‪.‬‬ ‫•‬

‫الجدول ‪ .9.10‬إدارة حجم الحاوية‬

‫تصلح عملية قلص_لتالئم ‪ shrink_to_fit‬للمتجه والسلسلة والطابور؛‬ ‫•‬

‫بينما تختص عمليتا الحجز ‪ reserve‬والسعة ‪ capacity‬باملتجه والسلسلة فقط‬ ‫•‬


‫)(‪c.shrink_to_fit‬‬ ‫‪Request to reduce capacity() to equal size().‬‬

‫‪Number of elements c can have before reallocation is‬‬


‫)(‪c.capacity‬‬
‫‪necessary.‬‬

‫)‪c.reserve(n‬‬ ‫‪Allocate a space for at least n elements.‬‬

‫ملحوظة‬

‫ال يغري الحجز عدد العنارص في الحاوية ؛ إذ يؤثر فقط على مقدار الذاكرة اليت يخصصها املتجه مسب ًقا‪.‬‬

‫يغري استدعاء الحجز سعة املتجه فقط إن تجاوزت املساحة املطلوبة السعة الحالية‪.‬‬ ‫•‬
‫أما إن كان الحجم املطلوب أكرب من السعة الحالية ‪ ،‬سيخصص الحجز على األقل سعة على (وقد يخصص‬ ‫•‬
‫أكرث من) الحجم املطلوب‪.‬‬
‫إن كان الحجم املطلوب أقل من أو يساوي السعة الحالية ‪ ،‬فلن يفعل الحجز شيًئ ا‪.‬‬ ‫•‬
‫تحديداً ‪ ،‬ال يؤدي استدعاء الحجز على حجم أصغر من السعة إلى إعادة الحاوية للذاكرة‪.‬‬ ‫•‬
‫وبالتالي ‪ ،‬بعد استدعاء الحجز ‪ ،‬ستكون السعة أكرب من أو تساوي الوسيطة اليت تم تمريرها للحجز‪.‬‬ ‫•‬
‫نتيجة لذلك ‪ ،‬لن يقلل استدعاء الحجز من مقدار املساحة اليت تستخدمها الحاوية‪.‬‬ ‫•‬
‫وباملثل ‪ ،‬فإن أعضاء تغيري الحجم ﻻ تغري إﻻ عدد العنارص في الحاوية ‪ ،‬وليس سعتها‪.‬‬ ‫•‬
‫• ال يمكننا استخدام تغيري الحجم لتقليل الذاكرة اليت تحتفظ بها الحاوية‪.‬‬
‫تحت املكتبة الجديدة ‪ ،‬يمكننا استدعاء قلّ ص_ليالئم ‪ shrink_to_fit‬لنطلب من طابور أو متجه أو سلسلة‬
‫إعادة ذاكرة غري رضورية‪.‬‬
‫• تشري هذه الدالة إلى أننا لم نعد بحاجة إلى أي سعة فائضة‪.‬‬
‫مع ذلك ‪ ،‬فإن التنفيذ حر في تجاهل هذا الطلب‪.‬‬ ‫•‬
‫فليس هناك ما يضمن أن استدعاء ‪ shrink_to_fit‬سيعيد الذاكرة‪.‬‬ ‫•‬

‫‪capacity and size‬‬ ‫السعة والحجم‬

‫من املهم فهم الفرق بني السعة والحجم‪.‬‬


‫حجم الحاوية هو عدد العنارص اليت تحتوي عليها بالفعل ؛‬ ‫•‬
‫بينما سعتها هي عدد العنارص اليت يمكنها االحتفاظ بها قبل أن يتم تخصيص مساحة أكرب لها‪.‬‬ ‫•‬
‫يوضح الكود التالي التفاعل بني الحجم والسعة‪:‬‬

‫;‪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‬‬

‫عند تشغيله على نظامنا ‪ ،‬ينتج عن هذا الرمز املخرجات التالية‪:‬‬

‫‪ivec: size: 0 capacity: 0‬‬


‫‪ivec: size: 24 capacity: 32‬‬

‫نحن نعلم أن حجم املتجه الفارغ سيساوي صفرًا ‪،‬‬ ‫•‬


‫أيضا سعة املتجه الفارغ إلى الصفر‪.‬‬
‫تعرف ً‬
‫ومن الواضح أن مكتبتنا ّ‬ ‫•‬
‫عندما نضيف عنارص إلى املتجه ‪ ،‬نعلم أن الحجم هو نفسه عدد العنارص اليت أضفناها‪.‬‬ ‫•‬
‫ينبغي أن يكون حجم السعة كبرياً كالحجم على األقل لكن يمكن أن يكون أكرب‪.‬‬ ‫•‬
‫تختلف تفاصيل مقدار السعة الزائدة املخصصة حسب تطبيقات املكتبة‪.‬‬ ‫•‬
‫في ظل هذا التنفيذ ‪ ،‬فإن إضافة ‪ 24‬عنرصًا واح ًدا في كل مرة ينتج عنها سعة ‪.32‬‬ ‫•‬
‫برصيا يمكننا التفكري في الوضع الحالي لـ ‪ ivec‬ويمكننا اآلن حجز بعض املساحة اإلضافية‪:‬‬

‫يمكننا اﻵن حجز بعض املساحة اﻹضافية ‪:‬‬

‫‪ivec.reserve(50); // sets capacity to at least 50; might be more‬‬


‫‪// size should be 24; capacity will be >= 50 and is implementation defined‬‬
‫)(‪cout << "ivec: size: " << ivec.size‬‬
‫;‪<< " capacity: " << ivec.capacity() << endl‬‬

‫هنا ‪ ،‬تشري املخرجات إلى أن استدعاء الحجز قد خصص بالضبط املساحة اليت طلبناها‪:‬‬

‫‪ivec: size: 24 capacity: 50‬‬

‫قد نستخدم بعد ذلك هذه السعة املحجوزة على النحو التالي‪:‬‬

‫‪// add elements to use up the excess capacity‬‬


‫))(‪while (ivec.size() != ivec.capacity‬‬
‫;)‪ivec.push_back(0‬‬
‫‪// capacity should be unchanged and size and capacity are now equal‬‬
‫)(‪cout << "ivec: size: " << ivec.size‬‬
‫;‪<< " capacity: " << ivec.capacity() << endl‬‬
‫تشري املخرجات إلى أننا استنفدنا السعة املحجوزة في هذه املرحلة ‪ ،‬وأصبح الحجم والسعة متساويان‪:‬‬

‫‪ivec: size: 50 capacity: 50‬‬

‫ونظر ًا ألننا استخدمنا السعة املحجوزة فقط ‪ ،‬فال داعي أن يقوم املتجه بأي تخصيص‪.‬‬ ‫•‬
‫في الواقع ‪ ،‬طاملا لم تتجاوز أي عملية سعة املتجه ‪ ،‬يجب أال يعيد املتجه تخصيص عنارصه‪.‬‬ ‫•‬
‫إن أضفنا اآلن عنرصًا آخر ‪ ،‬فسيتعني على املتجه إعادة تخصيص نفسه‪:‬‬

‫‪ivec.push_back(42); // add one more element‬‬


‫‪// size should be 51; capacity will be >= 51 and is implementation defined‬‬
‫)(‪cout << "ivec: size: " << ivec.size‬‬
‫;‪<< " capacity: " << ivec.capacity() << endl‬‬

‫ستكون املخرجات من هذا الجزء من الربنامج‬

‫‪ivec: size: 51 capacity: 100‬‬

‫يشري إلى أن تنفيذ املتجه هذا يبدو أنه يتبع اسرتاتيجية ملضاعفة سعته الحالية في كل مرة يتعني عليه‬ ‫•‬
‫تخصيص تخزين جديد‪.‬‬
‫يمكننا استدعاء ‪ shrink_to_fit‬لنطالب بإعادة الذاكرة اليت تتجاوز الحجم املطلوب الحالي إلى النظام‪:‬‬ ‫•‬

‫‪ivec.shrink_to_fit(); // ask for the memory to be returned‬‬


‫‪// size should be unchanged; capacity is implementation defined‬‬
‫)(‪cout << "ivec: size: " << ivec.size‬‬
‫;‪<< " capacity: " << ivec.capacity() << endl‬‬

‫استدعاء ‪ shrink_to_fit‬ليس سوى طلب ؛ فليس هناك ما يضمن أن املكتبة ستعيد الذاكرة‪.‬‬ ‫•‬

‫ملحوظة‬

‫يمكن لكل تطبيق متجه اختيار إسرتاتيجية تخصيص يخصه‪.‬‬ ‫•‬


‫مع ذلك ‪ ،‬يجب أال تخصص ذاكرة جديدة حىت تضطر إلى القيام بذلك‪.‬‬ ‫•‬

‫ال يجوز إعادة تخصيص املتجه إال عندما يقوم املستخدم بإجراء عملية إدراج حيث يساوي الحجم السعة ‪،‬‬ ‫•‬
‫أو عند استدعاء تغيري الحجم أو الحجز بقيمة تتجاوز السعة الحالية‪.‬‬ ‫•‬
‫يعود مقدار الذاكرة املخصصة بعد املقدار املحدد إلى التنفيذ‪.‬‬ ‫•‬
‫كل تنفيذ مطلوب التباع إسرتاتيجية تضمن كفاءة استخدام دفع_للخلف إلضافة عنارص إلى املتجه‪.‬‬ ‫•‬
‫من الناحية الفنية ‪ ،‬ينبغي أال يزيد وقت تنفيذ إنشاء متجه بالعنرص ‪ n‬عن طريق استدعاء دفع_للخلف على‬ ‫•‬
‫‪ n‬مرة على متجه فارغ في بداية_ أكرث من مضاعف ثابت لـ ‪.n‬‬

‫تمارين القسم ‪9.4‬‬


‫التمرين ‪:9.35‬‬
‫ارشح الفرق بني سعة املتجه وحجمه‪.‬‬

‫التمرين ‪: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‬‬ ‫•‬
‫أو تضيف إصدارات تتيح لنا استخدام الفهارس كبديل عن املكررات‪.‬‬ ‫•‬
‫أنماطا متكررة‪.‬‬
‫ً‬ ‫تعرف مكتبة السلسلة عد ًدا كبريًا من الدوال‪ .‬لحسن الحظ ‪ ،‬تستخدم هذه الدوال‬
‫ّ‬
‫وبالنظر إلى عدد الدوال املدعومة ‪ ،‬يمكن أن يكون هذا القسم مذهالً عند القراءة األولى ؛‬ ‫•‬
‫لذلك قد يرغب القراء في االطالع على تلك الدوال‪ .‬لكن بمجرد معرفة أنواع العمليات املتاحة ‪،‬‬ ‫•‬
‫سيمكنهم العودة لالطالع على تفاصيل أكرث عندما يحتاجون إلى استخدام عملية معينة‪.‬‬ ‫•‬

‫‪9.5.1. Other Ways to Construct strings‬‬ ‫‪ 9٫5٫1‬طرق أخرى ﻹنشاء السالسل‬

‫إضافة إلى املُنشئات اليت قمنا بتغطيتها في الفقرة ‪، 3.2.1‬‬


‫وكذلك امل ُنشئات اليت تتشاركها السلسلة مع الحاويات املتسلسلة األخرى (جداول ‪، )9.3‬‬ ‫•‬
‫يدعم نوع السلسلة ثالثة ُمنشئات أخرى موصوفة في الجدول ‪.9.11‬‬ ‫•‬

‫الجدول ‪ .9.11‬طرق إضافية لبناء السالسل‬

‫القيم ‪ n, len2, pos2‬كلها قيم بال_إشارة‬

‫‪s is a copy of the first n characters in the‬‬


‫)‪string s(cp, n‬‬ ‫‪array to which cp points.‬‬
‫‪That array must have at least n characters.‬‬

‫‪s is the copy of the characters in the string‬‬


‫)‪string s(s2, pos2‬‬ ‫‪s2 starting at the index pos2.‬‬
‫‪Undefined if pos2 > s2.size().‬‬

‫‪s is a copy of len2 characters from s2‬‬


‫‪starting at the index pos2.‬‬
‫)‪string s(s2, pos2, len2‬‬ ‫‪Undefined if pos2 > s2.size().‬‬
‫‪Regardless of the value of len2, copies at‬‬
‫‪most s2.size() - pos2 characters.‬‬

‫تأخذ املنشئات اليت تأخذ سلسلة أو مؤرشاً لحرف ثابت وسيطات إضافية (اختيارية) تتيح لنا تحديد عدد‬ ‫•‬
‫األحرف املراد نسخها‪.‬‬
‫أيضا تحديد فهرس أين يبدأ النسخ ‪:‬‬
‫فعندما نمرر سلسلة ‪ ،‬يمكننا ً‬ ‫•‬

‫‪const char *cp = "Hello World!!!"; // null-terminated array‬‬


‫‪char noNull[] = {'H', 'i'};        // not null terminated‬‬
‫"!!!‪string s1(cp);  // copy up to the null in cp; s1 == "Hello World‬‬
‫"‪string s2(noNull,2); // copy two characters from no_null; s2 == "Hi‬‬
‫‪string s3(noNull);   // undefined: noNull not null terminated‬‬
‫"‪string s4(cp + 6, 5);// copy 5 characters starting at cp[6]; s4 == "World‬‬
‫"‪string s5(s1, 6, 5); // copy 5 characters starting at s1[6]; s5 == "World‬‬
‫"!!!‪string s6(s1, 6);    // copy from s1 [6] to end of s1; s6 == "World‬‬
‫"!!!‪string s7(s1,6,20);  // ok, copies only to end of s1; s7 == "World‬‬
‫‪string s8(s1, 16);   // throws an out_of_range exception‬‬

‫في العادة عندما ننئش سلسلة من مؤرش لحرف ثابت ‪،‬‬ ‫•‬
‫يتم أن تكون املصفوفة اليت يجب أن يكون املؤرش يشري إليها منتهية بحرف خال ؛‬ ‫•‬
‫ويتم نسخ األحرف إلى القيمة الفارغة‪.‬‬ ‫•‬
‫أيضا عد ًدا ‪ ،‬فال يلزم إنهاء املصفوفة بحرف خال‪.‬‬
‫إن مررنا ً‬ ‫•‬
‫إن لم نمرر عد ًدا ولم يكن هناك أي قيمة فارغة ‪ ،‬أو كان العدد املحدد أكرب من حجم املصفوفة ‪،‬‬ ‫•‬
‫معرفة‪.‬‬
‫فإن العملية تكون غري ّ‬ ‫•‬
‫عندما نقوم بالنسخ من سلسلة ‪ ،‬يمكننا توفري موضع بدء اختياري وعدد‪.‬‬
‫يجب أن يكون موضع البداية أقل من أو يساوي حجم السلسلة املحددة‪.‬‬ ‫•‬
‫إن كان املوضع أكرب من الحجم ‪ ،‬فإن املُنشئة تطرح االستثناء خارج_النطاق ‪.out_of_range‬‬ ‫•‬
‫بدءا من املوضع املحدد‪.‬‬
‫عندما نمرر العد ‪ ،‬يتم نسخ عدد من األحرف ‪ً ،‬‬ ‫•‬
‫وبغض النظر عن عدد األحرف اليت نطلبها ‪ ،‬تنسخ املكتبة حىت حجم السلسلة ‪ ،‬لكن ليس أكرث‪.‬‬ ‫•‬

‫‪The substr Operation‬‬ ‫العملية سلسلة_فرعية‬

‫تعيد عملية السلسلة الفرعية (املوضحة في الجدول ‪ )9.12‬سلسلة عبارة عن نسخة السلسلة األصلية أو جزء منها‪.‬‬
‫يمكننا تمرير موضع بدء اختياري للمجموعة الفرعية والعد ‪:‬‬ ‫•‬

‫;)"‪string s("hello world‬‬


‫‪string s2 = s.substr(0, 5);  // s2 = hello‬‬
‫‪string s3 = s.substr(6);     // s3 = world‬‬
‫‪string s4 = s.substr(6, 11); // s3 = world‬‬
‫‪string s5 = s.substr(12);    // throws an out_of_range exception‬‬

‫الجدول ‪ .9.12‬عملية السلسلة_الفرعية‬

‫‪Return a string containing n characters from s‬‬


‫‪starting at pos.‬‬
‫)‪s.substr(pos n‬‬ ‫‪pos default to zero. n default to value that causes‬‬
‫‪the library to copy all the characters in s starting‬‬
‫‪from pos.‬‬
‫تطرح دالة السلسلة الفرعية االستثناء خارج_النطاق إن تجاوز املوضع حجم السلسلة‪.‬‬ ‫•‬
‫إن كان املوضع باإلضافة إلى العدد أكرب من الحجم ‪ ،‬فسيتم تعديل العد لينسخ فقط حىت آخر السلسلة‪.‬‬ ‫•‬

‫تمارين القسم ‪9.5.1‬‬

‫التمرين ‪:9.41‬‬
‫برنامجا يقوم بتهيئة سلسلة على متجه <‪.>char‬‬
‫ً‬ ‫اكتب‬

‫التمرين ‪:9.42‬‬
‫‪ -‬نظر ًا ألنك تريد قراءة حرف في كل مرة في سلسلة ‪ ،‬وأنت تعلم أنك بحاجة إلى قراءة ‪ 100‬حرف على األقل ‪،‬‬
‫‪ -‬فكيف يمكنك تحسني أداء برنامجك؟‬

‫‪9.5.2. Other Ways to Change a string‬‬ ‫‪ 9٫5٫2‬طرق أخرى لتغيري سلسلة‬

‫يدعم نوع السلسلة عوامل التعيني للحاويات املتسلسلة وعمليات تعيني ‪ assign‬وإدراج ‪ insert‬ومسح ‪.erase‬‬
‫أيضا إصدارات إضافية من اإلدراج واملسح‪.‬‬
‫يعرف ً‬
‫وكذلك ّ‬ ‫•‬
‫فهرسا‪.‬‬
‫ً‬ ‫وإضافة إلى إصدارات اإلدراج واملسح اليت تأخذ مكررات ‪ ،‬توفر السلسلة إصدارات تأخذ‬ ‫•‬
‫يشري الفهرس إلى عنرص البداية املراد مسحه أو املوضع الذي يجب إدراج القيم املحددة قبله‪:‬‬ ‫•‬

‫‪s.insert(s.size(), 5, '!'); // insert five exclamation points at end of s‬‬


‫‪s.erase(s.size() - 5, 5);   // erase last five characters from s‬‬

‫أيضا إصدارات من اإلدراج والتعيني تأخذ مصفوفات األحرف من النمط ‪.C‬‬


‫توفر مكتبة السالسل ً‬ ‫•‬
‫مثالً ‪ ،‬يمكننا استخدام مصفوفة أحرف منتهية بقيمة خالية كقيمة إلدراجها أو تعيينها في سلسلة‪:‬‬ ‫•‬

‫;"‪const char *cp = "Stately, plump Buck‬‬


‫;)‪s.assign(cp, 7‬‬ ‫"‪// s == "Stately‬‬
‫"‪s.insert(s.size(), cp + 7); // s == "Stately, plump Buck‬‬

‫هنا نقوم أوال ً باستبدال محتويات ‪ 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());

The append and replace Functions _‫الدوال إلحاق_ واستبدال‬

.‫ يمكنهما تغيري محتويات سلسلة‬، _‫ إلحاق_ واستبدال‬، ‫تعر ف فئة السلسلة عضوين إضافيتني‬
ّ
.‫ هذه الدوال‬9.13 ‫يلخص الجدول‬ •
: ‫عملية إلحاق_ تعترب طريقة مخترصة لإلدراج من النهاية‬ •

string s("C++ Primer"), s2 = s; // initialize s and s2 to "C++ Primer"


s.insert(s.size(), " 4th Ed."); // s == "C++ Primer 4th Ed."
s2.append(" 4th Ed."); // equivalent: appends " 4th Ed." to s2; s == s2

: ‫عمليات استبدال_ تعترب طريقة مخترصة الستدعاء املسح واﻹدراج‬ •

// equivalent way to replace "4th" by "5th"


s.erase(11, 3);                  // s == "C++ Primer Ed."
s.insert(11, "5th");             // s == "C++ Primer 5th Ed."
// starting at position 11, erase three characters and then insert "5th"
s2.replace(11, 3, "5th"); // equivalent: s == s2

‫ عمليات لتعديل السالسل‬.9.13 ‫الجدول‬

Insert characters specified by args before pos. pos can be


an index or an iterator.
s.insert
Versions taking an index return a reference to s; those
(pos, args)
taking an iterator return an iterator denoting the first
inserted character.

Remove len characters starting at position pos. if len is


s.erase
omitted, removes characters from pos to the end of the s.
(pos,len)
Return a reference to s.

s.assign Replace characters in s according to args.


(args) Return a reference to s.

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.

str The string str.

str, pos, len Up to len characters from str starting at pos.

Up to len characters from the character array pointed by


cp, len
cp.

cp Null-terminated array pointed to by pointer cp.

n, c n copies of character c.

b, e Characters in the range formed by iterators b and e.

initializer
Comma-separated list of characters enclosed in braces.
list

args for replace and insert depend on how range or pos is specialized.

replace replace insert insert args can be

(pos,len,args) (b,e,args) (pos, args) (iter, args)

yes yes yes no str

yes no yes no str, pos, len

yes yes yes no cp, len

yes yes no no cp

yes yes yes yes n, c

no yes no yes b2, e2

Initialize
no yes no yes
list

.‫ يكون النص الذي أدخلناه بنفس حجم النص الذي أزلناه‬، _‫في استدعاء استبدال‬ •
:‫يمكننا إدراج سلسلة أكرب أو أصغر‬ •
‫"‪s.replace(11, 3, "Fifth");      // s == "C++ Primer Fifth Ed.‬‬

‫في هذه االستدعاء نزيل ثالثة أحرف لكن نضيف خمسة في مكانها‪.‬‬ ‫•‬

‫العديد من الطرق زائدة التعبئة لتغيري سلسلة‬


‫‪The Many Overloaded Ways to Change a string‬‬

‫الدوال إلحاق_ ‪ ،‬وتعيني_ ‪ ،‬وإدراج_ ‪ ،‬واستبدال_ املدرجة في الجدول ‪ 9.13‬تملك عدة إصدارات زائدة التعبئة‪.‬‬
‫تختلف وسيطاتها بحسب كيفية تحديد األحرف املراد إضافتها وأي جزء من السلسلة يجب تغيريه‪.‬‬ ‫•‬
‫لحسن الحظ ‪ ،‬تشرتك هذه الدوال في واجهة مشرتكة‪.‬‬ ‫•‬
‫ال تحتاج الدوال تعيني_ وإلحاق_ إلى تحديد جزء السلسلة الذي تم تغيريه ‪:‬‬ ‫•‬
‫دائما إلى آخرها‪.‬‬
‫ً‬ ‫دائما محتويات السلسلة بالكامل ويضيف إلحاق_‬‫ً‬ ‫يستبدل تعيني_‬ ‫•‬
‫توفر دوال استبدال_ طريقتني لتحديد نطاق الحروف املراد إزالتها‪.‬‬ ‫•‬
‫فيمكننا تحديد هذا النطاق من خالل املوضع والطول ‪ ،‬أو عن طريق نطاق مكرر‪.‬‬ ‫•‬
‫تمنحنا دوال إدراج_ طريقتني لتعريف نقطة اإلدراج‪:‬‬ ‫•‬
‫إما باستخدام الفهرس وإما باستخدام مكرر‪.‬‬ ‫•‬
‫في كل حالة ‪ ،‬يتم إدراج العنـ (ــا) رص الجديدة أمام فهرس أو مكرر محدد‪.‬‬ ‫•‬
‫هناك عدة طرق لتحديد أحرف عند إضافتها إلى سلسلة ؛ حيث يمكن أن تؤخذ اﻷحرف الجديدة ‪...‬‬
‫من سلسلة أخرى ‪ ،‬من مؤرش حرف ‪ ،‬من قائمة أحرف محاطة بأقواس ‪ ،‬أو كحرف وعدد‪.‬‬ ‫•‬
‫عندما تأتي األحرف من سلسلة أو مؤرش حرف ‪،‬‬ ‫•‬
‫يمكن تمرير وسيطات إضافية للتحكم في ما إن كنا ننسخ بعض تلك اﻷحرف أو كلها من الوسيطة‪.‬‬ ‫•‬
‫ال تدعم كل الدوال جميع نسخ هذه الوسيطات‪.‬‬
‫فعلى سبيل املثال ‪ ،‬ال يوجد إصدار من إدراج_ يأخذ فهرساً وقائمة ُمهئي‪.‬‬ ‫•‬
‫وباملثل ‪ ،‬إن أردنا تعريف نقطة اإلدراج باستخدام مكرر ‪،‬‬ ‫•‬
‫فال يمكننا تمرير مؤرش حرف كمصدر لألحرف الجديدة‪.‬‬ ‫•‬

‫تمارين القسم ‪9.5.2‬‬

‫التمرين ‪:9.43‬‬
‫‪ -‬اكتب دالة تأخذ ثالث سالسل ‪ ، s ،‬و ‪ ، oldVal‬و ‪ .newVal‬باستخدام املكررات ‪،‬‬
‫‪ -‬تحل دالتا اإلدراج واملحو محل جميع مثيالت ‪ oldVal‬اليت تظهر في ‪ s‬بواسطة ‪.newVal‬‬
‫‪ -‬اخترب دالتك عن طريق استخدامها الستبدال اختصارات شائعة ‪،‬‬
‫‪ -‬مثل استبدال "‪ "tho‬بـ "‪ "though‬واستبدال "‪ "thru‬بـ "‪."through‬‬

‫التمرين ‪:9.44‬‬
‫أعد كتابة الدالة السابقة باستخدام فهرس واستبدل‪.‬‬
‫التمرين ‪:9.45‬‬
‫اسما وسلسلتني آخرتني تمثالن بادئة ‪،‬‬
‫ً‬ ‫‪ -‬اكتب دالة تأخذ سلسلة تمثل‬
‫‪ -‬مثل "‪ ".Mr‬أو "‪ ".Mrs‬والحقة ‪ ،‬مثل "‪ ".Jr‬أو "‪."III‬‬
‫‪ -‬باستخدام املكررات ودوال اإلدراج واإللحاق ‪،‬‬
‫‪ -‬قم بإنشاء سلسلة جديدة وإعادتها مع إضافة الالحقة والبادئة إلى االسم املحدد‪.‬‬

‫التمرين ‪:9.46‬‬
‫‪ -‬أعد كتابة التمرين السابق باستخدام موضع وطول إلدارة األوتار‪ .‬هذه املرة استخدم فقط دالة اإلدراج‪.‬‬

‫‪9.5.3. string Search Operations‬‬ ‫‪ 9٫5٫3‬عمليات بحث السلسلة‬

‫توفر فئة السلسلة ست دوال بحث مختلفة ‪ ،‬لكل منها أربع نسخ زائدة التعبئة‪.‬‬
‫يصف الجدول ‪ 9.14‬أعضاء البحث ووسيطاتها‪.‬‬ ‫•‬
‫تقوم كل عملية من عمليات البحث هذه بإعادة قيمة ‪ string::size_type‬تمثل فهرس أين صادف‬ ‫•‬
‫التطابق‪.‬‬
‫إن لم يكن هناك تطابق ‪ ،‬تقوم الدالة بإعادة عضو ثابت باسم ‪.string::npos‬‬ ‫•‬
‫تُعرِّف املكتبة ‪ npos‬على أنها ‪ string::size_type‬تمت تهيئتها على القيمة ‪.1-‬‬ ‫•‬
‫وألن ‪ npos‬هو نوع بال_إشارة ‪ ،‬فإن هذا املُهئي يعين أن ‪ npos‬يساوي أكرب حجم قد تحتويه أي سلسلة‪.‬‬ ‫•‬

‫الجدول ‪ .9.14‬سلسلة عمليات البحث‬

‫تعيد عمليات البحث هذه فهرساً للحرف املطلوب أو ‪ npos‬إن لم يتم العثور عليه‬

‫)‪s.find(args‬‬ ‫‪Find the first occurrence of args in s.‬‬

‫)‪s.rfind(args‬‬ ‫‪Find the last occurrence of args in s.‬‬

‫‪Find the first occurrence of any character‬‬


‫)‪s.find_first_of(args‬‬
‫‪from args in s.‬‬

‫‪Find the last occurrence of any character‬‬


‫)‪s.find_last_of(args‬‬
‫‪from args in s.‬‬

‫‪s.find_first_not_of(args‬‬ ‫‪Find the first character in s that is not‬‬


‫)‬ ‫‪in args.‬‬

‫‪Find the last character in s that is not in‬‬


‫)‪s.find_last_not_of(args‬‬
‫‪args.‬‬
‫‪args must be one of‬‬
‫‪Look for the character c starting at position‬‬
‫‪c, pos‬‬
‫‪pos in s. pos defaults to zero.‬‬
Look for the string s2 starting at position
s2, pos
pos in s. pos defaults to zero.

Look for the C-style null-terminated string


cp, pos pointed to by the pointer cp. Start looking a
position pos in s. pos defaults to zero.

Look for the first n characters in the array


cp, pos, n pointed by the pointer cp. Start looking at
position pos in s. No default for pos or n.

‫تحذير‬

.‫ وهو نوع بال_إشارة‬، string::size_type ‫تعيد دوال البحث عن السلسلة‬ •


.‫ لحفظ بالعائد من تلك الدوال فكرة سيئة‬، ‫ أو أي نوع ذي إشارة آخر‬، int ‫ استخدام‬، ‫نتيجة لذلك‬ •

.‫تقوم دالة البحث بأبسط بحث‬ •


:‫ إن لم يكن هناك تطابق‬npos ‫ أو‬، ‫يبحث عن وسيطته ويعيد فهرس أول تطابق يتم العثور عليه‬ •

string name("AnnaBelle");
auto pos1 = name.find("Anna"); // pos1 == 0

."AnnaBelle" ‫" في‬Anna" ‫ الفهرس الذي توجد عنده السلسلة الفرعية‬، 0 ‫تعيد القيمة‬ •
.‫البحث (وعمليات السالسل األخرى) حساسة لحالة األحرف‬ •
:‫ فإن الحالة مهمة‬، ‫عندما نبحث عن قيمة في السلسلة‬ •

string lowercase("annabelle");
pos1 = lowercase.find("Anna");   // pos1 == npos

.anna ‫ ال تتطابق مع‬Anna ‫ ألن‬npos ‫ على‬pos1 ‫سيعني هذا الرمز‬ •


.‫تتطلب املشكلة األكرث تعقي ًدا إيجاد تطابق مع أي حرف في سلسلة البحث‬
:‫يعرف ما يلي أول رقم داخل االسم‬
ّ ، ‫على سبيل املثال‬ •

string numbers("0123456789"), name("r2d2");


// returns 1, i.e., the index of the first digit in name
auto pos = name.find_first_of(numbers);

، ‫بدال ً من البحث عن تطابق‬ •


.‫ للعثور على أول موضع غري موجود في وسيطة البحث‬find_first_not_of ‫يمكننا استدعاء‬ •
‫على سبيل املثال ‪ ،‬للعثور على أول حرف غري رقمي من سلسلة ‪ ،‬يمكننا كتابة‬ ‫•‬

‫;)"‪string dept("03714p3‬‬
‫'‪// returns 5, which is the index to the character 'p‬‬
‫;)‪auto pos = dept.find_first_not_of(numbers‬‬

‫‪Specifying Where to Start the Search‬‬ ‫تحديد مكان بدء البحث‬

‫يمكننا تمرير موضع بدء اختياري لعمليات البحث‪.‬‬


‫تشري هذه الوسيطة االختيارية إلى املوضع الذي يبدأ منه البحث‪.‬‬ ‫•‬
‫افرتاضياً ‪ ،‬يتم تعيني هذا املوضع على صفر‪.‬‬ ‫•‬
‫يستخدم أحد أنماط الربمجة الشائعة هذه كوسيطة اختيارية تتنقل عرب سلسلة للعثور على كل املصادفات ‪:‬‬ ‫•‬

‫;‪string::size_type pos = 0‬‬


‫‪// each iteration finds the next number in name‬‬
‫{ )‪while ((pos = name.find_first_of(numbers, pos))!= string::npos‬‬
‫‪    cout << "found number at index: " << pos‬‬
‫;‪         << " element is " << name[pos] << endl‬‬
‫‪    ++pos; // move to the next character‬‬
‫}‬

‫بدءا من القيمة الحالية لـ ‪.pos‬‬


‫يعيد الرشط في ‪ while‬تعيني ‪ pos‬إلى فهرس أول رقم يصادفه ‪ً ،‬‬ ‫•‬
‫صالحا ‪ ،‬فإننا نطبع النتيجة الحالية ونقوم بمزايدة ‪.pos‬‬
‫ً‬ ‫فهرسا‬
‫ً‬ ‫وطاملا أن ‪ find_first_of‬تعيد‬ ‫•‬
‫لو أهملنا مزايدة ‪ ، pos‬ربما لن تنتهي الحلقة أبداً‪.‬‬ ‫•‬
‫ملعرفة السبب ‪ ،‬فكر في ما سيحدث إن لم نفعل املزايدة‪.‬‬ ‫•‬
‫في الرحلة الثانية عرب الحلقة ‪ ،‬سنبدأ في النظر إلى الحرف املفهرس بواسطة ‪.pos‬‬ ‫•‬
‫رقما ‪ ،‬لذا فإن ‪ find_first_of‬ستعيد (بشكل متكرر) ‪!pos‬‬
‫سيكون ذلك الحرف ً‬ ‫•‬

‫‪Searching Backward‬‬ ‫البحث للخلف‬

‫يتم تنفيذ عمليات البحث اليت استخدمناها حىت اآلن من اليسار إلى اليمني‪.‬‬
‫توفر املكتبة عمليات مماثلة تقوم بالبحث من اليمني إلى اليسار‪.‬‬ ‫•‬
‫يبحث العضو ‪ 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.5.3‬‬

‫التمرين ‪:9.47‬‬
‫برنامجا يبحث عن كل حرف رقمي ثم كل حرف أبجدي في السلسلة "‪."ab2c3d7R4E6‬‬
‫ً‬ ‫‪ -‬اكتب‬
‫‪ -‬اكتب نسختني من الربنامج‪.‬‬
‫‪ -‬يجب أن يستخدم األول ‪، find_first_of‬‬
‫‪ -‬ويجب أن يستخدم الثاني ‪.find_first_not_of‬‬

‫التمرين ‪:9.48‬‬
‫‪ -‬بالنظر إلى تعريفات األسماء واألرقام في الصفحة ‪، 365‬‬
‫‪ -‬ما الذي يعيده البحث عن (االسم)؟‬

‫التمرين ‪:9.49‬‬
‫‪ -‬يكون للحرف صاعد إن كان جزء من الحرف يمتد فوق السطر ‪ ،‬كما هو حال ‪ d‬أو ‪.f‬‬
‫‪ -‬يكون للحرف سليل إن امتد جزء من الحرف أسفل السطر ‪ ،‬كما هو حال ‪ p‬أو ‪.g‬‬
‫برنامجا يقرأ مل ًفا يحتوي على كلمات ويبلغ عن أطول كلمة ال تحتوي على صاعدة وال سفلية‪.‬‬
‫ً‬ ‫‪ -‬اكتب‬

‫‪9.5.4. The compare Functions‬‬ ‫‪ 9٫5٫4‬دوال املقارنة‬

‫إضافة إلى العوامل العالئقية ‪ ،‬توفر مكتبة السلسلة مجموعة دوال مقارنة تشبه دالة مكتبة اليس ‪.strcmp‬‬
‫ومثل ‪ ، strcmp‬تعيد ‪ s.compare‬صفرًا أو قيمة موجبة أو سالبة ‪،‬‬ ‫•‬
‫اعتما ًدا على ما إن كانت ‪ s‬تساوي أو أكرب من أو أقل من السلسلة املكونة من الوسيطات املحددة‪.‬‬ ‫•‬
‫كما هو موضح في الجدول ‪ ، 9.15‬هناك ستة إصدارات للمقارنة‪.‬‬ ‫•‬
‫بناء على ما إن كنا نقارن بني سلسلتني أو سلسلة ومجموعة أحرف‪.‬‬
‫ً‬ ‫تختلف الوسيطات‬ ‫•‬
‫في كلتا الحالتني ‪ ،‬قد نقارن السلسلة بأكملها أو جزء منها‪.‬‬ ‫•‬

‫الجدول ‪ .9.15‬الوسيطات املمكنة ملقارنة ‪s.compare‬‬

‫‪s2‬‬ ‫‪Compare s to s2.‬‬


pos1, n1, s2 Compare n1 characters starting at pos1 from s to s2.

pos1, n1, s2, Compare n1 characters starting at pos1 from s to the n2


pos2, n2 characters starting at pos2 in s2.

cp Compare s to the null-terminated array pointed to by cp.

pos1, n1, cp Compare n1 characters starting at pos1 from s to cp.

pos1, n1, cp, Compare n1 characters starting at pos1 from s to n2


n2 characters starting from the pointer cp.

9.5.5. Numeric Conversions ‫ التحويالت العددية‬9٫5٫5

، ً‫ فمثال‬.‫غالبا ما تحتوي السالسل على أحرف تمثل أرقام‬


ً
."5" ‫متبوعا بالحرف‬
ً "1" ‫ الحرف‬، ‫ كسلسلة مكونة من حرفني‬15 ‫نمثل القيمة العددية‬ •
.‫ يختلف تمثيل الحرف لرقم ما عن قيمته الرقمية‬، ‫بشكل عام‬ •
، 0000000000001111 ‫ بت قصرية لها نمط البت‬16 ‫ املخزنة في‬15 ‫القيمة العددية‬ •
.0011000100110101 ‫ لها نمط البت‬1- ‫" ممثلة كحرفني التينيني‬15" ‫بينما سلسلة األحرف‬ •
، 061 ‫' الذي يحتوي على الرقم الثماني القيمة‬1' ‫البايت األول يمثل الحرف‬ •
.065 ‫ هو ثماني‬1- ‫ وهو في الالتينية‬، "5" ‫ويمثل البايت الثاني‬ •
:‫قدم املعيار الجديد العديد من الدوال اليت تحول بني البيانات الرقمية وسالسل املكتبة‬

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

‫ التحويالت بني السالسل واألرقام‬.9.16 ‫الجدول‬

Overloaded functions returning the string representation


of val.
Val can be any arithmetic type.
to_string(val);
There are versions of to_string for each floating-point
type and integral type that is int or larger.
Small integral types are promoted as usual.

Return the initial substring of s that has numeric


stoi(s,p,b) content as an int, long, unsigned long, long long,
stol(s,p,b) unsigned long long, respectively. B indicates the numeric
stoul(s,p,b) base to use for the conversion; b defaults to 10. p is a
stoll(s,p,b) pointer to a size_t in which to put the index of the
stoull(s,p,b) first non-numeric character in s; p defaults to 0, in
which case the function does not store the index.

stof(s,p) Return the initial numeric substring in s as a float,


stod(s,p) double, or long double, respectively. P has the same
‫)‪stold(s,p‬‬ ‫‪behavior as described for the integer conversions.‬‬

‫هنا نستدعي ‪ to_string‬لتحويل ‪ 42‬إلى تمثيل السلسلة املقابل لها ‪،‬‬ ‫•‬
‫ثم نستدعي ‪ stod‬لتحويل تلك السلسلة إلى العائمة العرشية‬ ‫•‬
‫يجب أن يكون أول حرف ليس مسافة بيضاء في سلسلة نحولها إلى قيمة رقمية حر ًفا قد يظهر في رقم‪:‬‬ ‫•‬

‫;"‪string s2 = "pi = 3.14‬‬


‫‪// convert first substring in s that starts with digit, d = 3.14‬‬
‫;)))"‪d = stod(s2.substr(s2.find_first_of("+-.0123456789‬‬

‫في استدعاء ‪ stod‬هذا ‪،‬‬ ‫•‬


‫جزءا من رقم‪.‬‬
‫ً‬ ‫نستدعي ‪ find_first_of‬لنصادف موضع أول حرف في ‪ s‬قد يكون‬ ‫•‬
‫بدءا من هذا املوضع للتوقف‪.‬‬
‫نمرر السلسلة الفرعية من ‪ً s‬‬ ‫•‬
‫جزءا من رقم‪.‬‬
‫ً‬ ‫تقرأ دالة ‪ stod‬السلسلة اليت تم إعطاؤها حىت تصادف حرفاً ال يمكن أن يكون‬ ‫•‬
‫ثم يقوم بتحويل تمثيل األحرف للرقم الذي وجده إلى قيمة املزدوج املقابل‪.‬‬ ‫•‬
‫رقما‪.‬‬
‫يجب أن يكون أول حرف غري املسافة بيضاء في السلسلة إما عالميت (‪ +‬أو ‪ )-‬أو ً‬ ‫•‬
‫قد تبدأ السلسلة بـ ‪ 0x‬أو ‪ 0X‬لإلشارة إلى النظام الست عرشي‪.‬‬ ‫•‬
‫أيضا بعالمة عرشية (‪).‬‬
‫بالنسبة للدوال اليت تتحول إلى فاصلة عائمة ‪ ،‬قد تبدأ السلسلة ً‬ ‫•‬
‫وقد تحتوي على ‪ e‬أو ‪ E‬لتعيني األس‪.‬‬ ‫•‬
‫بالنسبة للدوال اليت يتم تحويلها إلى نوع عدد صحيح ‪ ،‬اعتما ًدا على األساس ‪،‬‬ ‫•‬
‫قد تحتوي السلسلة على أحرف أبجدية مقابلة لألرقام اليت تتجاوز الرقم ‪.9‬‬ ‫•‬

‫ملحوظة‬

‫إن كان ال يمكن تحويل السلسلة إلى رقم ‪ ،‬فإن هذه الداالت تطرح االستثناء غري صالح للوسيطة ‪.‬‬ ‫•‬
‫إن كان التحويل يولد قيمة ال يمكن تمثيلها ‪ ،‬فسيتم رفع اﻻستثناء خارج_النطاق ‪.out_of_range‬‬ ‫•‬

‫تمارين القسم ‪9.5.5‬‬

‫التمرين ‪:9.50‬‬
‫قيما أعداد صحيحة‪.‬‬
‫برنامجا ملعالجة متجه <سلسلة> تمثل عنارصه ً‬
‫ً‬ ‫‪ -‬اكتب‬
‫‪ -‬أنتج مجموع كل العنارص في هذا املتجه‪.‬‬
‫‪ -‬قم بتغيري الربنامج بحيث يكون مجموع السالسل اليت تمثل القيم عائمة عرشية‪.‬‬

‫التمرين ‪:9.51‬‬
‫‪ -‬اكتب فئة بها ثالثة أعضاء بال_إشارة تمثل السنة والشهر واليوم‪.‬‬
‫تاريخا‪.‬‬
‫ً‬ ‫‪ -‬اكتب ُمنشئة تأخذ سلسلة تمثل‬
‫‪ -‬يجب أن تتعامل امل ُنشئة مع مجموعة متنوعة من تنسيقات التاريخ ‪،‬‬
‫‪ -‬مثل ‪ 1‬يناير ‪ 1900‬و ‪ 1/1/1900‬و ‪ 1‬يناير ‪ 1900‬وما إلى ذلك‪.‬‬
‫ مكيــــــــفات الحــــــــــاويات‬. 9٫6
9.6 Container Adaptors

.‫الحزمة والصف وأولوية_الصف‬


ُ :‫تعرف املكتبة ثالثة مكيفات متسلسلة للحاويات‬
ّ ، ‫إضافة إلى الحاويات املتسلسلة‬
.‫ ومكيفات دوال‬، ‫ مكرر‬، ‫ فهناك حاويات‬.‫• املكيف مفهوم عام في املكتبة‬
.‫ يعد املكيف آلية لجعل يشء ما يترصف كيشء آخر‬، ‫في األساس‬ •
.‫يأخذ مكيف الحاوية نوع حاوية موجود ويجعله يعمل كنوع مختلف‬ •
.‫حزمة‬
ُ ‫الحزمة حاوية متسلسلة (عدا املصفوفة والقائمة_اﻷمامية) ويجعلها تعمل كأنها‬
ُ ‫ يأخذ مكيف‬، ‫مثال‬ •
.‫ العمليات واألنواع املشرتكة لجميع مكيفات الحاوية‬9.17 ‫يرسد الجدول‬ •

‫ العمليات واألنواع املشرتكة ملكيفات الحاوية‬.9.17 ‫الجدول‬

Type large enough to hold the size of the largest object


size_type
of this type.

value_type Element type.

Type of the underlying container on which the adaptor is


container_type
implemented.

A a; Create new empty adaptor named a.

A a(c); Create new adaptor named a with copy of container c.

Each adaptor supports all the relational operations:


relational ==, !=, <, <=, >, >=.
operators These operators return the result of comparing the
underlying containers.

a.empty() False if a has any elements, true otherwise.

a.size() Number of elements in a.

swap(a,b) Swaps contents of a and b; a and b must have same type,


a.swap(b) including type of container on which they are implemented.

Defining an Adaptor ‫تعريف مكيف‬

، ‫فارغا‬
ً ‫ املُنشئة االفرتاضية اليت تنئش كائنًا‬:‫يعرف كل مكيف ُمنشئتني‬
ّ
.‫• واملنشئة اليت تأخذ حاوية ويهئي املكيف عن طريق نسخ الحاوية املحددة‬
:‫حزمة جديدة على النحو التالي‬
ُ ‫ لتهيئة‬deq ‫ يمكننا استخدام‬، >int< ‫ هو طابور‬deq ‫ بافرتاض أن‬، ً‫فمثال‬ •

stack<int> stk(deq);  // copies elements from deq into stk


‫الحزمة والصف عن طريق طابور ؛ بينما تُنفذ أولوية_الصف عن طريق متجه‪.‬‬
‫افرتاضياً يتم تنفيذ كل من ُ‬ ‫•‬
‫يمكننا تجاوز نوع الحاوية االفرتايض باستدعاء حاوية متسلسلة كوسيطة نوع ثان عند إنشاء مكيف‪:‬‬ ‫•‬

‫‪// empty stack implemented on top of vector‬‬


‫;‪stack<string, vector<string>> str_stk‬‬
‫‪// str_stk2 implemented on top of vector and initially holds copy of svec‬‬
‫;)‪stack<string, vector<string>> str_stk2(svec‬‬

‫هناك قيود على الحاويات اليت يمكن استخدامها ملكيف معني‪.‬‬


‫تتطلب جميع املكيفات القدرة على إضافة العنارص وإزالتها‪.‬‬ ‫•‬
‫نتيجة لذلك ‪ ،‬ال يمكن إنشاؤها على مصفوفة‪.‬‬ ‫•‬
‫وباملثل ‪ ،‬ال يمكننا استخدام القائمة_اﻷمامية ‪ ،‬ألن جميع املكيفات تتطلب عمليات تضيف أو تزيل أو تصل‬ ‫•‬
‫إلى آخر عنرص في الحاوية‪.‬‬
‫الحزم فقط عمليات دفع_للخف و طرد_خلف و خلف_ ‪،‬‬ ‫تتطلب ُ‬ ‫•‬
‫للحزمة‪.‬‬
‫ولذلك يمكننا استخدام أي من أنواع الحاويات املتبقية ُ‬ ‫•‬
‫يتطلب مكيف الصف خلف_ ‪ ،‬ودفع_للخلف ‪ ،‬ومقدمة_ ‪ ،‬ودفع_للمقدمة ‪،‬‬ ‫•‬
‫بحيث يمكن بناؤه على قائمة أو طابور ولكن ليس على متجه‪.‬‬ ‫•‬
‫تتطلب خاصية أولوية_الصف وصوال ً عشوائياً إضافة إلى عمليات مقدمة_ ودفع_للخلف وطرد_خلف ؛‬ ‫•‬
‫ولذلك يمكن بناؤها على متجه أو طابور لكن ليس على قائمة‪.‬‬ ‫•‬

‫‪Stack Adaptor‬‬ ‫الحزمة‬


‫مكيف ُ‬

‫الحزمة‪.‬‬
‫الحزمة في عنوان ُ‬
‫يتم تعريف نوع ُ‬
‫الحزم‪:‬‬
‫الحزم في الجدول ‪ .9.18‬يوضح الربنامج التالي استخدام ُ‬
‫يتم رسد العمليات اليت يوفرها ُ‬

‫‪stack<int> intStack;  // empty stack‬‬


‫‪// fill up the stack‬‬
‫)‪for (size_t ix = 0; ix != 10; ++ix‬‬
‫‪    intStack.push(ix);   // intStack holds 0 ... 9 inclusive‬‬
‫‪while (!intStack.empty()) {    // while there are still values in intStack‬‬
‫;)(‪    int value = intStack.top‬‬
‫‪    // code that uses value‬‬
‫‪    intStack.pop(); // pop the top element, and repeat‬‬
‫}‬

‫الجدول ‪ .9.18‬عمليات الحزمة باإلضافة إلى تلك الواردة في الجدول ‪9.17‬‬


‫يستخدم مع الطابور افرتاضياً ويمكن تنفيذه كذلك على القائمة أو املتجه‬

‫‪Removes but does not returns, the top elements from the‬‬
‫)(‪s.pop‬‬
‫‪stack.‬‬

‫)‪s.push(item‬‬ ‫‪Create a new top elements on the stack by copying or‬‬


‫‪s.emplace(args) moving item or by constructing elements from args.‬‬

‫‪Returns but does not remove, the top elements on the‬‬


‫)(‪s.top‬‬
‫‪stack.‬‬

‫فاإلعالن‪. . .‬‬

‫‪stack<int> intStack;  // empty stack‬‬

‫حزمة فارغة تحتوي على عنارص عدد صحيح‪.‬‬ ‫يعرف ‪ intStack‬على أنه ُ‬
‫ّ‬ ‫•‬
‫بدءا من الصفر‪.‬‬
‫تضيف حلقة ‪ for‬عرشة عنارص ‪ ،‬وتبدأ كل منها في العدد الصحيح التالي بالتسلسل ً‬ ‫•‬
‫الحزمة‬
‫الحزمة حىت تصبح ُ‬
‫الحزمة بأكملها ‪ ،‬وتفحص القيمة األعلى وتطردها من ُ‬
‫تتكرر حلقة ‪ while‬خالل ُ‬ ‫•‬
‫فارغة‪.‬‬
‫يعر ف كل مكيف حاوية عملياته الخاصة من حيث العمليات اليت يوفرها نوع الحاوية األسايس‪.‬‬
‫ّ‬ ‫•‬
‫يمكننا استخدام عمليات املكيف فقط وال يمكننا استخدام عمليات نوع الحاوية األساسية‪ .‬مثالً ‪،‬‬ ‫•‬

‫‪intStack.push(ix);   // intStack holds 0 ... 9 inclusive‬‬

‫يستدعي دفع_للخلف على كائن طابور الذي يعتمد عليه ‪.intStack‬‬ ‫•‬
‫الحزمة تُنفذ باستخدام طابور ‪ ،‬إال أنه ليس لدينا وصول مبارش إلى عمليات الطابور‪.‬‬
‫بالرغم من أن ُ‬ ‫•‬
‫الحزمة املسماة دفع_ ‪.push‬‬
‫حزمة ؛ بل ‪ ،‬يجب أن نستخدم عملية ُ‬ ‫فال يمكننا استدعاء دفع_للخلف على ُ‬ ‫•‬

‫‪The Queue Adaptors‬‬ ‫مكيفات الصف‬

‫يتم تعريف مكيفات الصف و أولوية_الصف في عنوان الصف‪.‬‬


‫يرسد الجدول ‪ 9.19‬العمليات اليت تدعمها هذه األنواع‪.‬‬

‫الجدول ‪ .9.19‬عمليات الصف وأولوية_الصف باإلضافة إلى الجدول ‪9.17‬‬

‫يستخدم مكيف الصف الطابور افرتاضياً ‪ ،‬ويمكنه استخدام املتجه أو القائمة كذلك‪.‬‬ ‫•‬

‫يستخدم مكيف أولوية_الصف املتجه افرتاضياً ‪ ،‬ويمكنه استخدام الطابور كذلك‪.‬‬ ‫•‬
‫‪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.‬‬

‫‪Returns but does not remove, the highest-priority‬‬


‫)(‪q.top‬‬
‫‪elements. Valid only for priority_queue.‬‬

‫‪Create an elements with value item or constructed from arg‬‬


‫)‪q.push(item‬‬
‫‪at the end of queue or in its appropriate position in‬‬
‫)‪q.emplace(arg‬‬
‫‪priority_queue.‬‬

‫تستخدم مكتبة الصف سياسة فيفو ‪ :‬ما يدخل أوال ً يخرج أوال ً (‪.)FIFO : FirstInFirstOut‬‬
‫• حيث يتم وضع الكائنات اليت تدخل الصف في الخلف وتتم إزالة الكائنات اليت تغادره من املقدمة‪.‬‬
‫يعد املطعم الذي يُجلس األشخاص برتتيب وصولهم مثاال ً على صف فيفو ‪.FIFO‬‬ ‫•‬
‫تتيح لنا خاصية أولوية_الصف تحديد أولوية بني العنارص املوجودة في الصف‪.‬‬ ‫•‬
‫حيث توضع العنارص املضافة حديثًا في مقدمة كل العنارص ذات األولوية األقل‪.‬‬ ‫•‬
‫فاملطعم الذي يُجلس األشخاص وف ًقا لوقت حجزهم بغض النظر عن وقت وصولهم ‪ ،‬مثال ألولوية_الصف‪.‬‬ ‫•‬
‫افرتاضياً ‪ ،‬تستخدم املكتبة عامل نوع العنرص > لتحديد األولويات النسبية‪.‬‬ ‫•‬
‫سنتعلم كيفية تجاوز هذا اإلعداد االفرتايض في الفقرة ‪.11.2.2‬‬ ‫•‬

‫تمارين القسم ‪9.6‬‬

‫التمرين ‪:9.52‬‬
‫حزمة ملعالجة التعبريات ذات األقواس‪.‬‬
‫‪ -‬استخدم ُ‬
‫مفتوحا ‪ ،‬الحظ أنه تم رؤيته‪.‬‬
‫ً‬ ‫قوسا‬
‫ً‬ ‫‪ -‬عندما ترى‬
‫قوسا مغل ًقا بعد قوس مفتوح ‪،‬‬
‫ً‬ ‫‪ -‬عندما ترى‬
‫الحزمة‪.‬‬
‫‪ -‬اطرد العنارص ألسفل وقم بتضمني قوس الفتح خارج ُ‬
‫الحزمة لإلشارة إلى أنه تم استبدال تعبري بني قوسني‪.‬‬
‫‪ -‬قم بدفع قيمة إلى ُ‬
‫ملخــــــــــص الفصــــــــــل‬
‫‪Chapter Summary‬‬

‫حاويات املكتبة هي أنواع قوالب تحتوي على كائنات من نوع معني‪.‬‬


‫في حاوية متسلسلة ‪ ،‬يتم ترتيب العنارص والوصول إليها حسب املوضع‪.‬‬ ‫•‬
‫تتشارك الحاويات املتسلسلة في واجهة مشرتكة موحدة‪:‬‬ ‫•‬
‫إن كانت هناك حاويتان متتاليتان تقدمان عملية معينة ‪،‬‬ ‫•‬
‫فإن العملية لها نفس الواجهة واملعىن لكلتا الحاويتني‪.‬‬ ‫•‬

‫توفر جميع الحاويات (باستثناء املصفوفة) إدارة فعالة للذاكرة الحيوية‪.‬‬

‫قد نضيف عنارص إلى الحاوية دون القلق بشأن مكان تخزين العنارص‪.‬‬
‫الحاوية نفسها تدير تخزينها‪.‬‬ ‫•‬
‫تحكما أكرث تفصيالً في إدارة الذاكرة من خالل أعضاء الحجز والسعة‪.‬‬
‫ً‬ ‫يوفر كل من املتجه والسلسلة‬ ‫•‬

‫تعرف الحاويات عمليات قليلة بشكل مدهش‪.‬‬


‫بالنسبة للجزء األكرب ‪ّ ،‬‬
‫تعرف الحاويات املُنشئات ‪ ،‬وعمليات إضافة العنارص أو إزالتها ‪،‬‬
‫ّ‬ ‫•‬
‫وعمليات لتحديد حجم الحاوية ‪ ،‬وعمليات إلعادة املكررات إلى عنارص معينة‪.‬‬ ‫•‬
‫العمليات املفيدة األخرى ‪ ،‬مثل الفرز أو البحث ‪ ،‬ال يتم تعريفها بواسطة أنواع الحاويات ؛‬ ‫•‬
‫لكن بواسطة الخوارزميات القياسية ‪ ،‬واليت سنغطيها في الفصل ‪.10‬‬ ‫•‬

‫عندما نستخدم عمليات حاوية تضيف عنارص أو تزيلها ‪،‬‬


‫فمن الرضوري أن نتذكر أن هذه العمليات قد تبطل املكررات أو املؤرشات أو مراجع لعنارص في الحاوية‪.‬‬ ‫•‬
‫مكررا ‪ ،‬مثل اإلدراج أو املسح ‪ ،‬إلى إعادة مكرر جديد يسمح للربنامج بالحفاظ‬
‫ً‬ ‫تؤدي عدة عمليات تبطل‬ ‫•‬
‫على موضع داخل الحاوية‪.‬‬
‫يجب أن تكون الحلقات اليت تستخدم عمليات حاوية تغري حجمها حذرة بشكل خاص في استخدامها‬ ‫•‬
‫للمكررات واملؤرشات واملراجع‪.‬‬
‫مصطلحــــــــــات معــــــــــرفة‬
‫‪Defined Terms‬‬

‫مكيف ‪:‬‬
‫نوع مكتبة أو دالة أو مكرر يجعله يترصف كنوع آخر ‪ ،‬كنظري لنوعه أو‬
‫‪adaptor‬‬ ‫دالته أو مكرره‪.‬‬
‫الحزمة والصف وأولوية_الصف‪.‬‬‫ُ‬ ‫للحاويات‪:‬‬ ‫متسلسلة‬ ‫مكيفات‬ ‫هناك ثالثة‬
‫يعرف كل مكيف واجهة جديدة أعلى نوع الحاوية املتسلسل األسايس‪.‬‬‫ّ‬

‫مصفوفة ‪:‬‬
‫مصفوفة املكتبة هي حاوية متسلسلة ثابتة الحجم‪.‬‬
‫‪array‬‬ ‫لتعريف مصفوفة ‪ ،‬يجب أن نعطي الحجم إضافة إلى تحديد نوع العنرص‪.‬‬
‫يمكن الوصول إلى العنارص في املصفوفة من خالل فهرسها املوضعي‪.‬‬
‫يدعم الوصول العشوائي الرسيع إلى العنارص‪.‬‬

‫بداية_‪:‬‬
‫مكررا يشري ألول عنرص في الحاوية – إن وجد –‪،‬‬
‫ً‬ ‫عملية حاوية تعيد‬
‫‪begin‬‬
‫أو مكرر مابعد_نهاية إن كانت الحاوية فارغة‪.‬‬
‫يعتمد ما إن كان املكرر املعاد ثابتاً على نوع الحاوية‪.‬‬

‫بداية_ثابتة ‪:‬‬
‫‪cbegin‬‬ ‫عملية حاوية تعيد مكرراً ثابتاً يشري ألول عنرص في الحاوية ‪ ،‬إن وجد ‪،‬‬
‫أو يعيد مكرر مابعد_نهاية إن كانت الحاوية فارغة‪.‬‬

‫نهاية_ثابتة ‪:‬‬
‫‪cend‬‬ ‫عملية حاوية تعيد مكرراً ثابتاً يشري لعنرص (غري موجود) بعد نهاية‬
‫الحاوية‪.‬‬

‫حاوية ‪:‬‬
‫نوع يحتوي على مجموعة كائنات من نوع معني‪ .‬فكل نوع حاوية مكتبة‬
‫‪container‬‬ ‫عبارة عن قالب‪.‬‬
‫لتعريف حاوية ‪ ،‬يجب علينا تحديد نوع العنارص املخزنة في تلك الحاوية‪.‬‬
‫باستثناء املصفوفة ‪ ،‬تكون حاويات املكتبة متغرية الحجم‪.‬‬
‫طابور‪:‬‬
‫حاوية متسلسلة‪ .‬يمكن الوصول إلى عنارصها من خالل مؤرش موضع ‪،‬‬
‫كما يدعم الوصول العشوائي الرسيع إلى تلك العنارص‪.‬‬
‫‪deque‬‬
‫يشبه املتجه من جميع النواحي إﻻ أنه يدعم اإلدراج الرسيع والحذف من‬
‫مقدمة وآخر الحاوية وال ينقل عنارصه نتيجة لعمليات اإلدراج أو الحذف‬
‫في أي من الطرفني‪.‬‬

‫نهاية_‪:‬‬
‫‪end‬‬ ‫مكررا يشري إلى عنرص (غري موجود) بعد نهاية الحاوية‪.‬‬ ‫عملية حاوية تعيد‬
‫ً‬
‫يعتمد ما إن كان املكرر املعاد ثاب ًتا على نوع الحاوية‪.‬‬

‫قائمة_أمامية ‪:‬‬
‫حاوية متسلسلة تمثل قائمة ترتابط بشكل منفرد وحر‪.‬‬
‫بدءا من عنرص‬
‫يمكن الوصول إلى عنارص القائمة_اﻷمامية بالتسلسل فقط ؛ ً‬
‫معني ‪،‬‬
‫وال يمكن الوصول إلى عنرص آخر إال من خالل اجتياز كل عنرص بينهما‪.‬‬
‫املكررات في القائمة_اﻷمامية ال تدعم التناقص (‪.)-‬‬
‫‪forward_list‬‬ ‫تدعم القائمة_اﻷمامية اإلدراج الرسيع (أو الحذف) في أي مكان فيها‪.‬‬
‫وعلى عكس الحاويات األخرى ‪ ،‬تحدث عمليات اإلدراج والحذف بعد موضع‬
‫مكرر معني‪.‬‬
‫نتيجة لذلك ‪ ،‬تحتوي القائمة_اﻷمامية على مكرر "قبل_بداية" ليتماىش مع‬
‫املكرر العادي‪.‬‬
‫مكررات القائمة_اﻷمامية تبقى صالحة عند إضافة عنارص جديدة‪.‬‬
‫وعند إزالة عنرص ‪ ،‬يتم إبطال مكرر ذلك العنرص فقط‪.‬‬

‫نطاق املكرر‪:‬‬
‫مجموعة عنارص يُشار إليها بزوج من املكررات‪.‬‬
‫يشري املكرر األول إلى أول عنرص في التسلسل ‪ ،‬ويشري الثاني إلى ما بعد‬
‫آخر عنرص فيه‪.‬‬
‫فارغا ‪ ،‬فسيكون املكرران متساويان ؛‬
‫ً‬ ‫إن كان النطاق‬
‫‪iterator range‬‬
‫(والعكس صحيح ‪ -‬فإن كان املكرران غري متساويان ‪ ،‬فإنهما يشريان إلى‬
‫نطاق غري فارغ)‪.‬‬
‫فارغا ‪ ،‬فيجب أن يكون من املمكن الوصول إلى املكرر‬
‫ً‬ ‫إن لم يكن النطاق‬
‫الثاني عن طريق مزايدة املكرر األول بشكل متكرر‪.‬‬
‫ومن خالل زيادة املكرر ‪ ،‬سنتمكن من معالجة كل عنرص في التسلسل‪.‬‬

‫الفاصل الشامل لليسار‪:‬‬


‫نطاق من القيم يتضمن عنرصه األول ولكن ليس العنرص األخري‪.‬‬
‫‪left-inclusive interval‬‬
‫يُشار إليها عاد ًة بالرمز [‪، )i ، j‬‬
‫ما يعين أن التسلسل الذي يبدأ من ويتضمن ‪ i‬حىت ‪ j‬لكن سيتم استثناء ‪.j‬‬
‫قائمة ‪:‬‬
‫حاوية متسلسلة تمثل قائمة مرتبطة بشكل مزدوج‪.‬‬
‫بدءا من عنرص معني ‪،‬‬
‫ويمكن الوصول إلى عنارصها بالتسلسل فقط ؛ ً‬
‫وال يمكن الوصول إلى عنرص آخر إال من خالل اجتياز كل عنرص بينهما‪.‬‬
‫‪list‬‬
‫يدعم املكررات في القائمة كال من الزتايد (‪ )++‬والتناقص (‪.)-‬‬
‫كما يدعم اإلدراج الرسيع (أو الحذف) في أي مكان في القائمة‪.‬‬
‫وتظل مكرراتها صالحة عند إضافة عنارص جديدة‪ .‬وعند إزالة عنرص ‪ ،‬يتم‬
‫إبطال املكرر ذلك العنرص فقط‪.‬‬

‫مكرر_قبل_البداية ‪:‬‬
‫مكرر يشري إلى عنرص (غري موجود) قبل بداية القائمة_اﻷمامية‪.‬‬
‫‪off-the-beginning iterator‬‬
‫يعود من عضو القائمة_اﻷمامية ‪.before_begin‬‬
‫مثل مكرر نهاية_ ‪ ،‬ال يسمح بإلغاء املرجع عنه‪.‬‬

‫مكرر مابعد_نهاية ‪:‬‬


‫‪off-the-end iterator‬‬ ‫مكرر يشري إلى ما بعد آخر عنرص في النطاق‪.‬‬
‫يشار إليه عادة باسم "مكرر النهاية"‪.‬‬

‫أولوية_الصف ‪:‬‬
‫مكيف للحاويات املتسلسلة ينتج عنه صف يتم فيها إدراج العنارص ‪،‬‬
‫‪priority_queue‬‬
‫ليس في نهايته ولكن وف ًقا ملستوى أولوية محدد‪.‬‬
‫افرتاضياً ‪ ،‬يتم تحديد تلك األولوية باستخدام عامل نوع العنرص أقل من‪.‬‬

‫صف ‪:‬‬
‫‪queue‬‬ ‫نوعا يتيح لنا إضافة عنارص إلى الخلف‬
‫ً‬ ‫ينتج‬ ‫املتسلسلة‬ ‫للحاويات‬ ‫مكيف‬
‫وإزالتها من املقدمة‪.‬‬

‫حاوية متسلسلة‪:‬‬
‫‪sequential container‬‬ ‫نوع يحتوي على مجموعة مرتبة من الكائنات من نوع واحد‪.‬‬
‫يتم الوصول إلى العنارص في الحاوية املتسلسلة حسب املوضع‪.‬‬

‫حزمة ‪:‬‬
‫ُ‬
‫‪stack‬‬ ‫نوعا يتيح لنا إضافة وإزالة العنارص من‬
‫ً‬ ‫ينتج‬ ‫املتسلسلة‬ ‫للحاويات‬ ‫مكيف‬
‫طرف واحد فقط‪.‬‬
‫متجه ‪:‬‬
‫حاوية متسلسلة‪ .‬يمكن الوصول إلى عنارصه من خالل فهرسها املوضعي‪.‬‬
‫يدعم الوصول العشوائي الرسيع إلى العنارص‪.‬‬
‫يمكننا إضافة عنارص متجه أو إزالتها بكفاءة فقط من الخلف‪.‬‬
‫‪vector‬‬
‫قد تؤدي إضافة عنارص إلى متجه إلى إعادة تخصيصه ‪ ،‬وهو ما يؤدي إلى‬
‫إبطال كل مكرراته‪.‬‬
‫تؤدي إضافة (أو إزالة) عنرص في منتصف املتجه إلى إبطال كل مكررات‬
‫عنارصه بعد نقطة اإلدراج (أو الحذف)‪.‬‬

You might also like