Professional Documents
Culture Documents
10الخــــــــــوارزميــــــــــات الـشــــــــــاملــــــة
Chapter 10. Generic Algorithms
الـمحتويات
Contents
تعرف حاويات املكتبة مجموعة صغرية من العمليات بشكل مدهش .فبدال ً من إضافة عدة دوال لكل حاوية ،
ّ
توفر املكتبة مجموعة خوارزميات ،معظمها مستقلة عن أي نوع حاوية معني. •
هذه خوارزميات تعترب شاملة :حيث تعمل على أنواع مختلفة من الحاويات وعنارص من أنواع مختلفة. •
يتكون موضوع هذا الفصل من الخوارزميات الشاملة ومراجعة بتفصيل أكرث على املكررات.
يمكننا تخيل عدة عمليات مفيدة أخرى قد يرغب املرء في القيام بها :
قد نرغب في إيجاد عنرص معني ،أو استبدال أو إزالة قيمة معينة ، •
أو إعادة ترتيب عنارص حاوية ،وما إلى ذلك. •
أول وثاني وسيطات findهما مكرران يدالن على نطاق عنارص ،الثالثة عبارة قيمة. •
يقارن findكل عنرص في النطاق املحدد بالقيمة املحددة. •
يقوم بإعادة مكرر ألول عنرص يساوي تلك القيمة. •
إذا لم يكن هناك تطابق ،فسيعيد findمكرره الثاني ليشري إلى الفشل. •
وبالتالي ،يمكننا تحديد ما إذا كان قد تم اإليجاد العنرص من خالل مقارنة القيمة املعادة باملكرر الثاني. •
نقوم بإجراء هذا االختبار في جملة املخرجات ، •
واليت تستخدم العامل الرشطي إلظهار ما إذا تم إيجاد القيمة. •
ونظرًا ألن findتعمل بمنهجية املكررات ،فيمكننا استخدام نفس الدالة findللبحث عن قيم أي نوع حاوية.
• فعلى سبيل املثال ،يمكننا استخدام findللبحث عن قيمة في قائمة سالسل : list of strings
بنفس الكيفية ،وألن املؤرشات تعمل كاملكررات في املصفوفات املدمجة ،يمكننا استخدام findللبحث في مصفوفة:
]// search elements begining from ia[1] up to but not including ia[4
;)auto result = find(ia + 1, ia + 4, val
ملعرفة كيف يمكن استخدام الخوارزميات في أنواع حاويات مختلفة ،دعنا نلقي نظرة عن كثب على .find
تتمثل مهمة findفي إيجاد عنرص معني في تسلسل عنارص غري مفرزة. •
من الناحية املفاهيمية ،يمكننا رسد خطوات findاليت يجب أن يتخذها : •
.1ينفذ إلى أول عنرص في التسلسل.
.2فيقارن ذلك العنرص بالقيمة اليت نريدها.
تعرف ذلك العنرص.
.3إذا تطابق العنرص مع ما نريده ،يعيد findقيمة ّ
.4وإال ،فيتقدم findنحو العنرص التالي ويكرر الخطوتني الثانية والثالثة.
.5يجب أن يتوقف findعند وصوله إلى نهاية التسلسل.
.6إذا صادف findنهاية التسلسل ،فسيحتاج إلعادة قيمة تشري إلى أن العنرص لم يتم العثور عليه.
-يجب أن يكون لهذه القيمة والقيمة املعادة من الخطوة الثالثة أنواع متوافقة.
ال تعتمد أي من هذه العمليات على نوع الحاوية اليت تحمل العنارص.
فطاملا أنه يوجد مكرر يمكن استخدامه للوصول إلى العنارص ، •
فال يعتمد findبأي شكل على نوع الحاوية (أو حىت ما إذا كانت العنارص مخزنة في حاوية). •
يمكن معالجة كل الخطوات باستثناء الخطوة الثانية في دالة findعن طريق عمليات املكرر :
حيث يتيح عامل إلغاء مرجع املكرر الوصول إلى قيمة العنرص ؛ •
إذا تم إيجاد عنرص مطابق ،فيمكن لـ findأن يعيد مكرراً لهذا العنرص ؛ •
ويتحرك عامل تزايد املكرر نحو العنرص التالي ؛ •
سيشري مكرر "ما-بعد-النهاية" مىت صادف findنهاية تسلسله املحدد ؛ •
ويتمكن findمن إعادة مكرر ما-بعد النهاية ليشري إلى أنه لم يتم إيجاد القيمة املحددة. •
التمرين :10.1
زوجا من املكررات وقيمة مثل .find
ً عد_ countتأخذ
يعرف عنوان الخوارزمية دالة تسمى ّ
ّ -
-يقوم countبإعادة عدد مرات ظهور هذه القيمة.
-قم بقراءة تسلسل أرقام صحيحة في متجه
-واطبع عدد العنارص اليت لها قيمة محددة.
التمرين :10.2
كرر الربنامج السابق ،لكن اقرأ القيم في قائمة سالسل .list of strings
أبدا
الخوارزميات ال تنفذ عمليات حاوية ً مفهوم أسايس:
ال تنفذ الخوارزميات الشاملة عمليات حاوية بنفسها .ﻻ تحدث العمليات إﻻ بمنهجية املكرر وعملياته. •
تعمل الخوارزميات بمنهجية املكررات وليس بعمليات الحاوية ؛ •
حقيقة ذلك قد يكون له تأثري مدهش لكنه أسايس ومفصلي : •
ﻻ تغري الخوارزميات أب ًدا حجم الحاوية األساسية. •
قد تغري الخوارزميات قيم العنارص املخزنة في الحاوية ،وقد تنقل عنارص داخل الحاوية. •
مع ذلك ،فلن تضيف أو تزيل عنارص مبارشة. •
توفر املكتبة أكرث من 100خوارزمية .لحسن الحظ ،هي مشابهة للحاويات ،حيث تتمتع بنية متسقة.
ففهم هذه البنية يجعل تعلم واستخدام الخوارزميات أسهل من حفظ ما يزيد على 100منها. •
في هذا الفصل ،سوف نوضح كيفية استخدام الخوارزميات ،وسنوصف املبادئ املوحدة اليت تمزيها. •
يرسد امللحق أ جميع الخوارزميات املصنفة حسب كيفية عملها. •
وعلى الرغم من أن معظم الخوارزميات متشابهة كونها تعمل عرب نطاق مدخالت ،
إال أنها تختلف في كيفية استخدام العنارص في ذلك النطاق. •
الطريقة األساسية لفهم الخوارزميات هي معرفة ما إذا كانت تقرأ عنارص أو تكتبها أو تُعيد ترتيبها. •
تقوم عدة خوارزميات بقراءة العنارص في نطاق مدخالتها ،لكنها ال تكتب عليها مطل ًقا.
عد_ countاملستخدمة في التمرين السابق.
الدالة إيجاد_ findإحدى تلك الخوارزميات ،ومثلها دالة ّ •
املعرفة في العنوان العددي .numeric
ّ خوارزمية أخرى للقراءة فقط هي تجميع_ ، accumulate •
تأخذ تجميع_ ثالث وسيطات. •
تحدد األوليان نطاق العنارص املراد جمعها .والثالثة عبارة عن قيمة ابتدائية للمجموع. •
فبافرتاض أن vecعبارة عن سلسلة من األعداد الصحيحة ،فإن التالي : •
ملحوظة
نوع وسيطة تجميع_ الثالثة يحدد أي عامل جمع يستخدم ؛ وهو النوع الذي يقوم تجميع_ بإعادته.
حقيقة أن تجميع_ يستخدم وسيطته الثالثة كقيمة ابتدائية للمجموع لها تأثري مهم :
يجب أن يكون من املمكن جمع نوع العنرص مع نوع املجموع. •
بمعىن أن العنارص في التسلسل يجب أن تتطابق أو تكون قابلة للتحويل إلى نوع الوسيطة الثالثة. •
في هذا املثال ،قد تكون العنارص في vecعدداً صحيحاً ،أو مزدوجاً أو طويالً_أطول ، long long •
أو أي نوع آخر يمكن جمعه مع عدد صحيح. •
مثال آخر ،ألن السلسلة تملك العامل ، + •
فيمكننا ربط عنارص متجه من سالسل عن طريق استدعاء تجميع_ : •
يربط هذا االستدعاء كل عنرص في vبسلسلة تهئي على سلسلة فارغة. •
الحظ أننا ننئش سلسلة رصاحة كمعامل ثالث. •
ذلك ألن تمرير السلسلة الفارغة كحرفية سلسلة خطأ في وقت الرتجمة : •
فإذا مررنا حرفية سلسلة ،سيكون نوع الكائن املستخدم لحفظ املجموع هو مؤرش لحرف ثابت*. •
وبما أن هذا النوع يحدد أي عامل جمع سنستخدمه. •
ونظر ًا لعدم وجود عامل +لنوع مؤرش الحرف الثابت ،فلن يتم ترجمة هذا االستدعاء. •
أفضل املمارسات
من األفضل عاد ًة استخدام cbeginو cendمع خوارزميات تقرأ عنارص وال تكتبها. •
لكن ،إن خططت الستخدام مكرر معاد بخوارزمية تغرّي قيمة عنرص ،ستحتاج لتمرير beginو . end •
خوارزمية أخرى للقراءة فقط هي تساوي_ ، equalواليت تتيح لنا تحديد ما إذا تسلسالن يحمالن نفس القيم.
تقارن تساوي_ كل عنرص من أول تسلسل بعنرصه املقابل في الثاني. •
وتُعيد قيمة صحيحة trueإن كانت العنارص املتقابلة متساوية ،وإال تعيد قيمة خطأ .false •
تأخذ الخوارزمية تساوي_ ثالثة مكررات :أولهما (كالعادة) يشريان لنطاق العنارص في أول تسلسل ؛ •
بينما يشري الثالث إلى أول عنرص في التسلسل الثاني : •
وألن تساوي_ تعمل بنهج املكررات ،فيمكننا استدعاءها ملقارنة عنارص في حاويات مختلفة األنواع . •
أيضا أن تكون أنواع العنارص واحدة طاملا نستخدم == ملقارنة تلك األنواع.
عالوة على ذلك ،ال حاجة ً •
متجها من سلسلة وتكون roster2قائمة من مؤرش لحرف ثابت .
ً • فمثالً ،يمكن أن تكون roster1
مهما للغاية:
افرتاضا ً
ً مع ذلك ،تضع تساوي_ تضع
فهي تفرتض أن حجم التسلسل الثاني على األقل بمقدار حجم أول تسلسل. •
فمن املحتمل أن تبحث هذه الخوارزمية في كامل عنارص أول تسلسل. •
حيث تفرتض أن هناك عنرصًا مطاب ًقا لكل عنرص منها في التسلسل الثاني املقابل. •
تحذير
مكررا وحي ًدا تدل على تسلسل ثانٍ أن حجم الثاني على األقل سيكون بحجم األول.
ً تفرتض خوارزميات تأخذ
التمرين :10.3
استخدم "تجميع_ "accumulateلجمع العنارص في متجه عدد صحيح <.vector<int
التمرين :10.4
بافرتاض أن vمتجه < ، >doubleفما الخطأ ،إن ُوجد ،في استدعاء تجميع_ كالتالي :
?)accumulate(v.cbegin(), v.cend(), 0
التمرين :10.5
-في استدعاء تساوي_ على قوائم ، rosters
-ماذا سيحدث إذا حملت كلتا القائمتني سالسل من النمط ، Cبدال ً من سالسل املكتبة؟
عالوة على ذلك ،لن يتطلب التطابق التام في أنواع العنارص في تسلسلني. •
إنما املطلوب هو أن نكون قادرين على مقارنة عنارص من كال التسلسلني. •
فمثالً ،في خوارزمية تساوي_ ،ال حاجة لتماثل أنواع العنارص ، •
لكن يجب أن نكون قادرين فعالً على استخدام == ملقارنة عنارص من كال التسلسلني. •
تختلف الخوارزميات اليت تعمل على تسلسلني حول كيفية تمرير التسلسل الثاني. •
تأخذ بعضها -مثل تساوي_ -ثالثة مكررات : •
تشري األوليان إلى نطاق عنارص أول تسلسل ،ويشري الثالث إلى أول عنرص في التسلسل الثاني. •
تأخذ خوارزميات أخرى أربعة مكررات: •
تشري األوليان إلى نطاق عنارص أول تسلسل ،وتشري األخريان إلى نطاق عنارص التسلسل الثاني. •
تفرتض خوارزميات تشري بمكرر واحد إلى التسلسل الثاني أن يكون حجمه على األقل بحجم األول. •
األمر مرتوك لنا لنتأكد أن الخوارزمية لن تحاول الوصول إلى عنرص غري موجود في التسلسل الثاني. •
مثالً ،يحتمل أن تقارن خوارزمية تساوي_ كل عنرص من تسلسله األول مع عنرص في الثاني. •
فإذا كان التسلسل الثاني مجموعة فرعية من األول ،فهذا يعين أن لدى برنامجنا خطأ فادحاً - •
حيث سيحاول تساوي_ الوصول إلى عنارص تتجاوز نهاية التسلسل الثاني. •
Algorithms Do Not Check Write Operations ال تفحص الخوارزميات عمليات الكتابة
تحذير
تفرتض خوارزميات تكتب على مكرر وجهة أن حجم الوجهة كبري بما يكفي الحتواء عدد العنارص اليت ستكتب.
هناك طريقة واحدة للتأكد من أن خوارزمية ما لديها عنارص كافية لتحمل املخرجات :
استخدام مكرر إدراج .insert iterator •
مكرر اإلدراج عبارة عن مكرر يضيف عنارص إلى حاوية. •
وعادة ،عندما نقوم بتعيني على عنرص حاوية من خالل مكرر ،فإننا نعني على عنرص يشري إليه املكرر. •
لكن عندما نقوم بتعيني من خالل مكرر إدراج ، •
فإنه يتم إضافة عنرص جديد إلى الحاوية مساوي لقيمة الجهة اليمىن. •
سيكون لدينا املزيد عن مكررات اإلدراج في فقرة . 10.4.1
بكل حال ،من أجل توضيح كيفية استخدام خوارزميات تكتب على حاوية ، •
معرفة في عنوان املكرر . iterator
الـمد ِرج_الخلفي ، back_inserterوهي دالة ّ
سنستخدم ُ •
مرتبطا بتلك الحاوية.
ً مرجعا لحاوية ويعيد مكرر إدراج
ً تأخذ دالة ُمدرج_خلف •
وعندما نقوم بتعيني من خالل هذا املكرر ، •
فإن التعيني سيستدعي دفع_للخلف ليضيف عنرصاً بالقيمة املحددة إلى الحاوية : •
وكثريًا ما نستخدم ُمدرج_خلف إلنشاء مكرر الستخدامه كوجهة للخوارزمية .فمثال : •
تعد الخوارزمية نسخ مثااًل آخر على خوارزمية تكتب على عنارص تسلسل مخرجات يشار إليه بواسطة مكرر وجهة.
• تأخذ هذه الخوارزمية ثالثة مكررات .يشري األوليان لنطاق املدخالت ؛ والثالث إلى بداية تسلسل الوجهة.
تنسخ هذه الخوارزمية عنارص من نطاق مدخالتها إلى عنارص في الوجهة. •
من األسايس أن يكون حجم الوجهة اليت يتم تمريرها للخوارزمية كبرياً على األقل بحجم نطاق املدخالت. •
كمثال ،يمكننا استخدام copyلنسخ مصفوفة مدمجة إلى أخرى:
هنا نعرف مصفوفة باسم a2ونستخدم sizeofلضمان أن تملك a2عنارص بعدد عنارص . a1 •
ثم نستدعي copyلنسخ a1إلى .a2 •
بعد استدعاء ، copyسيكون للعنارص في كال املصفوفتني القيم نفسها. •
القيمة املعادة من copyهي القيمة (املزتايدة) عن مكرر الوجهة. •
بمعىن أن ، retسيشري ملا بعد آخر عنرص تم نسخه إلى .a2 •
التمرين :10.6
برنامجا لتعيني تسلسل قيم رقم صحيح على .0
ً باستخدام ، fill_nاكتب
التمرين :10.7
حدد ما إذا كانت هناك أية أخطاء في الربامج التالية ،وإذا كان األمر كذلك ،فقم بتصحيح الخطأ (األخطاء):
)(a
;vector<int> vec; list<int> lst; int i
)while (cin >> i
;) lst.push_back(i
;))(copy(lst.cbegin(), lst.cend(), vec.begin
)(b
;vector<int> vec
)vec.reserve(10); // reserve is covered in § 9.4 (p. 356
;)fill_n(vec.begin(), 10, 0
التمرين :10.8
قلنا أن الخوارزميات ال تغري حجم الحاويات اليت تعمل عليها .ملاذا ال يؤدي استخدام ُمدرج_خلف إلى إبطال هذا
اﻻدعاء ؟
the quick red fox jumps over the slow red turtle
الستبعاد الكلمات املتكررة ،سنقوم أوال ً بفرز املتجه بحيث تظهر الكلمات املتكررة بجوار بعضها.
بمجرد فرز املتجه ،يمكننا استخدام خوارزمية مكتبة أخرى ،تسمى فريد_ ،unique •
وذلك إلعادة ترتيب املتجه بحيث تظهر العنارص الفريدة منه في الجزء األول من املتجه. •
وألن الخوارزميات ال يمكنها إجراء عمليات حاوية ، •
فعليا :
ً سنستخدم العضو مسح_ eraseفي املتجه إلزالة العنارص •
تأخذ الخوارزمية فرز_ مكررين للداللة على نطاق عنارص الفرز. •
في هذا االستدعاء ،نقوم بفرز املتجه بأكمله. •
بعد استدعاء فرز_ ،يتم ترتيب الكلمات بتنسيق •
fox jumps over quick red red slow the the turtle
حجم كلمات كما هو ؛ فال يزال يحمل عرشة عنارص .لكن تم تغيري ترتيب هذه العنارص - •
حيث تمت "إزالة" العنارص املتكررة املتجاورة. •
لقد وضعنا إزالة بني عالميت اقتباس ألن الخوارزمية فريد_ لن تزيل أية عنارص. •
بل ،تقوم بالكتابة فوق املتكررات املتجاورة بحيث تظهر العنارص الفريدة في مقدمة التسلسل. •
املكرر املعاد بواسطة فريد_ يشري إلى ما بعد آخر عنرص فريد. •
ستظل عنارص ما بعد تلك النقطة موجودة ،لكننا لن نعرف ما القيم اليت تملكها. •
ملحوظة
تعمل خوارزميات املكتبة على مكررات ،ﻻ على حاويات .لذا ،لن يمكنها (مبارشة) أن تضيف أو تزيل عنارص.
التمرين :10.9
-نفذ إصدارك من دالة .elimDups
-اخترب برنامجك بطباعة املتجه بعد قراءة املدخالت ،
-وبعد استدعاء فريد_ ،
-وبعد استدعاء مسح_.
التمرين :10.10
ملاذا تعتقد أن الخوارزميات ال تغري حجم الحاويات؟
10٫3تخصــــــــــيص العمـــــــــليــــــــــات
10.3 Customizing Operations
فعلى سبيل املثال ،تستخدم الخوارزمية فرز_ sortعامل نوع العنرص > أقل من.
مع ذلك ،قد نرغب في فرز تسلسل إلى ترتيب مختلف عن ذلك املحدد بواسطة > ، •
أو قد يحتوي تسلسلنا على عنارص من نوع فئة (كبيانات_املبيعات) ال تملك العامل >. •
في كلتا الحالتني ،نحتاج إلى تجاوز السلوك االفرتايض لـفرز_. •
Predicates املحموالت
املحمولة تعبري يمكن استدعاؤه ويعيد قيمة يمكن استخدامها كرشط (تعطي نتيجة منطقية).
املحموالت اليت تستخدمها خوارزميات املكتبة هي •
إما محموالت أحادية ( unary predicatesبمعىن أن لديها معلمة واحدة ) ، •
وإما محموالت ثنائية ( binary predicatesبمعىن أن لديها معلمتان ). •
الخوارزميات اليت تأخذ محموالت تستدعي املحمولة املحدد على عنارص في نطاق املدخالت.
نتيجة لذلك ،يجب أن يكون من املمكن تحويل نوع العنرص إلى نوع معلمة املحمولة. •
يستخدم إصدار فرز_ الذي يأخذ محمولة ثنائية املحمولة املحددة بدال ً من العامل > ملقارنة عنارص. •
يجب أن تفي املحموالت اليت نوفرها لفرز_ باملتطلبات اليت سنصفها في الفقرة .11.2.2 •
تعرف ترتيبًا ثاب ًتا لجميع العنارص املمكنة في تسلسل املدخالت.
حالياً ،نحتاج معرفة أن العملية يجب أن ّ •
تعد الدالة هل_أقرص isShorterمن الفصل 6مثاال ً على دالة تليب هذه املتطلبات ، •
لذا يمكننا تمريرها لفرز_ .وسيؤدي القيام بذلك إلى إعادة ترتيب العنارص حسب الحجم : •
إذا احتوت الكلمات على نفس البيانات الواردة في الفقرة ، 10٫2٫3 •
فإن هذا االستدعاء سيعيد ترتيب الكلمات ، •
بحيث تظهر جميع الكلمات ذات الطول 3قبل ذات الطول ، 4واليت بدورها تتبعها كلمات بطول ، 5و هكذا. •
أيضا الحفاظ على الرتتيب األبجدي بني العنارص اليت لها نفس الطول.
عندما نفرز كلمات حسب الحجم ،نريد ً
وللحفاظ على الكلمات متساوية الطول برتتيبها األبجدي ،نستخدم خوارزمية فرز_صلب .stable_sort •
يحافظ فرز_صلب على الرتتيب األصلي بني العنارص املتساوية. •
في العادة ،ال نهتم بالرتتيب النسيب للعنارص املتساوية في تسلسل مفرز .فبعد كل يشء ،إنها متساوية.
مع ذلك ،في هذه الحالة ،قمنا بتعريف كلمة "متساوي" لتعين "تملك نفس الطول". •
ال تزال العنارص متساوية الطول تختلف عن بعضها عند عرض محتوياتها. •
من خالل استدعاء فرز_صلب ،يمكننا الحفاظ على الرتتيب األبجدي بني العنارص متساوية الطول: •
بافرتاض أن الكلمات كانت بالرتتيب األبجدي قبل هذا االستدعاء ، •
بعد االستدعاء ،سيتم فرز الكلمات حسب حجم العنرص ،وستبقى كلمات كل طول بالرتتيب األبجدي. •
إذا قمنا بتشغيل هذا الكود على املتجه األصلي الخاص بنا ،فستكون املخرجات
التمرين :10.11
برنامجا يستخدم "فرز_صلب " stable_sortو هل_أقرص isShorterلفرز متجه تم تمريره إلى
ً -اكتب
إصدارك من .elimDups
-اطبع املتجه للتحقق من صحة برنامجك.
التمرين :10.12
-اكتب دالة باسم CompareIsbnتقارن بني أعضاء isbnلكائنني من كائنات .Sales_data
-استخدم هذه الدالة لفرز متجه يحتوي على كائنات .Sales_data
التمرين :10.13
ُعرف املكتبة خوارزمية تسمى " ِق ْسم " partitionتأخذ محمولة وتقسم الحاوية بحيث تظهر القيم اليت يكون
-ت ّ
صحيحا trueفي القسم األول وتلك اليت يكون تعبري محمولها خاطًئ ا falseلتظهر في القسم
ً تعبري محمولها
الثاني.
صحيحا.
ً مكررا بعد آخر عنرص أعاد محموله
ً -تُعيد الخوارزمية
منطقيا يشري إلى ما إذا كانت السلسلة تتكون من خمسة أحرف أو أكرث.
ً -اكتب دالة تأخذ سلسلة وتُعيد
-استخدم هذه الدالة لتقسيم كلمات.
-اطبع العنارص اليت تحتوي على خمسة أحرف أو أكرث.
يجب أن تحتوي املحموالت اليت نمررها إلى خوارزمية ما على معلمة واحدة أو اثنتني ،
اعتما ًد ا على ما إذا كانت الخوارزمية تأخذ محمولة أحادية أو ثنائية ،على التوالي. •
مع ذلك ،فإننا نود أحياناً إجراء معالجة تتطلب وسيطات أكرث مما تسمح به محمولة الخوارزمية. •
فعلى سبيل املثال ،في الحل الذي كتبته للتمرين األخري في القسم السابق ، •
كان يجب أن يربط الحجم 5إلى املحمولة املستخدمة لتقسيم التسلسل. •
سيكون من املفيد القدرة على تقسيم تسلسل دون الحاجة إلى كتابة محمولة منفصلة لكل حجم ممكن. •
كمثال ذي صلة ،سرناجع برنامجنا من الفقرة 10٫3٫1إلظهار عدد الكلمات ذات الحجم املحدد أو أكرب. •
أيضا بتغيري املخرجات بحيث ﻻ يطبع إﻻ الكلمات ذات الطول املحدد أو أكرب.
سنقوم ً •
الرسم التخطيطي لهذه الدالة ،اليت سنسميها ، biggiesسيكون على النحو التالي :
تتمثل مشكلتنا الجديدة في إيجاد أول عنرص في املتجه يملك الحجم املحدد. •
بمجرد أن نعرف ذلك العنرص ،سنستخدم موضعه لحوسبة عدد العنارص اليت تملك ذلك الحجم أو أكرب. •
يمكننا استخدام خوارزمية املكتبة أوجد_إذا find_ifإليجاد عنرص بحجم معني.
زوجا من املكررات تدل على نطاق.
ً ومثل الخوارزمية إيجاد_ ، findتأخذ الخوارزمية find_if •
لكنها على عكس ، findستكون وسيطتها الثالثة عبارة عن محمولة. •
تستدعي الخوارزمية find_ifاملحمولة املحددة على كل عنرص في نطاق املدخالت. •
فتقوم بإعادة أول عنرص تقوم املحمولة بإعادة قيمة غري صفرية له ، •
أو تقوم بإعادة مكرر نهاية_ إذا لم يتم إيجاد مثل ذلك العنرص. •
وحجما
ً سيكون من السهل كتابة دالة تأخذ سلسلة
منطقيا يشري إلى ما إذا كان حجم سلسلة معينة أكرب من الحجم املحدد.
ً وتُعيد •
مع ذلك ،فإن find_ifتأخذ محمولة أحادية ؛ فأي دالة نمررها إلى ، find_if •
يجب أن تملك معامالً واحداً بالضبط يمكن استدعاؤه باستخدام عنرص من تسلسل املدخالت. •
إذن ،فال توجد طريقة لتمرير وسيطة ثانية تمثل الحجم. •
لحل هذا الجزء من مشكلتنا ،سنحتاج إلى استخدام بعض أقسام اللغة اإلضافية. •
املواد القابلة لالستدعاء الوحيدة اليت استخدمناها حىت اآلن هي الدوال ومؤرشاتها.
لكن هناك نوعان آخران من العنارص القابلة لالستدعاء : •
الفئات اليت تزيد-تعبئة عامل استدعاء الدالة ،سنغطيها في الفقرة ، 14.8وتعبريات المدا_. •
يمثل تعبري المدا وحدة قابلة لالستدعاء من األكواد الربمجية .ويمكن اعتبارها دالة ضمن-سطر غري مسماة.
ومثل أي دالة ،تحتوي المدا على نوع إعادة ،وقائمة معلمات ،وبنية دالة. •
لكنها على عكس الدالة ،يمكن تعريفها ضمن دالة. •
يملك تعبري المدا_ النموذج التالي : •
حيث :
معرفة في الدالة املتضمنة
غالبا) ّ
ً قائمة_التقاط capture listهي قائمة متغريات محلية (فارغة •
نوع_اإلعادة return typeوقائمة املعلمات parameter listوبنية الدالة function body •
هي نفسها كما في أي دالة عادية. •
مع ذلك ،فعلى عكس الدوال العادية ،يجب أن تستخدم المدا العائد الالحق لتعريف نوع اإلعادة. •
دائما تضمني قائمة_التقاط وبنية الدالة :
ً يمكننا حذف قائمة املعلمات أو نوع اإلعادة أو كالهما لكن يجب •
;} ;auto f = [] { return 42
هنا ،عرفنا fككائن قابل لالستدعاء ال يأخذ أية وسيطات ويعيد . 42 •
نستدعي الالمدا_ بنفس الطريقة اليت نستدعي بها أية دالة وذلك باستخدام عامل االستدعاء :
إن حذف األقواس وقائمة املعلمات في المدا_ يعادل تعريف قائمة معلمات فارغة. •
ومن ثم ،فعندما نستدعي ، fستكون قائمة وسيطاتها فارغة. •
فإذا حذفنا نوع اإلعادة ،فإن الالمدا_ تملك نوع إعادة مستنتج يعتمد على الكود في بنية الدالة. •
أما إذا كانت بنية الدالة تملك فقط جملة ِ
أعد ،فسيتم استنتاج نوع اإلعادة من نوع التعبري املعاد. •
خالف ذلك ،يكون نوع اإلعادة فراغـاً .void
ملحوظة
كما هو حال استدعاء أي دالة عادية ،تُستخدم وسيطات استدعاء المدا لتهيئة معامالتها.
فكالعادة ،يجب أن تتطابق الوسيطات مع أنواع املعلمات. •
لكن على عكس الدوال العادية ،ﻻ يسمح أن تحتوي الالمدا على وسيطات افرتاضية. •
دائم ا ما يكون عدد وسيطات استدعاء الالمدا مطابقاً لعدد معلماتها.
ً لذا ، •
وبمجرد تهيئة معلماتها ،يتم تنفيذ بنية الدالة. •
كمثال على المدا تأخذ وسيطات ،يمكننا كتابة المدا تترصف مثل دالتنا : isShorter
};)([](const string &a, const string &b){ return a.size() < b.size
تشري قائمة االلتقاط الفارغة هذه إلى أن هذه الالمدا لن تستخدم أي متغريات محلية من الدالة املتضمنة. •
معلمات الالمدا ،مثل معلمات ، isShorterعبارة عن مراجع لسلسلة ثابتة. •
وتقارن بنيتها حجم معلماته وتعيد قيمة منطقية تعتمد على األحجام النسبية للوسيطات املعطاة. •
يمكننا إعادة كتابة استدعائنا لفرز_صلب stable_sortلتستخدم هذه الالمدا على النحو التالي :
عندما تحتاج " "stable_sortإلى مقارنة عنرصين ،فسوف يستدعي تعبري الالمدا املعطى. •
Using the Capture List استخدام قائمة االلتقاط
ملحوظة
محليا لدالتها املتضمنة إﻻ إذا التقطت ذلك املتغري ضمن قائمة التقاطها.
ً لن تستخدم المدا متغريًا
باستخدام هذه الالمدا ،يمكننا إيجاد أول عنرص يكون حجمه على األقل بحجم : sz
يقوم استدعاء find_ifبإعادة مكرر إلى أول عنرص يكون على األقل بطول szاملعطى ، •
أو بإعادة نسخة من نهاية_ كلمات Words.endإذا لم يكن ذلك العنرص موجو ًدا. •
يمكننا استخدام املكرر العائد من find_ifلحوسبة عدد العنارص اليت ظهرت بني ذلك املكرر ونهاية_ كلمات:
تستدعي جملة مخرجاتنا make_pluralلتطبع كلمة أو كلمات ،اعتما ًدا على ما إذا كان هذا الحجم يساوي .1
الجزء األخري من مشكلتنا هو طباعة العنارص في كلمات واليت طولها مساو لـ szأو أكرب.
للقيام بذلك ،سنستخدم الخوارزمية .for_each •
تأخذ هذه الخوارزمية كائنًا قابالً لالستدعاء وتستدعي ذلك الكائن على كل عنرص في نطاق املدخالت : •
// print words of given size or longer, each one followed by space
;)};" " << for_each(wc, words.end(),[](const string &s){cout << s
;cout << endl
قائمة االلتقاط في هذه الالمدا فارغة ،مع ذلك تستخدم البنية اسمني :
معلمتها الخاصة اليت تسمى ، sو .cout •
معرفة ضمن الدالة املتضمنة فقط.
إن قائمة االلتقاط فارغة ألننا نستخدمها ملتغريات ( ّ ) non-static •
معرفة خارج الدالة اليت تتضمنها المدا_.
لكن يمكن أن تستخدم المدا أسماء ّ •
محليا في الدالة املتضمنة biggies؛
ً اسما معرفاً
ً في هذه الحالة cout ،ليس •
حيث يتم تعريف هذا االسم في العنوان .iostream •
وطاملا تم تضمني العنوان iostreamفي نطاق يظهر فيه ، biggiesيمكن أن تستخدمه الالمدا_. •
ملحوظة
تمرين :10.14
اكتب المدا تأخذ رقمني صحيحني وتُعيد مجموعهما.
التمرين :10.15
-اكتب المدا تلتقط رقم صحيح من دالة تضمينها وتأخذ معامل رقم صحيح.
-ينبغي أن تُعيد الالمدا مجموع الرقم الصحيح امللتقط مع معلمة الرقم الصحيح.
التمرين :10.16
اكتب نسختك من دالة biggiesباستخدام الالمدا.
التمرين :10.17
أعد كتابة التمرين 10٫12من الفقرة 10٫3٫1باستخدام الالمدا في استدعاء فرز بدال ً من دالة .CompareIsbn
التمرين :10.18
-أعد كتابة biggiesباستخدام القسم partitionبدال ً من .find_ifلقد
-وصفنا خوارزمية التقسيم في التمرين 10٫13في الفقرة .3.1.10
التمرين :10.19
-أعد كتابة التمرين السابق باستخدام "القسم الصلب ، "stable_partition
-والذي مثل "الفرز الصلب "stable_sortيحافظ على ترتيب العنارص األصلي في التسلسل املقسم.
نعرف المدا ،يقوم املرتجم بتوليد نوع فئة جديد (غري مسمى) يتوافق مع تلك الالمدا.
عندما ّ
سرنى كيف يتم توليد تلك الفئات في فقرة .14٫8٫1أما في الوقت الحالي ،فما يفيدنا فهمه هو : •
نعرف نوعاً جديداً وكائناً من ذلك النوع :
أنه عندما نقوم بتمرير المدا إلى دالة ،فإننا ّ •
فالوسيطة هي كائن غري مسمى من نوع الفئة املولّ د بواسطة املرتجم هذا. •
وباملثل ،عندما نستخدم autoلتعريف متغري تمت تهيئته بواسطة المدا ، •
نعرف كائنًا من النوع املولّ د من تلك الالمدا.
فإننا ّ •
افرتاضياً ،تحتوي الفئة املولّ دة من المدا على عضو بيانات يتوافق مع املتغريات امللتقطة بواسطة الالمدا.
فمثل أعضاء بيانات أي فئة ،تتم تهيئة أعضاء بيانات المدا عند إنشاء كائن المدا. •
على غرار تمرير املعلمات ،يمكننا التقاط متغريات بواسطة قيمة أو بواسطة مرجع.
يغطي الجدول 10٫1الطرق املختلفة اليت يمكننا من خاللها تكوين قائمة التقاط. •
حىت اآلن ،التقطت الالمدا متغريات بواسطة قيمة. •
وكما هو حال معلمة تم تمريرها بواسطة قيمة ،يجب أن يكون من املمكن نسخ تلك املتغريات. •
لكن على عكس املعلمات ،يتم نسخ قيمة متغري ملتقط عند إنشاء الالمدا ،وليس عند استدعائها : •
{ )(void fcn1
; size_t v1 = 42 // local variable
// copies v1 into the callable object named f
;} ; auto f = [v1] { return v1
; v1 = 0
auto j = f(); } // j is 42; f stored a copy of v1 when we created it
void fcn2() {
size_t v1 = 42; // local variable
// the object f2 contains a reference to v1
auto f2 = [&v1] { return v1; };
v1 = 0;
auto j = f2(); } // j is 0; f2 refers to v1; it doesn't store it
.تواجه امللتقطات املرجعية نفس املشاكل والقيود اليت تواجهها املراجع املعادة
. فيجب أن نتأكد من وجود الكائن املشار إليه في وقت تنفيذ الالمدا، فإذا التقطنا متغريًا بواسطة مرجع •
. وتنتهي من الوجود بمجرد اكتمال الدالة.املتغريات امللتقطة بواسطة المدا عبارة عن متغريات محلية •
، فإذا كان من املمكن تنفيذ المدا بعد انتهاء الدالة •
.فاملتغريات املحلية اليت يشري إليها االلتقاط لن تظل موجودة •
عندما نقوم بتمرير المدا إلى دالة ،كما هو حال استدعاء ، for_eachسيتم تنفيذ الالمدا على الفور. •
يعد التقاط osباملرجع أمرًا جي ًدا ،ألن املتغريات في biggiesموجودة أثناء تشغيل .for_each •
أيض ا إعادة المدا من دالة .فقد تقوم الدالة بإعادة كائن قابل لالستدعاء مبارشة ،
ويمكننا ً
أو قد تُعيد كائنًا من فئة تحتوي على كائن قابل لالستدعاء كعضو بيانات. •
مرجعا ملتغري محلي -
ً فإن كانت الدالة تُعيد المدا ،فإذن -ولنفس األسباب اليت تجعل دالة ال يجب أن تُعيد •
يجب أال تحتوي تلك الالمدا على التقاطات مرجعية. •
تحذير
عندما نلتقط متغريًا باملرجع ،يجب أن نتأكد من وجود املتغري في الوقت الذي يتم فيه تنفيذ الالمدا.
يقوم التقاط المدا بتخزين معلومات بني وقت إنشاء الالمدا ووقت تنفيذها ؛ •
(أي عند تنفيذ الكود الذي يعرف الالمدا) والوقت (أو األوقات) اليت يتم فيها تنفيذ الالمدا نفسها. •
حيث يقع على عاتق املربمج مسؤولية التأكد من أن : •
أي معلومات يتم التقاطها تحمل املعىن املقصود في كل مرة يتم فيها تنفيذ الالمدا. •
عاد ًة ما يكون التقاط متغري عادي -عدد صحيح أو سلسلة أو أي نوع آخر غري مؤرش -بواسطة قيمة •
أمرًا مبارشًا.
في هذه الحالة ،نحتاج فقط أن نهتم بما إذا كان املتغري يملك القيمة اليت نحتاجها عند التقاطه. •
قد يؤدي الكود الذي ينفذ بني وقت إنشاء الالمدا ووقت تنفيذه إلى تغيري قيمة الكائن الذي يؤرش عليه (أو •
يشري إليه ) التقاط الالمدا.
قد تكون قيمة الكائن في وقت التقاط املؤرش (أو املرجع) فيه هي ما أردناه. •
تماما.
ً لكن قد تكون قيمة هذا الكائن عند تنفيذ الالمدا مختلفة •
كقاعدة عامة ،يمكننا تجنب مشاكل االلتقاطات املحتملة عن طريق تقليل البيانات اليت نلتقطها. •
عالوة على ذلك ،إذا أمكن ،تجنب التقاط مؤرشات أو مراجع. •
بدال ً من رسد املتغريات اليت نريد استخدامها رصاحة من الدالة املتضمنة ،
يمكننا السماح للمرتجم باستنتاج أي متغريات سنستخدمها من الكود في بنية الالمدا. •
لتوجيه املرتجم الستنتاج قائمة االلتقاط ،نستخدم & أو = في قائمة االلتقاط. •
يخرب الـ & املرتجم أن يلتقط باملرجع ،و يقول الـ = أن القيم تلتقط بالقيمة. •
على سبيل املثال ،يمكننا إعادة كتابة الالمدا اليت مررناها لـ : find_if •
لو أردنا التقاط بعض املتغريات بالقيمة وأخرى باملرجع ،فيمكننا مزج االلتقاط الضمين والرصيح:
عندما نمزج االلتقاطات الضمنية مع الرصيحة ،يجب أن يكون أول عنرص في قائمة االلتقاط إما & وإما = . •
سيضبط هذا الرمز وضع االلتقاط االفرتايض على أنه بمرجع أو بقيمة ،على التوالي. •
وكذلك يجب أن تستخدم املتغريات امللتقطة رصاحة الشكل البديل .بمعىن أنه : •
إذا كان االلتقاط الضمين باملرجع (استخدام &) ،فيجب أن يتم التقاط املتغريات املسماة رصاحة بالقيمة ؛ •
ومن ثم ال يجوز أن تسبق أسمائها عالمة & .والعكس بالعكس ، •
فإذا كان االلتقاط الضمين بالقيمة (استخدام =) ،فيجب أن تكون املتغريات املسماة رصاحة مسبوقة بـ &؛ •
لتشري إلى أنه سيتم التقاطها عن طريق املرجع. •
{ )(void fcn3
size_t v1 = 42; // local variable
// f can change value of variables it captures
;} ; auto f = [v1] () mutable { return ++v1
; v1 = 0
;)( auto j = f } // j is 43
{ )(void fcn4
; size_t v1 = 42 // local variable
// v1 is a reference to a non const variable
// we can change that variable through reference inside f2
;} ; auto f2 = [&v1] { return ++v1
; v1 = 0
auto j = f2(); } // j is 1
يستنتج إصدار الالمدا هذا نوع اإلعادة على أنه فراغ لكننا قمنا بإعادة قيمة. •
عندما نحتاج إلى تعريف نوع إعادة المدا ،يجب أن نستخدم نوع إعادة الحق : •
في هذه الحالة ،وسيطة تحويل_ الرابعة عبارة عن المدا بقائمة التقاط فارغة ، •
وتأخذ معلمة وحيدة من نوع عدد صحيح وتُعيد قيمة من نوع عدد صحيح. •
بنية دالتها عبارة عن جملة ifتُعيد القيمة املطلقة ملعلمتها. •
التمرين :10.20
عد_إذا تسمى .count_if
تعرف املكتبة خوارزمية ّ
ّ -
-مثل أوجد_إذا ، find_ifتأخذ هذه الدالة زوج مكررات لنطاق مدخالت ومحمولة تنطبق على كل عنرص في
النطاق املحدد.
-يعرض count_ifعدد مرات صحة املحمولة.
-استخدم count_ifإلعادة كتابة جزء برنامجنا الذي يحسب عدد الكلمات األكرب من الطول .6
التمرين :10.21
محليا ويتناقص ذلك املتغري حىت يصل إلى .0
ً -اكتب المدا تلتقط متغرياً عدداً صحيحاً
-بمجرد أن يصبح املتغري صفرًا ،يجب أال تنقص املتغري استدعاءات إضافية.
منطقيا يشري إلى ما إذا كان املتغري امللتقط هو .0
ً -ينبغي أن تُعيد الالمدا
تعد تعبريات المدا أكرث فائدة لعمليات بسيطة ال نحتاج إلى استخدامها في أكرث من مكان أو مكانني.
أما إذا احتجنا إلى إجراء نفس العملية في عدة أماكن ، •
فينبغي عاد ًة تعريف دالة بدال ً من كتابة نفس تعبري الالمدا عدة مرات. •
وباملثل ،إذا كانت عملية ما تتطلب عدة جمل ،فمن األفضل عاد ًة استخدام دالة. •
عادة ما يكون من املبارش استخدام دالة بدال ً من المدا تحتوي على قائمة التقاط فارغة.
فكما رأينا ،يمكننا استخدام إما المدا أو الدالة isShorterلفرز املتجه بناء على طول الكلمة. •
وباملثل ،سيكون من السهل استبدال الالمدا اليت طبعت محتويات املتجه ، •
عن طريق كتابة دالة تأخذ سلسلة وتطبع السلسلة املحددة إلى املخرجات القياسية. •
مع ذلك ،فليس من السهل كتابة دالة تستبدل المدا تلتقط متغريات محلية.
فمثالً ،قارنت الالمدا اليت استخدمناها في استدعاء ( find_ifقارنت) سلسلة بحجم معني. •
يمكننا بسهولة كتابة دالة للقيام بنفس العمل : •
مع ذلك ،لن يمكننا استخدام هذه الدالة كوسيطة لـ .find_if •
فكما رأينا ،فإن find_ifتأخذ محمولة أحادية ،لذلك يجب أن يأخذ قابل االستدعاء الذي تم تمريره إلى •
find_ifوسيطة وحيدة.
تستخدم الالمدا الذي مررته biggiesإلــى find_ifقائمة التقاطها لتخزين .sz •
من أجل استخدام check_sizeفي مكان تلك الالمدا ،علينا إيجاد طريقة لتمرير وسيط إلى املعلمة .sz •
حيث :
يعترب newCallableنفسه كائن قابل لالستدعاء •
و arg_listقائمة وسيطات مفصولة بفاصلة تتوافق مع معلمات قابل االستدعاء املحدد. •
بمعىن أنه عند استدعاء ، newCallable •
فستقوم newCallableباستدعاء ، callableممررة الوسيطات في . arg_list •
صحيحا.
ً قد تتضمن الوسيطات في arg_listأسماء من النموذج _ ، nحيث تمثل nعد ًدا
هذه الوسيطات هي " عنارص نائبة " placeholdersتمثل معلمات . newCallable •
إنها تقف "في مكان" الوسيطات اليت سيتم تمريرها إلى . newCallable •
الرقم nيمثل موضع املعلمة في االستدعاء املولّ د : •
فـ _ 1هو أول معلمة في ، newCallableو _ 2هي املعلمة الثانية ،وهكذا دواليك. •
// check6 is a callable object that takes one argument of type string
// and calls check_size on its given string and value 6
;)auto check6 = bind(check_size, _1, 6
استدعاء الربط هذا لديه عنرص نائب واحد فقط ،ما يعين أن check6تأخذ وسيطة وحيدة. •
يظهر العنرص النائب أوال ً في ، arg_list •
ما يعين أن املعلمة في check6تتوافق مع املعلمة األولى لـ .check_size •
تلك املعلمة عبارة عن سلسلة ثابتة مرجعية ، •
أيضا سلسلة ثابتة مرجعية.
ما يعين أن املعلمة في check6هي ً •
وبالتالي ،يجب أن يمرر استدعاء check6وسيطة من نوع ، string •
واليت ستمرر check6كأول وسيط لـ .check_size •
;"string s = "hello
;)bool b1 = check6(s )// check6(s) calls check_size(s, 6
سيولد هذا االستدعاء لربط_ كائنًا قابالً لالستدعاء يربط الوسيطة الثانية من check_sizeبقيمة .sz •
عندما تستدعي find_ifهذا الكائن على سالسل في كلمات ، •
فإن هذه االستدعاءات بدورها ستستدعي check_sizeممررة السلسلة املعطاة و .sz •
لذلك ،سوف تستدعي ( find_ifبشكل فعال) check_sizeعلى كل سلسلة في نطاق املدخالت •
ويقارن حجم هذه السلسلة بـ .sz
يتم تعريف األسماء _ nفي مساحة اسم تسمى العنارص النائبة . placeholders
يتم تعريف مساحة االسم نفسها داخل مساحة االسم . std •
والستخدام هذه األسماء ،يجب علينا توفري األسماء ملساحيت اﻻسم. •
كما هو الحال مع األمثلة األخرى ،تفرتض استدعاءاتنا لربط_ وجود إعالنات usingمناسبة. •
على سبيل املثال ،إعالن usingلـ _ 1هو : •
;using std::placeholders::_1
يوضح هذا اإلعالن أننا نستخدم االسم _ ، 1الذي تم تعريفه في مساحة االسم ،placeholders •
والذي تم تعريفه بنفسه في مساحة االسم . std •
يقول أننا نريد أن نجعل جميع األسماء من namespace_nameمتاحة لربنامجنا .فمثال :
يولد قابل استدعاء جدي ًدا يأخذ وسيطتني ،يمثلهما العنرصان النائبان _ 2و _.1 •
سوف يمرر القابل لالستدعاء الجديد وسيطاته الخاصة باعتباره الوسيط الثالث والخامس لـ .f •
تُربط الوسيطات األولى والثانية والرابعة لـ fبالقيم املحددة a ،و bو cعلى التوالي. •
إلى
)f(a, b, _2, c, _1
كمثال أكرث واقعية الستخدام ربط إلعادة ترتيب الوسيطات ،يمكننا استخدام ربط لعكس معىن isShorter
بكتابة
في أول استدعاء ،عندما احتاجت فرز ملقارنة العنرصين Aو ، Bفإنها استدعت ).isShorter(A ، B •
أما في االستدعاء الثاني لفرز ،تم مبادلة وسيطات .isShorter •
وفي تلك الحالة ،عندما تقارن فرز بني العنارص ، •
فسيكون األمر كما لو أن فرز استدعت ).isShorter(B ، A •
افرتاضياً ،يتم نسخ وسيطات ربط اليت ليست عنارص نائبة إلى الكائن القابل لالستدعاء الذي تعيده ربط_.
• مع ذلك ،وكما هو الحال مع الالمدا ،فأحيانا يكون لدينا وسيطات نريد ربطها ،
لكننا نريد تمريرها بواسطة مرجع أو قد نرغب في ربط وسيطة لديها نوع ال يمكننا نسخه. •
على سبيل املثال ،الستبدال الالمدا اليت التقطت ostreamباملرجع :
ومع ذلك ،ال يمكننا استخدام ربط مبارشة الستبدال التقاط : os
تُعيد الدالة refكائنًا يحتوي على املرجع املحدد ويكون هو نفسه قاباًل للنسخ. •
مرجعا لـثابت.
ً أيضا الدالة crefاليت تولد فئة تحمل
هناك ً •
ومثل ربط_ ،يتم تعريف داليت refو crefفي عنوان الدوال .functional •
قدمت إصدارات يس ++اﻷقدم مجموعة أقسام محدودة أكرث -لكن أكرث تعقي ًدا -لربط الوسيطات بالدوال. •
فعرفت املكتبة دالتني باسم bind1stو .bind2nd
ّ •
ومثل ربط_ ،تأخذ هاتني الدالتني دالة وتولدان كائنًا جدي ًدا قابالً لالستدعاء ، •
يستدعي الدالة املحددة بإحدى معلماتها املربوطة بقيمة معينة. •
مع ذلك ،يمكن لهاتني الدالتني ربط املعلمة األولى أو الثانية فقط ،على التوالي. •
ونظرًا ألن فائدتها محدودة للغاية ،فقد تم إهمالها في املعيار الجديد. •
املزية املهملة هي املزية اليت قد ال يتم دعمها في إصدارات مستقبلية. •
التمرين :10.22
أعد كتابة الربنامج لحساب الكلمات ذات الحجم 6أو أقل باستخدام الدوال بدال ً من المدا.
التمرين :10.23
كم عدد الوسيطات اليت تأخذها ربط؟
التمرين :10.24
استخدم bind and check_sizeإليجاد العنرص األول في متجه أرقام صحيحة الذي له قيمة أكرب من طول
قيمة سلسلة محددة.
التمرين :10.25في تدريبات الفقرة 10.3.2كتبت نسخة من biggiesتستخدم التقسيم .أعد كتابة هذه الدالة
باستخدام check_sizeوالربط.
10٫4مراجــــــــــعة املـــــــــكــــــــــررات
10.4 Revisiting Iterators
الـمد ِرجات .تختلف كل منها عن األخريات فيما يتعلق بمكان إدراج العنارص :
هناك ثالثة أنواع من ُ
مكررا يستخدم دفع_للخلف .Push_back
ً ُمدرج_خلف : back_inserterينئش •
مكررا يستخدم دفع_للمقدمة .push_front
ً ُمدرج_مقدمة : front_inserterينئش •
مكررا يستخدم إدراج_ . insertتأخذ هذه الدالة وسيطة ثانية ، ً ُمدرج_ : inserterينئش •
مكرر ا في الحاوية املحددة .يتم إدراج العنارص قبل العنرص املشار إليه باملكرر املحدد.
ً واليت يجب أن تكون •
ملحوظة
لن يمكننا استخدام ُمدرج_مقدمة إال لحاوية تملك عضو دفع_للمقدمة .push_front •
وباملثل ،ال يمكن استخدام ُمدرج_خلف إال على حاوية تملك دفع_للخلف .push_back •
من املهم أن نفهم أنه عندما نستدعي مدرج_ )، inserter(c, iter •
نحصل على مكرر يقوم ،عند استخدامه تباعاً ،بإدراج عنارص قبل املشار إليه في األصل بواسطة .iter •
مكررا تم إنشاؤه بواسطة ُمدرج_ ،فإن تعييناً مثل
ً بمعىن أنه ،إذا كان it •
;* it = va1
سيترصف مثل
عندما نستدعي ) ، front_inserter(cنحصل على مكرر إدراج يستدعي تباعاً دفع_للمقدمة. •
وكل عنرص يتم إدراجه ،سيصبح العنرص األول الجديد في .c •
مكررا يعكس ترتيب التسلسل الذي يُدرجه ؛
ً لذلك ،ينتج ُمدرج_مقدمة •
ومدرج_خلف ذلك.
بينما ﻻ يفعل ُمدرج_ ُ •
التمرين :10.26
ارشح االختالفات بني األنواع الثالثة ملكررات اإلدراج.
التمرين :10.27
-باإلضافة إلى "فريد_ ، "uniqueتعرف املكتبة دالة تسمى "نسخ_فريد "unique_copy
مكررا ثالثًا يشري إلى الوجهة اليت يتم نسخ العنارص الفريدة إليها.
ً -تأخذ
برنامجا يستخدم unique_copyلنسخ العنارص الفريدة من متجه إلى قائمة فارغة أولياً.
ً -اكتب
التمرين :10.28
متجها يحمل القيم من 1إلى 9في ثالث حاويات أخرى.
ً -انسخ
ومدرجاً خلفياً ،ومدرجا أماميا ،على الرتتيب إلضافة عنارص إلى هذه الحاويات.
-استخدم ُمدرجاً ُ ،
-توقع كيف يختلف تسلسل املخرجات حسب نوع املُدرج وتحقق من تنبؤاتك عن طريق تشغيل برامجك.
>> Reads the next value from the input stream using the
operator for the element type.
++in, in++ As usual, the prefix version returns a reference to the
incremented iterator.
The postfix version returns the old value.
. يجب أن نحدد نوع الكائنات اليت سيقرأها أو يكتبها املكرر، عندما نقوم بإنشاء مكرر قناة
.يستخدم مكرر قناة_املدخالت عامل << مزدوج لقراءة قناة •
. يجب أن يحتوي النوع الذي يقرأه مكرر قناة_املدخالت على عامل مدخالت محدد، لذلك •
. يمكننا ربطه إلى قناة، فعندما نقوم بإنشاء مكرر قناة_املدخالت •
. ما يؤدي إلى إنشاء مكرر يمكننا استخدامه كقيمة ما بعد النهاية، افرتاضيا
ً يمكننا تهيئة املكرر، وكبديل •
: يمكننا استخدام مكرر قناة_املدخالت لقراءة املدخالت القياسية إلى متجه، كمثال
.vec وتخزن ما تمت قراءته في، cin تقرأ هذه الحلقة أعداداً صحيحة من •
.eof مماثلة لـin_iter تتحقق الحلقة ما إذا كانت، وفي كل تكرار •
. والذي يستخدم كمكرر ما بعد النهاية، تم تعريف ذلك املكرر على أنه مكرر قناة_مدخالت فارغ •
مكرر مرتبط بقناة سيساوي مكرر النهاية بمجرد أن تصادف القناة املرتبط به نهاية ملف أو تواجه خطأ في •
املدخالت أو املخرجات.
الجزء األصعب من هذا الربنامج هو وسيطة ، push_backواليت تستخدم عوامل إلغاء مرجع وتزايد الحقة.
تماما مثل تعابري أخرى كتبناها تجمع بني إلغاء مرجعية وتزايد الحق.
ً يعمل هذا التعبري •
يعمل الزتايد الالحق على تقدم القناة عرب قراءة القيمة التالية لكنها تُعيد قيمة املكرر القديمة. •
تحتوي تلك القيمة القديمة على القيمة السابقة املقروءة من القناة. •
نلغي املرجع عن ذلك املكرر لنحصل على تلك القيمة. •
األكرث فائدة هو أنه يمكننا إعادة كتابة هذا الربنامج كالتالي :
نحن هنا نبين vecمن زوج مكررات تشري إلى مجموعة من العنارص. •
هذه املكررات عبارة عن مكررات قناة_املدخالت ، •
ما يعين أنه يتم الحصول على النطاق من خالل قراءة القناة املرتبطة. •
ٍ
مدخالت ليس بعدد صحيح. يقرأ هذا املُنئش cinحىت يصل لنهاية امللف أو يصادف •
يتم استخدام العنارص اليت تتم قراءتها لبناء .vec •
نظرًا ألن الخوارزميات تعمل من ناحية عمليات املكرر ،وﻷن مكررات القناة تدعم على األقل بعض عمليات املكرر ،
فبإمكاننا استخدام مكررات القناة مع بعض الخوارزميات على األقل. •
سرنى في الفقرة 10.5.1كيف نعرف أي الخوارزميات اليت يمكن استخدامها مع مكررات القناة. •
كمثال ،يمكننا استدعاء تجميع_ accumulateمع زوج من مكررات قناة_املدخالت : •
سينئش هذا االستدعاء مجموع القيم املقروءة من املدخالت القياسية .إذا كانت املدخالت إلى هذا الربنامج هي
23 109 45 89 6 34 12 90 34 23 56 23 8 89 23
عندما نربط مكرر قناة_املدخالت إلى قناة ،فال نضمن أنه سيقرأ القناة على الفور.
يُسمح للتطبيق بتأخري قراءة القناة حىت نستخدم املكرر. •
لكن نضمن أنه قبل إلغاء مرجع املكرر ألول مرة ،ستـتم قراءة القناة. •
بالنسبة ملعظم الربامج ،سواء كانت القراءة فورية أو متأخرة فال تشكل فرقاً. •
مع ذلك ،إذا أنشأنا مكرر قناة_املدخالت دمرناه بدون استخدام ؛ •
أو إذا كنا نزامن القراءات إلى نفس القناة من كائنني مختلفني ،فحينها قد نهتم كثريًا عند حدوث القراءة. •
يمكن تعريف مكرر قناة_املخرجات ألي نوع لديه عامل مخرجات (العامل >>).
فعندما نقوم بإنشاء مكرر قناة_املخرجات ، •
ثانيا يحدد سلسلة أحرف لتطبع بعد كل عنرص.
ً وسيطا
ً (اختياريا)
ً قد نوفر •
يجب أن تكون تلك السلسلة سلسلة أحرف نمطC- •
(أي حرفية سلسلة أو مؤرشاً ملصفوفة منتهية بقيمة خالية). •
يتوجب علينا ربط مكرر قناة_املخرجات إلى قناة محددة. •
ال يوجد هناك مكرر قناة_مخرجات فارغ أو ما بعد النهاية. •
يمكننا استخدام مكرر قناة_املخرجات لكتابة سلسلة من القيم : sequence of values
يقوم هذا الربنامج بكتابة كل عنرص من vecعلى coutكل عنرص متبوع بمسافة. •
في كل مرة نقوم فيها بتعيني قيمة إلى ، out_iterيتم االلزتام بالكتابة. •
من الجدير بالذكر أنه يمكننا حذف إلغاء املرجع والزتايد عندما نعني إلى .out_iter
أي يمكننا كتابة هذه الحلقة متكافئة كالتالي :
ال يقوم العامالن * و ++بعمل أي يشء على مكرر قناة_املخرجات ، •
لذا فإن حذفهما ليس له أي تأثري على برنامجنا. •
مع ذلك ،فنحن نفضل كتابة الحلقة كما قدمت أول مرة. •
تستخدم هذه الحلقة املكرر باستمرار مع كيفية استخدامنا ألنواع مكررات أخرى.
يمكننا بسهولة تغيري هذه الحلقة لتنفيذها على نوع مكرر آخر. •
وضوحا لقراء كودنا.
ً عالوة على ذلك ،سيكون سلوك هذه الحلقة أكرث •
بدال ً من كتابة الحلقة بأنفسنا ،يمكننا بسهولة أكرث طباعة العنارص في vecعن طريق استدعاء : copy
يمكننا إنشاء مكرر قناة_املدخالت ألي نوع لديه عامل مدخالت (<<).
وباملثل ،يمكننا تعريف مكرر قناة_املخرجات طاملا أن النوع يملك عامل مخرجات (>>). •
ونظرًا ألن فئة عنرص_املبيعات تملك عوامل مدخالت ومخرجات ، •
فيمكننا استخدام مكررات املدخالت واملخرجات إلعادة كتابة برنامج متجر الكتب من الفقرة : 1.6 •
يتم تنفيذ حلقة whileحىت نصطدم بنهاية امللف على .cin •
داخل ، whileنتحقق مما إذا كان sumوالسجل الذي قرأناه للتو يشريان إلى نفس الكتاب. •
إذا كانا كذلك ،فإننا نضيف أحدث عنرص قرأه Sales_itemإلى . sum •
أما إذا كانت أرقام ISBNمختلفة ،فإننا نعني sumعلى ، out_iter •
واليت تطبع القيمة الحالية لـ sumمتبوعة بسطر جديد. •
بعد طباعة املجموع للكتاب السابق ،نقوم بتعيني sumنسخة من أحدث معاملة تمت قراءتها ونزايد املكرر ، •
والذي يقرأ املعاملة التالية.
تستمر الحلقة حىت يحدث خطأ أو نصطدم بنهاية امللف. •
قبل الخروج ،نتذكر أن نطبع القيم املرتبطة بآخر كتاب في املدخالت. •
تمارين القسم 10.4.2
التمرين :10.29
برنامج ا باستخدام مكررات القناة لقراءة ملف نيص في متجه من السالسل.
ً اكتب
التمرين :10.30
-استخدم مكررات القناة وفرزها ونسخها لقراءة سلسلة من األعداد الصحيحة من املدخالت القياسية وفرزها
-ثم إعادة كتابتها إلى املخرجات القيايس.
التمرين :10.31
-قم بتحديث الربنامج من التمرين السابق بحيث يطبع العنارص الفريدة فقط.
-يجب أن يستخدم برنامجك .unqiue_copy
التمرين :10.32
-أعد كتابة مشكلة مكتبة الكتب من الفقرة 1.6باستخدام متجه إلجراء املعامالت والخوارزميات املختلفة إلجراء
املعالجة.
-استخدم الفرز باستخدام دالة CompareIsbnالخاصة بك من الفقرة 10.3.1لرتتيب املعامالت بالرتتيب ،
-ثم استخدم إيجاد_ وتجميع_ لعمل املجموع.
التمرين :10.33
برنامجا يأخذ أسماء ملف مدخالت وملفي مخرجات.
ً -اكتب
-يجب أن يحتوي ملف املدخالت على أعداد صحيحة.
-باستخدام مكرر قناة_املدخالت ،اقرأ ملف املدخالت.
-باستخدام مكررات قناة_املخرجات ،اكتب األرقام الفردية في ملف املخرجات األول.
-يجب أن يتبع كل قيمة مسافة.
-اكتب األرقام الزوجية في امللف الثاني .يجب وضع كل من هذه القيم في سطر منفصل.
املكرر العكيس هو مكرر يجتاز حاوية للخلف ،بدءاً من آخر عنرص باتجاه األول.
يقلب مكرر عكيس معىن الزتايد (والتناقص). •
تزايد ( )it ++مكرر عكيس يحرك املكرر إلى العنرص السابق ؛ •
بينما تناقصه ( )it--يحرك املكرر إلى العنرص التالي. •
سيوضح الشكل 10.1العالقة بني هذه املكررات األربعة على متجه افرتايض يسمى .vec
)(Vec.cbegin )(Vec.cend
... ...
)(Vec.crend )(Vec.crbegin
على الرغم من أنه قد يبدو محريًا أن يتم عكس معاني عوامل الزتايد والتناقص ، •
إال أن القيام بذلك يتيح لنا استخدام الخوارزميات بشفافية ملعالجة حاوية نحو املقدمة أو نحو الخلف. •
فعلى سبيل املثال ،يمكننا فرز املتجه برتتيب تنازلي عن طريق تمرير زوج من املكررات العكسية إلى فرز : •
ليس من املستغرب أنه ال يمكننا تعريف مكرر عكيس إال من مكرر يدعم التناقص --كما يدعم الزتايد .++
فبعد كل يشء ،فالغرض منه تحريك املكرر للخلف عرب التسلسل. •
كل املكررات على الحاويات القياسية ما عدا القائمة اﻷمامية تدعم التناقص وكذلك الزتايد. •
مع ذلك ،فال تدعم مكررات قناة_املدخالت واملخرجات التناقص ،حيث ال يمكنها التحرك للخلف عرب القناة. •
ولذلك ،من غري الـممكن إنشاء مكرر عكيس من قائمة_أمامية أو من مكرر قناة. •
العالقة بني املكررات العكسية واملكررات األخرى
Relationship between Reverse Iterators and Other Iterators
لنفرتض أن لدينا سلسلة باسم سطر lineيحتوي على قائمة كلمات مفصولة بفواصل ،
ونريد أن نطبع الكلمة األولى فيها .فباستخدام إيجاد_ ، findستكون هذه املهمة سهلة :
إن كانت هناك فاصلة في ، lineستشري commaإلى تلك الفاصلة ؛ وإال فستشري إلى . line.cend •
عندما نطبع السلسلة من line.cbeginإلى ، comma •
فإننا سنطبع األحرف حىت الفاصلة ،أو السلسلة بأكملها إذا لم تكن هناك فاصلة. •
أما إذا أردنا الكلمة األخرية ،فيمكننا استخدام املكررات العكسية بدال ً من ذلك : •
ونظرًا ألننا مررنا crbeginو ، crendفإن هذا االستدعاء يبدأ بآخر حرف في lineويبحث للخلف. •
عند اكتمال ، findإن كانت هناك فاصلة ،فستشري rcommaإلى آخر فاصلة في السطر - •
أي أنها تشري إلى أول فاصلة تم العثور عليها في البحث العكيس. •
إذا لم تكن هناك فاصلة ،فـ rcommaستكون . line.crend •
يأتي الجزء املثري لالهتمام عندما نحاول أن نطبع الكلمة اليت وجدناها .الطريقة اليت تبدو واضحة
FIRST,MIDDLE,LAST
يوضح الشكل 10.2املشكلة :فنحن نستخدم املكررات العكسية ،واليت تعالج السلسلة نحو الخلف. •
لذا ،فإن جملة املخرجات تطبع من crbeginنحو الخلف عرب .line •
نريد أن نطبع بدال ً من ذلك من rcommaنحو اﻷمام حىت نهاية .line •
مع ذلك ،ال يمكننا استخدام rcommaمبارشة. •
ذلك املكرر هو مكرر عكيس ،مما يعين أنه يميض للخلف نحو بداية السلسلة. •
ما يتعني علينا القيام به هو تحويل rcommaمرة أخرى إلى مكرر عادي يتقدم عرب .line •
يمكننا القيام بذلك عن طريق استدعاء العضو : reverse_iterator •
يسمى ، baseوالذي يعطينا مكرره العادي املقابل : •
rcomma )(crbegin
بالنظر إلى نفس املدخالت السابقة ،سيطبع هذا البيان LASTكما هو متوقع.
توضح الكائنات املوضحة في الشكل 10.2العالقة بني املكررات العادية والعكسية. •
فمثالً ،يشري rcommaو rcomma.baseإلى عنارص مختلفة ،مثل line.crbeginو .line.cend •
هذه االختالفات رضورية للتأكد من أن نطاق العنارص ،سواء تمت معالجته ملقدمة أو لخلف ،هو نفسه. •
من الناحية الفنية ،فإن العالقة بني املكررات العادية والعكسية تستوعب خصائص نطاق-أيرس-شامل. •
املقصد هو أن كالً من [ )line.crbegin()، rcommaو [) rcomma.base()، line.cend •
سيشريان إلى العنارص نفسها في .line •
ولكي يحدث ذلك ،يجب أن ينتج عن rcommaو rcomma.baseمواضع متجاورة ، •
بدال ً من نفس املوضع ،كما يتوجب أن يؤدي crbeginو .cend •
ملحوظة
حقيقة أن املكررات العكسية تهدف إلى تمثيل النطاقات وأن هذه النطاقات غري متماثلة لها عواقب مهمة :
عندما نهئي أو نعني مكرراً عكسياً من مكرر عادي ،فإن املكرر الناتج ال يشري إلى نفس العنرص كاألصل.
التمرين :10.34
استخدم reverse_iteratorsلطباعة متجه برتتيب عكيس.
التمرين :10.35
قم اآلن بطباعة العنارص برتتيب عكيس باستخدام املكررات العادية.
التمرين :10.36
استخدم findإليجاد آخر عنرص في قائمة أعداد صحيحة بالقيمة .0
التمرين :10.37
-نظرًا لوجود متجه يحتوي على عرشة عنارص ،
-قم بنسخ العنارص من املواضع 3إلى 7برتتيب عكيس إلى قائمة.
10٫5هيكــــــلة الخــــــــــوارزميــــــــــات الشــــــــــاملة
10.5 Structure of Generic Algorithms
الخاصية األساسية ألي خوارزمية هي قائمة العمليات اليت تتطلبها من مكررها (مكرراتها).
• تتطلب بعض الخوارزميات ،كإيجاد_ ،فقط القدرة على الوصول إلى عنرص عرب املكرر ،وتزايد املكرر ،
ومقارنة مكررين من أجل التساوي.
• تتطلب خوارزميات أخرى ،كالفرز ،القدرة على القراءة والكتابة والوصول العشوائي للعنارص.
يتم تصنيف عمليات املكرر اليت تتطلبها الخوارزميات ، •
إلى خمس فئات مكرر iterator categoriesمدرجة في الجدول .10.5 •
تحدد كل خوارزمية أية نوع مكرر يتوجب توفريه لكل من معلمات مكررها. •
الطريقة الثانية هي تصنيف الخوارزميات (كما فعلنا في بداية هذا الفصل) •
حسب ما إذا كانت تقرأ أو تكتب أو تُعيد ترتيب العنارص في التسلسل. •
يغطي امللحق أ جميع الخوارزميات وف ًقا لهذا التصنيف . •
يحدد املعيار التصنيف اﻷدنى لكل معلمة مكرر للخوارزميات الشاملة والعددية.
فمثالً ،يتطلب إيجاد_ -الذي ينفذ اجتيازًا ملرور واحد ،للقراءة فقط عرب تسلسل -ح ًدا أدنى مكرر مدخالت. •
زوجا من املكررات اليت تكون على األقل مكررات_أمامية.
ً بينما تتطلب دالة استبدال_ •
وباملثل ،تتطلب replace_copyمكررات أمامية ألول مكررين لها. •
مكررها الثالث ،الذي يمثل وجهة ،يجب أن يكون على األقل مكرر مخرجات ،وهكذا. •
لكل معلمة ،يجب أن يكون املكرر على األقل بنفس قوة الحد األدنى املنصوص عليه. •
يعد تمرير مكرر بقوة أقل خطأ. •
تحذير
لن تشتكي العديد من املرتجمات عندما نمرر تصنيف مكرر خاطئ إلى خوارزمية.
قد نقوم بتعيني قيمة معينة ملكرر مخرجات مرة واحدة فقط. •
ومثل ُمكرِّرات املدخالت ،يمكن استخدام ُمكرِّرات املخرجات فقط لخوارزميات املرور الفردي. •
املكررات املستخدمة كوجهة عادة ما تكون مكررات مخرجات. •
مثالً ،معلمة نسخ_ copyالثالثة عبارة عن مكرر مخرجات .نوع مكرر قناة_املخرجات هو مكرر مخرجات. •
التمرين :10.38
قم بعمل قائمة لتصنيفات املكرر الخمس والعمليات اليت تدعمها كل منها.
التمرين :10.39
ما هو نوع مكرر القائمة؟ ماذا عن املتجه؟
التمرين :10.40
ما أنواع املُكرِّرات اليت تعتقد أن نسخ_ يتطلبها؟ ماذا عن عكس_ أو فريد_؟
املعلمة destهو مكرر يشري إلى وجهة يمكن للخوارزمية أن تكتب مخرجاتها عليه.
تفرتض الخوارزميات أنه من اآلمن كتابة عدد ما تحتاجه من العنارص .
تحذير
تفرتض خوارزميات تكتب إلى مكرر مخرجات أن الوجهة كبرية بما يكفي لتحمل املخرجات.
إذا كان destمكرراً يشري مبارشة لحاوية ،فإن الخوارزمية تكتب مخرجاتها على العنارص داخل الحاوية. •
شيوعا ،أن destترتبط بمكرر مدخالت أو مكرر قناة_مخرجات.
ً األكرث •
يضيف مكرر املدخالت عنارص جديدة إلى الحاوية ،مما يضمن أن هناك مساحة كافية. •
يكتب مكرر قناة_مخرجات على قناة مخرجات ، •
مرة أخرى لن تكون هناك أي مشكلة بغض النظر كم عدد العنارص اليت تمت كتابتها. •
Algorithms with a Second Input Sequence خوارزميات ذات تسلسل مدخالت ثان
الخوارزميات اليت تأخذ إما beg2بمفردها أو beg2مع end2تستخدمها لتشري إلى نطاق مدخالت ثانٍ .
تستخدم تلك الخوارزميات عاد ًة عنارص النطاق الثاني إلى جانب نطاق املدخالت إلجراء عملية حسابية. •
عندما تأخذ خوارزمية كالً من beg2مع ، end2فإن هذه املكررات تشري إلى نطاق ثان.
تماما:
ً تأخذ مثل هذه الخوارزميات نطاقني محددين •
نطاق املدخالت املشار إليه بواسطة [، )beg ، end •
ونطاق مدخالت ثانٍ يُشار إليه بـ [.)beg2 ، end2 •
الخوارزميات اليت تأخذ beg2فقط (بدون )end2تعامل beg2كأول عنرص في نطاق مدخالت ثانٍ .
لم يتم تحديد نهاية ذلك النطاق. •
بل ستفرتض أن حجم النطاق البادئ من beg2يكون على األقل بحجم النطاق املشار إليه بـ . beg, end •
تحذير
تفرتض الخوارزميات اليت تأخذ beg2وحده أن حجم التسلسل البادئ من beg2بحجم نطاق .beg, end
الخوارزميات اليت تأخذ محمولة تستخدمه بدال ً من العامل > أو == ،واليت ال تأخذ وسيطات أخرى ،عاد ًة ما تكون
زائدة-التعبئة.
• فإصدار منها يستخدم عامل نوع العنرص ملقارنة العنارص ؛
بينما يأخذ إصدار ثان معلمة إضافية عبارة عن محمولة تستخدمه مكان > أو == : •
كال االستدعاءان يعيدان ترتيب التسلسل املحدد عن طريق إزالة العنارص املكررة املتجاورة. •
األول يستخدم عامل نوع العنرص == للتحقق من التكرارات ؛ •
بينما يستدعي الثاني compليقرر ما إذا كان عنرصان متساويان. •
ونظرًا الختالف نسخيت الدالة من حيث عدد الوسيطات ، •
فال غموض محتمل بشأن الدالة اليت يتم استدعاؤها. •
تملك خوارزميات تأخذ قيمة عنرص عادة إصداراً ثانياً مسمى (غري زائد-التعبئة) يأخذ محمولة بدال ً من قيمة.
تلك الخوارزميات اليت تأخذ محمولة تملك امتداد _ ifملحقة : •
;)find(beg, end, val // find first instance of val in input range
find_if(beg, end, pred); // find first instance for which pred is true
تبحث هاتان الخوارزميتان عن أول مثيل لعنرص محدد في نطاق املدخالت. •
تبحث الخوارزمية أوجد_ findعن قيمة محددة ؛ •
بينما تبحث خوارزمية أوجد_إذا find_ifعن قيمة من أجل أن تُعيد predلها قيمة غري صفرية. •
افرتاضياً ،تكتب الخوارزميات اليت تُعيد ترتيب عنارصها العنارص املرتبة مرة أخرى على نطاق املدخالت املحدد.
ثانيا يكتب على وجهة مخرجات محددة.
ً إصدارا
ً توفر هذه الخوارزميات •
وكما رأينا ،فإن الخوارزميات اليت تكتب على وجهة تُلحق _ copyإلى أسمائها : •
توفر بعض الخوارزميات كالً من إصداري _ copyو _ .ifتأخذ هذه اإلصدارات مكرر وجهة ومحمولة :
// removes odd elements from v1
;)} ;remove_if(v1.begin(), v1.end(),[](int i) { return i % 2
// copies only even elements from v1 into v2; v1 is unchanged
remove_copy_if(v1.begin(), v1.end(), back_inserter(v2),
;)} ;[](int i) { return i % 2
فرديا.
ً يستخدم كال االستدعاءين المدا لتحديد ما إذا كان العنرص •
في الحالة األولى ،نقوم بإزالة العنارص الفردية من تسلسل املدخالت نفسه. •
أما في الثانية ،فنقوم بنسخ العنارص غري الفردية (أو الزوجية) من نطاق املدخالت إلى اإلصدار .2 •
التمرين :10.41
بناء على أسماء الخوارزمية والوسيطات فقط ،
ً -
-قم بوصف العملية اليت تنفذها كل من خوارزميات املكتبة التالية:
;)replace(beg, end, old_val, new_val
;)replace_if(beg, end, pred, new_val
;)replace_copy(beg, end, dest, old_val, new_val
;)replace_copy_if(beg, end, dest, pred, new_val
10٫6خــــــــــوارزميــــــــــات الحــــــاوية الخــــــــــاصة
10.6 Container-Specific Algorithms
أفضل املمارسات
ينبغي استخدام إصدارات أعضاء القائمة بتفضيل على الخوارزميات الشاملة للقائمة والقوائم اﻷمامية.
)lst.splice(args) or flst.splice_after(args
معظم الخوارزميات الخاصة بالقائمة متشابهة -لكن ليست متطابقة -مع نظرياتها الشاملة.
مع ذلك ،فإن االختالف املهم للغاية بني اإلصدارات الخاصة بالقائمة واإلصدارات الشاملة هو : •
أن إصدارات القائمة تغري الحاوية األساسية. •
فعلى سبيل املثال ،يزيل إصدار إزالة_ للقائمة العنارص املشار إليها. •
كما يزيل إصدار فريد_ للقائمة العنارص املتكررة الثانية والالحقة. •
التمرين :10.42
أعد تنفيذ الربنامج الذي حذف الكلمات املكررة اليت كتبناها في الفقرة 10.2.3لتستخدم قائمة بدال ً من املتجه.
ملخــــــــــص الفصــــــــــل
Chapter Summary
تعرف املكتبة القياسية ما يقارب من 100خوارزمية مستقلة عن النوع تعمل على التسلسالت.
ّ
يمكن أن تكون التسلسالت عنارص في نوع مكتبة حاوية ،أو مصفوفة مدمجة ، •
أو يتم إنشاؤها (على سبيل املثال) عن طريق القراءة أو الكتابة على قناة. •
يتم تصنيف املكررات إلى واحدة من خمس فئات اعتما ًدا على العمليات اليت تدعمها.
فئات املكرر هي املدخالت واملخرجات واﻷمامية وثنائية االتجاه والوصول العشوائي. •
ينتمي املكرر إلى فئة معينة إذا كان يدعم العمليات املطلوبة لفئة املكرر هذه. •
ال تغري الخوارزميات بشكل مبارش أبداً حجم التسلسالت اليت تعمل عليها.
قد تقوم بنسخ العنارص من موضع إلى آخر ، •
لكن لن يمكنها إضافة عنارص أو إزالتها بشكل مبارش. •
وعلى الرغم من أن الخوارزميات ال يمكنها إضافة عنارص إلى تسلسل ،إال أن مكرر اإلدراج قد يقوم بذلك.
مكرر املدخالت مرتبط بحاوية. •
وعندما نقوم بتعيني قيمة نوع عنرص حاوية على مكرر إدراج ، •
يضيف املكرر العنرص املحدد إلى الحاوية. •
ُمدرج_خلف :مكيف مكرر يأخذ إشارة إلى الحاوية ويقوم بإنشاء مكرر إدراج
back_inserter
يستخدم دفع_للخلف push_backإلضافة عنارص إلى الحاوية املحددة.
ربط_ :دالة مكتبة تربط وسيطة واحدة أو أكرث بتعبري قابل لالستدعاء.
bind
يتم تعريف ربط_ في العنوان الدالي.
كائن قابل لالستدعاء :كائن يمكن أن يظهر كمعامل يسار لعامل االستدعاء.
callable object تعرف عامل استدعاء دالة زائد التعبئة ،
املؤرشات للدوال ،و المدا_ ،وكائنات فئة ّ
كلها كائنات قابلة لالستدعاء.
قائمة_التقاط:
capture list جزء من تعبري المدا يعرف متغريات من دالة متضمنة يمكن لتعبري المدا الوصول
إليها.
دالة مكتبة تقوم بإعادة كائن قابل للنسخ يحتوي على مرجع لكائن ثابت من نوع ال
cref
يمكن نسخه.
ُم درج_مقدمة :مكيف مكرر ،عند إعطائه حاوية ،يولد مكرر مدخالت يستخدم
front_inserter
دفع_للمقدمة push_frontإلضافة عنارص إلى بداية تلك الحاوية.
output iterator مكرر مخرجات :مكرر يمكنه الكتابة على العنارص ،ولكن ليس بالرضورة قراءتها.
نوعا يمكن تحويله إلى منطقي.
محمولة :دالة تُعيد ً
غالبا ما تستخدم بواسطة الخوارزميات الشاملة الختبار العنارص.
ً
predicate
املحموالت املستخدمة من قبل املكتبة هي
إما أحادية (تأخذ وسيطة واحدة) أو ثنائية (تأخذ وسيطتني).
ref دالة مكتبة تنئش كائنًا قاباًل للنسخ من مرجع إلى كائن من نوع ال يمكن نسخه.