Professional Documents
Culture Documents
C++ Primer, Fifth Edition ترجمتي (الفصل3 الثالث)
C++ Primer, Fifth Edition ترجمتي (الفصل3 الثالث)
الـمحتويات
Contents
معرفة مبارشة في لغة يس.++ األنواع املدمجة اليت غطيناها في الفصل الثاني هي أنواع ّ
• تمثل هذه األنواع أقساما موجودة في معظم أجهزة الكمبيوتر ،مثل األرقام أو األحرف.
تعرف املكتبة القياسية عد ًدا من األنواع اإلضافية ذات املستوى األعلى واليت ال تنفذها أجهزة الكمبيوتر
ّ •
عاد ًة بشكل مبارش.
في هذا الفصل ،سوف نقدم اثنني من أهم أنواع املكتبة :السلسلة stringواملتجه .vector
السلسلة عبارة عن تسلسل متغري الطول من األحرف. •
أما املتجه فيحمل سلسلة متغرية الطول من كائنات نوع معني. •
أيضا نوع املصفوفة املدمجة.
سنغطي ً •
ومثل األنواع املدمجة األخرى ،تمثل املصفوفات أقسام العتاد الصلب. •
نتيجة لذلك ،تكون املصفوفات أقل مالءمة لالستخدام من أنواع مكتبة السلسلة واملتجهات. •
املعرفة في املكتبة.
ّ وقبل البدء في استكشاف أنواع املكتبة ،سنلقي نظرة على آلية لتبسيط الوصول إلى األسماء
. 3٫1إعالنات مساحـــــة اﻻسم Using
3.1. Namespace using Declarations
حىت اآلن ،أشارت برامجنا رصاح ًة إلى أن كل اسم مكتبة نستخدمه موجود في مساحة االسم .std
فعلى سبيل املثال ،للقراءة من املدخالت القياسية ،نكتب .std::cin •
تستخدم هذه األسماء عامل النطاق ( ، )::والذي يخرب بأن املرتجم يجب أن يبحث في نطاق املعامل األيرس •
عن اسم املعامل األيمن.
وهكذا ،يخرب std::cinإننا نريد استخدام اسم cinمن مساحة االسم .std •
يمكن أن تكون اإلشارة إلى أسماء املكتبة باستخدام هذا الرتمزي مرهقة.
لحسن الحظ ،هناك طرق أسهل الستخدام أعضاء مساحة االسم. •
الطريقة األكرث أما ًنا هي إعالن .usingتغطي الفقرة 18.2.2طريقة أخرى الستخدام األسماء من مساحة •
االسم.
يتيح لنا إعالن usingاستخدام اسم مساحة اسم دون تقييد االسم ببادئة: :اسم_مساحة_اسم .إعالن using
يكون بصيغة:
;using namespace::name
>#include <iostream
//using declaration; when we use name cin, we get one from namespace std
;using std::cin
{ )(int main
;int i
;cin >> i // ok: cin synonym for std::cin
cout << i; // error: no using declaration; we must use full name
std::cout << i; // ok: explicitly use cout from namespace std
;return 0
}
على سبيل املثال ،سنعيد كتابة الربنامج من فقرة 1.2بإعالنات usingألسماء املكتبة اليت تستخدمها:
>#include <iostream
// using declarations for names from standard library
;using std::cin ;using std::cout ;using std::endl
{ )(int main
;cout << "Enter two numbers:" << endl
;int v1, v2
;cin >> v1 >> v2
cout << "The sum of " << v1 << " and " << v2
;<< " is " << v1 + v2 << endl
;return 0
}
إعالنات usingلـ cin ، cout ، endlتعين أنه يمكننا استخدام هذه األسماء بدون البادئة .std: : •
تذكر أن برامج يس ++حرة الشكل ،لذلك يمكننا وضع كل إعالن usingفي سطر خاص به أو دمج عدة •
منها في سطر واحد.
أهم جزء هو أنه يجب أن يكون هناك إعالن usingلكل اسم نستخدمه ،وأن ينتهي كل منها بفاصلة •
منقوطة.
يرسد الجدول A-1في امللحق Aقائمة األسماء والعناوين املقابلة ألسماء املكتبة القياسية اليت نستخدمها في هذا
الكتاب التمهيدي.
تحذير
ينبغي أن يدرك القراء أن عليهم إضافة #includeوإعالنات usingاملناسبة ألمثلتنا قبل تجميعها.
>#include <string
;using std::string
ملحوظة
يمكننا بشكل افرتايض تهيئة سلسلة ،ما يؤدي إلى إنشاء سلسلة فارغة ؛ أي سلسلة بدون أحرف. •
عندما نوفر حرفية سلسلة ،يتم نسخ األحرف من قيم ذلك الحرفي -حىت وإن لم يتضمن الحرف الخالي في •
نهاية الحرفي -إلى السلسلة املنشأة حديثًا.
وعندما نوفر عد ًدا وحر ًفا ،فإن السلسلة تحتوي على عدة نسخ من الحرف املحدد. •
Direct and Copy Forms of Initialization أشكال التهيئة املبارشة وتهيئة النسخ
في الفقرة 2.2.1رأينا أن لغة يس ++تملك عدة صيغ مختلفة من التهيئة.
باستخدام السالسل ،يمكننا البدء في فهم كيفية اختالف هذه النماذج عن بعضها. •
عندما نقوم بتهيئة متغري باستخدام = ،فإننا نطلب من املرتجم نسخ تهيئة الكائن عن طريق نسخ املُهئي •
على الجانب األيمن إلى الكائن الذي يتم إنشاؤه.
عدا ذلك ،عندما نحذف = ،نستخدم التهيئة املبارشة. •
عندما يكون لدينا ُمهئي واحد ،يمكننا استخدام إما شكل التهيئة املبارشة أو تهيئة النسخة. •
وعندما نقوم بتهيئة متغري على أكرث من قيمة واحدة ،كما هو الحال في تهيئة s4أعاله ، •
يجب أن نستخدم الشكل املبارش للتهيئة: •
عندما نريد استخدام عدة قيم ،يمكننا استخدام صيغة التهيئة بشكل غري مبارش عن طريق إنشاء كائن (مؤقت) بشكل
رصيح لنسخه:
يقوم ُمهئي s8بإنشاء سلسلة - string(10, ‘c’) -بالحجم املحدد وقيمة الحرف ثم ينسخ تلك القيمة إلى
.s8سيبدو األمر كما لو كنا قد كتبنا
وبالرغم من أن الكود املستخدم لتهيئة s8رشعي ،إال أنه أقل قابلية للقراءة وال يقدم أي مزية تعويضية على
الطريقة اليت هيأنا بها .s7
// Note: #include and using declarations must added to compile this code
int main() {
string s; // empty string
cin >> s; // read a whitespace-separated string into s
cout << s << endl; // write s to output
return 0;
}
إذا أعطينا هذا اإلصدار من الربنامج نفس املدخالت ! Hello World ،فستكون مخرجاتنا ""! HelloWorld
{ )(int main
;string word
)while (cin >> word // read until end-of-file
cout << word << endl; // write each word followed by new line
;return 0
}
في هذا الربنامج ،نقرأ إلى سلسلة ،وليس عدد صحيح. •
عدا ذلك ،يتم تنفيذ رشط whileبشكل مشابه لذلك املوجود في برنامجنا السابق. •
يخترب الرشط القناة بعد اكتمال القراءة. •
فإن كانت القناة صالح ًة -لم تصل لنهاية امللف أو تواجه مدخالً غري صالح - •
فسيتم تنفيذ جملة .while •
تطبع الجملة القيمة اليت نقرأها على املخرجات القياسية. •
وبمجرد أن نصل نهاية امللف (أو نواجه مدخالً غري صالح) ،فإننا نخرج من .while •
فمثالً ،يمكننا إعادة كتابة الربنامج السابق الذي يكتب كلمة واحدة كل سطر لكتابة سطر في املرة بدال ً من ذلك :
{ )(int main
;string line
// read input line at time until end-of-file
))while (getline(cin, line
;cout << line << endl
;return 0
}
خاصا بنا.
ً ونظرًا ألن السطر ال يحتوي على سطر جديد ،يجب أن نكتب سطرًا •
كالعادة ،نستخدم endlإلنهاء السطر الحالي ومسح املخزن املؤقت. •
ملحوظة
يتم تجاهل السطر الجديد الذي يتسبب في إعادة getline؛ ال يتم تخزين السطر الجديد في السلسلة.
The string empty and size Operations عمليات الفراغ والحجم للسلسلة
تقوم الدالة emptyبما يتوقعه املرء :إعادة منطقي يشري إلى ما إذا كانت السلسلة فارغة.
ومثل العضو isbnفي عنرص املبيعات ،الدالة emptyهي دالة عضو في عنوان سلسلة. •
الستدعاء هذه الدالة ،نستخدم عامل النقطة لتحديد الكائن الذي نريد تشغيل الدالة emptyعليه. •
يمكننا استخدام sizeلطباعة األسطر اليت يزيد طولها عن 80حر ًفا فقط :
;string line
// read input line at time and print lines that longer than 80 characters
))while (getline(cin, line
)if (line.size() > 80
;cout << line << endl
قد يكون من املنطقي أن نتوقع أن sizeتعيد عدداً صحيحاً أو -بالتفكري في الفقرة – 2.1.1بال_إشارة.
بدال ً من ذلك ،يقوم sizeبإعادة قيمة .string::size_type •
هذا النوع سيتطلب القليل من الرشح. •
نوعا بال_إشارة ،فمن الرضوري أن نتذكر أن التعبريات اليت تمزج البيانات ذات
ونظرًا ألن sizeتعيد ً •
اﻹشارة مع الال_إشارة قد تكون لها نتائج مفاجئة.
تقريبا أن
ً فعلى سبيل املثال ،إذا كانت nعبارة عن عدد صحيح intتحتوي على قيمة سالبة ،فمن املؤكد •
s.size() < nسيتم تقييمها صحيحة.
سينتج عن ذلك تقييم صحيح ألن القيمة السالبة في nستتحول إلى قيمة كبرية بال_إشارة. •
تلميح
يمكنك تجنب املشاكل الناجمة عن التحويل بني الال_إشارة والعدد الصحيح int
وذلك عن طريق عدم استخدام األعداد الصحيحة intsفي تعبريات تستخدم .)( size
;string st1(10, 'c'), st2 // st1 is cccccccccc; st2 empty string
;st1 = st2 // assignment: replace contents of st1 with copy of st2
// both st1 and st2 now empty string
يؤدي جمع سلسلتني إلى إنتاج سلسلة جديدة تمثل سلسلة الجهة اليرسى متبوعة بالسلسلة اليمىن.
أي عندما نستخدم عامل الجمع ( )+على السالسل ، •
تكون النتيجة سلسلة جديدة تكون أحرفها نسخة من تلك املوجودة في املعامل األيرس متبوع ًة بتلك •
املوجودة في املعامل األيمن.
يلحق عامل التعيني املركب (= )+املعامل األيمن إلى السلسلة املوجودة على اليسار:
ونظرًا ألنه يمكننا استخدام هذه الحرفيات حيث يُتوقع وجود سلسلة ،يمكننا إعادة كتابة الربنامج السابق على
النحو التالي :
عندما نمزج سالسل مع سلسلة أو حرفيات حرف ،يجب أن يكون نوع سلسلة معامالً واحداً على األقل لكل عامل
جمع : +
تتضمن عمليات تهيئة s4و s5عملية واحدة فقط لكل منهما ، •
لذلك من السهل معرفة ما إذا كانت التهيئة رشعية أم ال. •
معا تعابري املدخالت أو
قد تبدو بداية تهيئة s6مفاجئة ،لكنها تعمل بنفس الطريقة اليت نربط بها ً •
املخرجات.
فمجموعات التهيئة هذه تشبه :
يعيد التعبري الفرعي "،" + s1سلسلة تشكل املعامل األيرس للعامل +الثاني.
يبدو األمر كما لو كنا قد كتبنا
من ناحية أخرى ،فإن تهيئة s7غري رشعية ،واليت يمكننا رؤيتها إذا قمنا بوضع أقواس في التعبري:
string s7 = ("hello" + ", ") + s2; // error: can't add string literals
اآلن يجب أن يكون من السهل مالحظة أن التعبري الفرعي األول يضيف حرفييت سلسلة. •
ال توجد طريقة للقيام بذلك ،وبالتالي فإن الجملة خاطئة. •
تحذير
ألسباب تاريخية ،وللتوافق مع لغة ، Cال تعترب حرفيات السلسلة سالسل املكتبة القياسية.
من املهم أن تتذكر أن هذه أنواع مختلفة عندما تستخدم حرفيات سلسلة وسالسل املكتبة.
قسم التدريبات 3.2.2
التمرين :3.2
برنامجا لقراءة سطر مدخالت قياسية في املرة الواحدة.
ً -اكتب
-قم بتعديل برنامجك لقراءة كلمة في الوقت الواحد.
التمرين :3.3
-ارشح كيف يتم التعامل مع أحرف املسافات البيضاء في عامل مدخالت السلسلة وفي دالة .getline
التمرين :3.4
برنامجا يقرأ سلسلتني وقدم تقريراً ما إذا كانت السالسل متساوية.
ً -اكتب
-إن لم تكن ،فقدم تقريراً أيهما أكرب.
-اآلن ،قم بتغيري الربنامج لتقرير ما إذا كانت السالسل لها نفس الطول ،
-إذا لم تكن ،فقدم تقريراً بالسلسلة األطول.
التمرين :3.5
برنامجا يقرأ سالسل من املدخالت القياسية ،ودمج ما يقرأ إلى سلسلة واحدة كبرية.
ً -اكتب
-اطبع السلسلة املدمجة.
-بعد ذلك ،قم بتغيري الربنامج لفصل سالسل املدخالت املجاورة بمسافة.
يتضمن أحد أجزاء هذا النوع من املعالجة كيفية وصولنا إلى األحرف نفسها.
نحتاج أحيا ًنا إلى معالجة كل حرف. •
وفي أحيان أخرى نحتاج إلى معالجة حرف معني فقط ، •
أو التوقف عن املعالجة بمجرد استيفاء بعض الرشوط. •
ليتضح أن أفضل طريقة للتعامل مع هذه الحاالت تتضمن أقسام لغة ومكتبة مختلفة. •
true if c whitespace
isspace(c)
(i.e. space, tab, vertical tab, return, newline or formfeed)
name.h من العناوين ﻻ إصداراتc-name إصدارات++ ينبغي أن تستخدم برامج يس، في العادة •
.std بهذه الطريقة يتم العثور على األسماء من املكتبة القياسية باستمرار في مساحة االسم •
العبء على املربمج لتذكر أسماء املكتبة املوروثة من يس واليت هي فريدة منh. يضع استخدام عناوين •
.++نوعها لـ يس
وكمثال بسيط ،يمكننا استخدام forللنطاق لطباعة كل حرف من سلسلة على سطر مخرجات خاص به :
كمثال أكرث تعقي ًدا إلى حد ما ،سنستخدم forالنطاق ودالة ispunctلحساب عدد أحرف الرتقيم في سلسلة:
نستخدم هنا نوع-معلن decltypeلإلعالن عن العداد الخاص بنا .punct_cnt ، •
نوعه هو النوع الذي يتم إعادته عند استدعاء ، s.sizeوهو .string::size_type •
نستخدم forالنطاق ملعالجة كل حرف في السلسلة. •
هذه املرة نتحقق مما إذا كان كل حرف عبارة عن إحدى عالمات الرتقيم. •
إن كان األمر كذلك ،فإننا نستخدم عامل الزتايد ++إلضافة 1إلى العداد. •
عندما يكتمل النطاق ،نطبع النتيجة. •
إن أردنا تغيري قيمة أحرف في سلسلة ،يجب أن نعرف متغري الحلقة كنوع مرجعي.
تذكر أن املرجع هو مجرد اسم آخر لكائن معني. •
مرجعا كمتغري تحكم لدينا ،فإن هذا املتغري مرتبط بكل عنرص في التسلسل بدوره.
ً فعندما نستخدم •
وباستخدام املرجع ،يمكننا تغيري الحرف الذي يرتبط به املرجع. •
لنفرتض أنه بدال ً من حساب عالمات الرتقيم ،أردنا تحويل سلسلة إلى حالة األحرف الكبرية.
فللقيام بذلك ،يمكننا استخدام دالة ، toupperواليت تأخذ حر ًفا وتعيد اإلصدار الكبري من ذلك الحرف. •
لتحويل السلسلة بأكملها ،نحتاج إلى استدعاء toupperعلى كل حرف وإعادة النتيجة إلى هذا الحرف:
!!!HELLO WORLD
يعمل forالنطاق بشكل جيد عندما نحتاج إلى معالجة كل حرف .ومع ذلك ،
أحياناً نحتاج إلى الوصول إلى حرف فقط أو الوصول إلى عدة أحرف للتوصل إلى بعض الرشوط. •
فعلى سبيل املثال ،قد نرغب في كتابة الحرف األول فقط باألحرف الكبرية أو الكلمة األولى فقط في •
السلسلة.
ملحوظة
يجب أن تكون القيم اليت نستخدمها لفهرسة سلسلة أكرب من أو تساوي الصفر و أصغر من ().size
معرف.
َّ ستكون نتيجة استخدام فهرس خارج هذا النطاق سلوكاً غري
معرف.
َّ ضمنيا ،تعد فهرسة سلسلة فارغة سلوكاً غري
ً
يُشار إلى القيمة املوجودة في الفهرسة بـ"شفرة-فرعية "subscriptأو "فهرس ."index •
يمكن أن يكون الفهرس الذي نقدمه أي تعبري ينتج عنه قيمة عدد صحيح .مع ذلك ، •
إذا كان فهرسنا يحتوي على نوع ذي إشارة ،فسيتم تحويل قيمته إلى نوع بال_إشارة يمثله •
.string::size_type
يستخدم املثال التالي عامل الفهرسة لطباعة أول حرف في السلسلة:
وطاملا أن السلسلة ليست ثابتة ،فيمكننا تعيني قيمة جديدة على الحرف الذي يعيده عامل الفهرسة.
فعلى سبيل املثال ،يمكننا استبدال أول حرف بحرف كبري على النحو التالي:
Some string
Using a Subscript for Iteration استخدام فهرسة للتكرار
كمثال آخر ،سنقوم بتغيري أول كلمة في sإلى أحرف كبرية بالكامل:
SOME string
تحذير
املكتبة غري مطالبة بفحص قيمة الفهرسة .نتيجة استخدام فهرس خارج النطاق سلوك غري معرف
رقما بني 0و 15ونريد توليد التمثيل السدايس العرشي لهذا الرقم.
كمثال ،لنفرتض أن لدينا ً
عرشيا:
ً سداسيا
ً "رقما"
ً يمكننا القيام بذلك باستخدام سلسلة نصية تتم تهيئتها الستيعاب 16
12 0 5 15 8 15
نبدأ بتهيئة hexdigitsعلى حفظ األرقام السدايس عرشية من 0إلى .F •
سنجعل هذه السلسلة ثابتة const-ألننا ال نريد تغيري تلك القيم. •
داخل الحلقة ،نستخدم قيمة مدخالت nلفهرسة .hexdigitsقيمة ] hexdigits[nهي الحرف الذي •
يظهر في املوضع nباألرقام السداسية.
مثالً ،إذا كان nتساوي ، 15فإن النتيجة هي F؛ إذا كانت ، 12تكون النتيجة C؛ وهلم جرا. •
نلحق هذا الرقم بالنتيجة ،ونطبعه بمجرد قراءة كل املدخالت. •
عندما نستخدم رمز فهرسة ،يجب أن نفكر في كيفية علمنا أنه ضمن النطاق.
في هذا الربنامج ،يعد رمزنا nمن نوع ، string::size_typeوهو كما نعلم نوع بال_إشارة. •
ونتيجة لذلك ،نعلم أنه تم ضمان أن تكون قيمة nأكرب من أو تساوي .0 •
فكل ما تبقى هو أن نتحقق أنها أقل من حجم hexdigitsقبل أن نستخدم nلفهرسة اﻷرقام. •
التمرين :3.7
-ماذا سيحدث إن قمت بتعريف متغري التحكم في الحلقة في التمرين السابق كنوع حرف char؟
-توقع النتائج ثم قم بتغيري برنامجك الستخدام حرف ملعرفة ما إذا كنت على حق.
التمرين :3.8
-أعد كتابة الربنامج في التمرين األول ،أوال ً باستخدام whileومرة أخرى باستخدام حلقة forالتقليدية.
-أي من الطرق الثالثة تفضل وملاذا؟
التمرين :3.9
-ماذا يفعل الربنامج التالي؟ هل الربنامج صحيح؟
-إذا لم يكن كذلك ،فلماذا؟
;string s
;cout << s[0] << endl
التمرين :3.10
برنامج ا يقرأ سلسلة من األحرف بما في ذلك عالمات الرتقيم ويكتب ما تمت قراءته لكن مع إزالة عالمات
ً -اكتب
الرتقيم.
التمرين :3.11
-هل forالنطاق التالية رشعية؟
-إن كانت كذلك ،فما هو نوع C؟
;"!const string s = "Keep out
… *for (auto &c : s) { / } */
. 3٫2نـــــوع مكتبة املتجـــــه
3.3. Library vector Type
>#include <vector
;using std::vector
في حالة املتجه ،فإن املعلومات اإلضافية اليت نقدمها هي نوع الكائنات اليت سيحملها املتجه :
في هذا املثال ،يُنئش املرتجم ثالثة أنواع ممزية من قالب املتجه: •
متجه من نوع عدد صحيح < >intومتجه من نوع عنرص املبيعات <>Sales_item •
ومتجه من نوع <متجه من نوع سلسلة <.>string •
ملحوظة
املتجه عبارة عن قالب وليس نوع .يجب أن تتضمن األنواع اليت يتم توليدها من املتجه نوع العنرص ،
على سبيل املثال ،متجه <.>int
جدير بالذكر أن اإلصدارات السابقة من يس ++استخدمت بناء جملة مختلفة قليالً لتعريف متجه تتكون عنارصه من
نوع متجهات (أو نوع قالب آخر).
فقد كان علينا توفري مسافة بني قوس إغالق الزاوية للمتجه الخارجي ونوع عنرصه ؛ بحيث يكون __
> >vector<vector<int
بدال ً من ___
>>vector<vector<int
تحذير
قد تتطلب بعض املرتجمات تعريفات النمط القديم ملتجه من املتجهات ،مثالً :
> >vector<vector<int
شيوعا
ً كحال أي نوع فئة ،يتحكم قالب املتجه في كيفية تعريف املتجهات وتهيئتها .يرسد الجدول 3.4أكرث الطرق
لتعريف املتجهات.
نعرف املتجه.
أيضا توفري القيمة (القيم) األولية للعنرص (العنارص) عندما ّ
يمكننا ً
على سبيل املثال ،يمكننا نسخ عنارص من متجه آخر. •
عندما نقوم بنسخ متجه ،يكون كل عنرص في املتجه الجديد نسخة من العنرص املقابل في املتجه األصلي. •
ويجب أن يكون املتجهان من نفس النوع: •
هناك طريقة أخرى لتوفري قيم العنارص ،وهي أنه بموجب املعيار الجديد ،يمكننا تهيئة متجه تهيئة-قائمة على
صفر أو أكرث من قيم العنارص األولية املحاطة بأقواس معقوفة :
يتكون املتجه الناتج من ثالثة عنارص ؛ األول يحمل السلسلة " ، "aوالثاني يحمل " ، "anواألخري هو "."the
في حاالت قليلة ،يعتمد معىن التهيئة على ما إذا كنا نستخدم األقواس املتعرجة أو األقواس العادية لتمرير املُهئي.
• على سبيل املثال ،عندما نقوم بتهيئة متجه < >intمن قيمة intواحدة ،
فقد تمثل هذه القيمة حجم املتجه أو قد تكون قيمة عنرص. •
حجما وقيمة أولية ،
ً وباملثل ،إذا قدمنا قيميت intبالضبط ،فقد تكون هذه القيم •
قيما ملتجه ثنائي العنرص.
أو يمكن أن تكون ً •
نحدد املعىن الذي ننوي استخدامه سواء استخدمنا األقواس أو األقواس املتعرجة :
عندما نستخدم األقواس العادية ،فإننا نخرب بأن القيم اليت نوفرها يجب استخدامها لبناء الكائن. •
بالتالي ،يستخدم v1و ُ v3مهيئهما لتحديد حجم املتجه ،وحجمه وقيم عنارصه ،على التوالي. •
وعندما نستخدم األقواس املتعرجة ، }...{ ،فإننا نخرب بأنه إن أمكن ،نريد إعداد تهيئة الكائن كقائمة. •
بمعىن ،إذا كانت هناك طريقة الستخدام القيم املوجودة داخل األقواس املتعرجة كقائمة من ُمهئي العنارص ، •
فستقوم الفئة بذلك.
وفقط إذا لم يكن من املمكن تهيئة الكائن كقائمة ،فسيتم النظر في الطرق األخرى لتهيئة الكائن. •
يمكن استخدام القيم اليت نوفرها عند تهيئة v2و v4كقيم للعنارص. •
تتم تهيئة هذه الكائنات كقائمة ؛ ﻷن املتجهات الناتجة لها عنرص واحد وعنرصين ،على التوالي. •
في هذه الحالة ،ال يوجد التباس حول ما إذا كان سيتم تهيئة قائمة العنارص أو إنشاء متجه بالحجم املحدد:
على الرغم من أننا استخدمنا األقواس في جميع هذه التعريفات باستثناء واحد ، •
إال أن املتجه v5فقط هي اليت تمت تهيئتها كقائمة. •
من أجل تهيئة متجه كقائمة ،يجب أن تتطابق القيم املوجودة داخل األقواس مع نوع العنرص. •
فال يمكننا استخدام intلتهيئة سلسلة ، •
ولذلك ال يمكن أن تكون ُمهيئات v7و v8مهيئات لعنرص. •
إن كانت تهيئة القائمة غري ممكنة ،يبحث املرتجم عن طرق أخرى لتهيئة الكائن على القيم املحددة. •
فمثال:
فعلى سبيل املثال ،قد نقرأ املدخالت ،ونخزن القيم اليت نقرأها في املتجه:
// read words from standard input and store them as elements in vector
;string word
;vector<string> text // empty vector
{ )while (cin >> word
;)text.push_back(word // append word to text
}
مرة أخرى ،نبدأ بمتجه فارغ في البداية .هذه املرة ،نقرأ ونخزن عد ًدا غري معروف من القيم في .text
تنمو املتجهات بكفاءة vectors Grow Efficiently مفهوم رئييس :
يتطلب املعيار أن تطبيقات املتجه يمكن أن تضيف عنارص بكفاءة في وقت التشغيل. •
فغالبا ما يكون من غري الرضوري -وقد يؤدي إلى ضعف في األداء -
ً ونظرًا ألن املتجهات تنمو بكفاءة ، •
تحديد متجه بحجم معني.
االستثناء من هذه القاعدة هو إن كانت جميع العنارص تحتاج بالفعل إلى نفس القيمة. •
أما إذا كانت هناك حاجة إلى قيم عنارص مختلفة ، •
فعادة ما يكون من األفضل تحديد متجه فارغ وإضافة عنارص عندما تصبح القيم اليت نحتاجها معروفة •
في وقت التشغيل.
عالوة على ذلك ،كما سرنى في فقرة ، 9.4يوفر املتجه إمكانيات تتيح لنا زيادة تحسني أداء وقت •
التشغيل عندما نضيف عنارص.
يختلف البدء بمتجه فارغ وإضافة عنارص في وقت التشغيل بشكل واضح عن كيفية استخدامنا •
للمصفوفات املدمجة في لغة يس وفي معظم اللغات األخرى.
خصوصاً ،إن كنت معتا ًدا على يس أو جافا ،قد تتوقع أن األفضل تحديد املتجه بحجمه املتوقع. •
لكن في الواقع ،العكس هو الصحيح في العادة. •
حقيقة أنه يمكننا بسهولة وكفاءة إضافة عنارص إلى متجه يبسط إلى حد كبري العديد من مهام الربمجة.
الزتاما جدي ًدا على برامجنا:
ً ومع ذلك ،فإن هذه البساطة تفرض •
حيث يجب أن نتأكد من صحة أي حلقات نكتبها حىت لو غريت الحلقة حجم املتجه. •
وضوحا كلما تعلمنا املزيد عن
ً ستصبح اآلثار األخرى اليت تنجم عن الطبيعة الحيوية للمتجهات أكرث •
استخدامها.
ومع ذلك ،هناك تأثري واحد جدير باملالحظة بالفعل: •
ألسباب سنستكشفها في فقرة ، 5.4.3لن يمكننا استخدام forالنطاق إذا كانت بنية الحلقة تضيف عنارص •
إلى املتجه.
تحذير
يجب أال تغري بنية forالنطاق حجم التسلسل الذي يتم التكرار عليه.
نتوصل إلى عنارص املتجه بنفس الطريقة اليت نتوصل بها إلى أحرف في سلسلة: •
من خالل موضعها في املتجه. •
على سبيل املثال ،يمكننا استخدام forالنطاق ملعالجة جميع العنارص في املتجه:
;}vector<int> v{1,2,3,4,5,6,7,8,9
)for (auto &i : v )// for each element in v (note: i reference
;i *= i // square element value
)for (auto i : v // for each element in v
;" " << cout << i // print element
;cout << endl
تترصف األعضاء () emptyو () sizeكما تترصف أعضاء السلسلة املقابلة :
تعيد emptyمنطقيا ،يشري إلى ما إذا كان املتجه يحتوي على أي عنارص ، •
وتعيد sizeعدد العنارص في املتجه. •
املعرف بواسطة نوع املتجه املقابل.
ّ يقوم عضو الحجم sizeبإعادة قيمة من نوع size_type •
ملحوظة
دائما على نوع عنرصه:
ً املعرف به .يشتمل نوع املتجه
ّ الستخدام ، size_typeيجب تسمية النوع
vector<int>::size_type // ok
vector::size_type // error
تملك عوامل املساواة والعالئق املنطقية نفس سلوك عمليات السلسلة املقابلة.
فيتساوى متجهان إن كان لديهما نفس عدد العنارص وكانت لعنارصهما املتقابلة نفس القيمة. •
تطبق العوامل العالئقية ترتيب القاموس: •
فإن كان للمتجهات أحجام مختلفة ،لكن عنارصها املشرتكة متساوية ، •
فإن املتجه الذي يحتوي على عدد أقل من العنارص يكون أقل من الذي يحتوي على عدد أكرب منها. •
أما إن كانت للعنارص قيم مختلفة ،فإن العالقة بني املتجهات تتحدد بالعالقة بني أولى العنارص املختلفة . •
على سبيل املثال ،لنفرتض أن لدينا مجموعة من الدرجات ترتاوح من 0إلى .100
نود حساب عدد الدرجات اليت تقع في مجموعات مختلفة عرشية. •
بني الصفر و 100هناك 101درجة ممكنة. •
يمكن تمثيل هذه الدرجات من خالل 11مجموعة: •
10مجموعات من 10درجات لكل منها باإلضافة إلى مجموعة واحدة للحصول على الدرجة املثالية .100 •
ستحسب املجموعة األولى درجات من 0إلى ، 9واملجموعة الثانية درجات من 10إلى ، 19وهكذا. •
تحسب املجموعة النهائية عدد النقاط اليت تم تحقيقها من .100 •
42 65 95 100 39 67 95 76 88 76 83 92 76 93
0 0 0 1 1 0 2 3 2 4 1
حيث تشري املخرجات إلى عدم وجود درجات أقل من ، 30ودرجة واحدة في الثالثينيات ، •
ودرجة واحدة في األربعينيات ،وال يشء في الخمسينيات ،واثنان في الستينيات ، •
وثالثة في السبعينيات ،واثنان في الثمانينيات ،وأربعة في التسعينيات ،ودرجة واحدة من .100 •
وبمجرد أن نحوسب فهرس املجموعة ،يمكننا استخدامه لفهرسة املتجه وإحضار العداد الذي نريد زيادته:
// count number of grades by clusters of ten: 0-9, 10-19, … 90-99, 100
;)vector<unsigned> scores(11, 0 // 11 buckets, all initially 0
;unsigned grade
{ )while (cin >> grade // read the grades
)if (grade <= 100 // handle only valid grades
;]++scores[grade/10 // increment counter for current cluster
}
الجملة اليت يقوم بالزتايد هي مثال جيد لنوع الكود املقتضب املمزي لربامج يس.++
نحوسب الفهرس بقسمة gradeعلى 10ونستخدم نتيجة القسمة لفهرسة .scores •
تجلب الدرجات املفهرسة العداد املناسب لهذه الدرجة. •
نقوم بزيادة قيمة هذا العنرص لإلشارة إلى حدوث درجة في النطاق املعطى. •
كما رأينا ،عندما نستخدم رمز فهرسة ،يجب أن نفكر في كيفية معرفتنا أن الفهارس تقع ضمن النطاق.
في هذا الربنامج ،نتحقق من أن املدخالت تكون درجة صالحة في نطاق بني 0و .100 •
وبالتالي ،فإننا نعلم أن الفهارس اليت يمكننا حسابها ترتاوح بني 0و .10 •
هذه الفهارس ستكون بني 0و . scores.size()-1 •
بكل حال ،هذا خطأ ivec :متجه فارغ ؛ ال توجد عنارص لفهرستها!
وكما رأينا سابقاً ،فالطريقة الصحيحة لكتابة هذه الحلقة هي استخدام : push_back
من املهم للغاية أن نفهم أننا نستخدم عامل الفهرسة [ ] لجلب عنارص موجودة فعالً فقط .فمثال: •
;vector<int> ivec // empty vector
;]cout << ivec[0 !// error: ivec has no elements
vector<int> ivec2(10); // vector with ten elements
;]cout << ivec2[10 // error: ivec2 has elements 0 … 9
يعد إدخال عنرص غري موجود خطًأ ،ولكنه خطأ من غري املحتمل أن يكتشفه املرتجم. •
بدال ً من ذلك ،القيمة اليت نحصل عليها في وقت التشغيل غري محددة. •
محاولة فهرسة عنارص غري موجودة ،لألسف ،خطأ برمجي شائع للغاية وخبيث. •
ما يسمى بأخطاء تجاوز سعة املخزن املؤقت هي نتيجة لعنارص فهرسة غري موجودة. •
شيوعا ملشاكل األمان في جهاز الكمبيوتر والتطبيقات األخرى.
ً مثل هذه األخطاء هي السبب األكرث •
تحذير
عامل الفهرسة على املتجه (والسلسلة) يقوم بجلب عنرص موجود ؛ لكن ال يضيف عنرصًا.
تلميح
على الرغم من أنه يمكننا استخدام الفهرسة للوصول إلى أحرف سلسلة أو عنارص متجه ،
إال أن هناك آلية أكرث عمومية -تُعرف باسم املكررات -Iteratorsيمكننا استخدامها لنفس الغرض. •
وكما سرنى في الجزء الثاني تعرف املكتبة عدة أنواع أخرى من الحاويات إضافة إلى املتجهات. •
تحتوي كل حاويات املكتبة على مكررات ،لكن قلة منها فقط تدعم الفهرسة. •
من الناحية الفنية ،فإن السلسلة ليست نوع حاوية ،لكنها تدعم العديد من عمليات الحاوية. •
أيضا على مكررات مثل املتجهات.
وكما رأينا فالسلسلة مثل املتجه لها عامل فهرسة .و تحتوي ً •
على عكس املؤرشات ،ال نستخدم عامل العنوان للحصول على مكرر.
لكن بدال ً من ذلك ،اﻷنواع اليت تملك مكررات تحوي أعضاء تعيد مكررات. •
على وجه الخصوص ،هذه األنواع تملك أعضاء باسم بداية beginونهاية .end •
مكررا يشري إلى أول عنرص(أو أول حرف) ،إن وجد :
ً يعيد عضو بداية •
املكرر املعاد عن طريق نهاية هو مكرر مكانه "ما بعد نهاية" الحاوية املرتبطة (أو السلسلة). •
يشري ذلك املكرر إلى عنرص غري موجود "ما بعد نهاية" الحاوية. •
فيتم استخدام نهاية كعالمة تشري إلى نهاية معالجتنا لجميع العنارص. •
وغالبا ما يُشار إلى املكرر املعاد من نهاية بمكرر ما بعد النهاية the off-the-end iterator
ً •
أو اختصاراً "مكرر النهاية" “”.the end iterator •
فإن كانت الحاوية فارغة ،فستقوم بداية بإعادة نفس املكرر املعاد من نهاية. •
ملحوظة
إن كانت الحاوية فارغة ،فإن املكررات املعادة بواسطة beginو endمتساوية -فكالهما مكررا ما بعد النهاية.
بشكل عام ،ال نعرف (أو نهتم) بالنوع الدقيق الذي يمتلكه املكرر. •
في هذا املثال ،استخدمنا autoلتعريف bو . e •
نتيجة لذلك ،فإن لهذه املتغريات نوع ما يتم إعادته بواسطة عضوي beginو ، endعلى التوالي. •
سيكون لدينا املزيد لنقوله عن هذه األنواع ﻻحقا. •
مثل املؤرشات ،يمكننا إلغاء املرجع عن مكرر للوصول إلى العنرص املشار إليه بواسطة مكرر. •
أيضا ،مثل املؤرشات ،قد نلغي املرجع فقط عن مكرر صالح يشري إلى عنرص.
ً •
إلغاء املرجع عن مكرر غري صالح أو مكرر ما بعد النهاية يعد سلوكاً غري معرف. •
فعلى سبيل املثال ،سنعيد كتابة الربنامج من الفقرة 3.2.3الذي استبدل أول حرف من سلسلة بحرف كبري •
وذلك باستخدام مكرر بدال ً من فهرسة : •
Some string
Moving Iterators from One Element to Another تحريك املكررات من عنرص إلى آخر
ملحوظة
نظرًا ألن املكرر املعاد من endال يشري لعنرص ،فال يسمح بزتايده وال إلغاء مرجع عنه.
باستخدام عامل الزتايد ،يمكننا إعادة كتابة برنامجنا الذي غرّي حالة أول كلمة في سلسلة لنستخدم املكررات :
هذه الحلقة ،مثل تلك املوجودة في الفقرة ، 3.2.3تتكرر عرب األحرف في ، s •
وتتوقف عندما تواجه حرف مسافة بيضاء .مع ذلك ، •
تصل هذه الحلقة إلى هذه األحرف باستخدام مكرر وليس بفهرسة. •
تبدأ الحلقة بتهيئة itعلى ، s.beginما يعين أن itستشري إلى أول حرف (إن وجد) في .s •
يتحقق الرشط ما إذا كان itقد وصل إلى نهاية .sفإن لم يكن كذلك ، •
يقوم الرشط التالي بإلغاء املرجع عن itلتمرير الحرف الحالي إلى isspaceملعرفة ما إذا كنا قد انتهينا. •
في نهاية كل تكرار ،سننفذ ++itللتقدم في التكرار لنصل إلى الحرف التالي في .s •
بنية هذه الحلقة ،هو نفس الجملة األخرية في ifالسابقة. •
حيث نلغي املرجع عن itلتمرير الحرف الحالي إلى toupperوتعيني الحرف الكبري الناتج مرة أخرى •
على الحرف الذي يشري إلى .it
قد يتفاجأ املربمجون الوافدون إلى يس ++من يس أو جافا أننا استخدمنا =! بدال ً من > في حلقات for •
كتلك املوجودة أعاله وفي الحلقة املوجودة في الصفحة .94
يستخدم مربمجو يس != ++كعادة .يفعلون ذلك لنفس السبب الذي يجعلهم يستخدمون املكررات بدال ً •
من الفهرسة:
ينطبق أسلوب الكود هذا بشكل جيد على أنواع مختلفة من الحاويات اليت توفرها املكتبة. •
كما رأينا ،هناك عدد قليل من أنواع املكتبة ،من بينها املتجه والسلسلة ،تملك عامل فهرسة. •
وباملثل ،تحتوي جميع حاويات املكتبة على مكررات تعرف عاملي == و=!. •
معظم هذه املكررات ال تملك عامل املقارنة >. •
لكن ومن خالل استخدام املكررات و=! بشكل روتيين ،فال داعي للقلق بشأن النوع الدقيق للحاوية اليت •
نعالجها.
من املهم أن نفهم أن هناك مجموعة من األنواع ذات الصلة من الناحية املفاهيمية. •
النوع عبارة عن مكرر إن كان يدعم مجموعة مشرتكة من اإلجراءات. •
تتيح لنا هذه اإلجراءات الوصول إلى عنرص في حاوية وتسمح لنا أن نتحرك من عنرص إلى آخر. •
يعتمد النوع املعاد بواسطة بداية ونهاية begin and endعلى ما إذا كان الكائن الذي يتم تشغيلهما عليه ثاب ًتا.
فإن كان الكائن ثاب ًتا ،فعندها ستقوم begin and endبإعادة مكرر ثابت ؛ •
أما إن لم يكن الكائن ثاب ًتا ،فسيتم إعادة مكرر : •
;vector<int> v
;const vector<int> cv
;)(auto it1 = v.begin // it1 has type vector<int>::iterator
;)(auto it2 = cv.begin // it2 has type vector<int>::const_iterator
كأعضاء بداية ونهاية ،تقوم هذه األعضاء بإعادة مكررات إلى أول عنرص وما بعد آخر عنرص في الحاوية. •
مع ذلك ،وبغض النظر عما إذا كان املتجه (أو السلسلة) ثاب ًتا ،فإنهما تُعيدان مكررا ثابتا. •
Combining Dereference and Member Access الدمج بني إزالة املرجع والوصول للعضو
عندما نلغي مرجعا عن مكرر ،نصل إلى الكائن الذي يشري إليه املكرر.
فإن كان لذلك الكائن نوع فئة ،فقد نرغب في الوصول إلى عضو من هذا الكائن. •
فارغا.
ً على سبيل املثال ،قد يكون لدينا متجه لسالسل وقد نحتاج إلى معرفة ما إذا كان عنرص معني •
وبافرتاض أن itمكرر في ذلك املتجه ،يمكننا التحقق مما إذا كانت السلسلة اليت تشري إليها فارغة كما يلي :
)((*it).empty
ألسباب سنغطيها في الفقرة ، 4.1.2فإن األقواس املوجودة في الكود أعاله رضورية. •
تخرب األقواس أنه سيطبق عامل إلغاء املرجع عن itويطبق عامل النقطة على نتيجة إلغاء املرجع عن .it •
لكن بدون األقواس ،سيطبق عامل النقطة على ، itوليس على الكائن الناتج عنها : •
يتم تفسري التعبري الثاني على أنه طلب لجلب العضو emptyمن الكائن املسمى .it •
بكل حال ،فـ itمكرر وليس له عضو يسمى . empty •
ومن ثم ،فإن هذا التعبري خاطئ. •
(*it).mem
فارغا :
ً فإذا أردنا طباعة محتويات الفقرة األولى من النص ،فسنكتب حلقة تتكرر خالل textحىت نواجه عنرصًا
Some vector Operations Invalidate Iterators بعض عمليات املتجه تبطل املكررات
تحذير
في الوقت الحالي ،من املهم إدراك أن الحلقات اليت تستخدم املكررات
يجب أال تضيف عنارص إلى الحاوية اليت تشري إليها املكررات.
.يؤدي تزايد مكرر إلى تحريك املكرر عنرصًا واح ًدا كل مرة
.• تملك جميع حاويات املكتبة مكررات تدعم الزتايد
. يمكننا استخدام == و=! ملقارنة مكررين صالحني في أي من أنواع حاويات املكتبة، وباملثل •
.كما تدعم املكررات للسلسلة واملتجه عمليات إضافية يمكنها التحريك عدة عنارص مكرر في املرة الواحدة •
.كذلك تدعم جميع العوامل العالئقية •
فمثالً ،وبافرتاض أن itمكرر في نفس املتجه مثل ، midيمكننا التحقق ما إن كان يشري إلى عنرص قبل أو بعد
midكالتالي :
أيض ا طرح مكررين طاملا أنهما يشريان إلى عنارص في نفس املتجه أو السلسلة أو ما بعد نهايته.
يمكننا ً •
والنتيجة ستكون املسافة بني املكررات. •
نعين باملسافة هنا املقدار الذي يتعني علينا من خالله تغيري مكرر واحد للحصول على اآلخر. •
سمى .difference_type
نوع النتيجة هو نوع عدد صحيح ذو إشارة يُ َّ •
يعرفان .difference_type
كل من املتجه والسلسلة ّ •
هذا النوع ذو إشارة ،ألن الطرح قد يعطي نتيجة سلبية. •
نبدأ بتعريف ثالثة مكررات beg :سيكون أول عنرص في النطاق ، •
و endمكرر ما بعد العنرص األخري ،و midالعنرص األقرب إلى الوسط. •
نقوم بتهيئة هذه املكررات لتشري إلى النطاق بأكمله في متجه < >stringيسمى .text •
فارغا.
ً تتحقق الحلقة أوال ً من أن النطاق ليس
إن كان midيساوي القيمة الحالية ل ، endفقد نفدت عنارص البحث. •
في هذه الحالة يفشل الرشط ونخرج من .while •
خالف ذلك ،يشري midإلى عنرص ما وسنتحقق ما إذا كان midيشري إلى العنرص الذي نريده. •
إذا كان كذلك ،فقد انتهينا ونخرج من الحلقة. •
إن كان ال يزال لدينا عنارص يجب معالجتها ،فإن الكود املوجود داخل whileيضبط النطاق عن طريق تحريك
endأو .beg
• إذا كان العنرص املشار إليه ب midأكرب من ، soughtفنحن نعلم أنه إذا كان soughtفي ، text
فسيظهر قبل العنرص الذي يُشار إليه ب .mid
• لذلك ،يمكننا تجاهل العنارص بعد ، midوهو ما نقوم به عن طريق ضبط midعلى .end
• إذا كانت *midأصغر من ، soughtفيجب أن يكون العنرص في نطاق العنارص بعد العنرص املشار إليه
ب .mid
• في هذه الحالة ،نقوم بضبط النطاق بجعل begيشري إلى العنرص بعد midمبارشة.
نحن نعلم بالفعل أن midليس هو الذي نريده ،لذا يمكننا استبعاده من النطاق. •
مساويا ل endأو سيشري إلى العنرص الذي نبحث عنه.
ً في نهاية ، whileسيكون mid •
إذا كان midيساوي ، endفهذا يعين أن العنرص لم يكن في .text •
املصفوفة هي بنية بيانات مشابهة لنوع مكتبة املتجهات لكنها تقدم تباينا مختلفا في األداء واملرونة.
فهي كاملتجه عبارة عن حاوية لكائنات غري مسماة من نوع واحد يمكن الوصول إليها عن طريق الفهرسة. •
لكنها على عكس املتجه ،ذات حجم ثابت ؛ إذ ال يمكننا إضافة عنارص إليها. •
ونظرًا ألن حجمها ثابت ،فإنها تقدم أحيا ًنا أداء أفضل وقت التشغيل للتطبيقات املتخصصة. •
مع ذلك ،تأتي مزية وقت التشغيل تلك على حساب املرونة املفقودة. •
تلميح
إن كنت ال تعرف بالضبط عدد العنارص اليت تحتاجها ،فاستخدم املتجه.
تحذير
يمكننا تهيئة عنارص املصفوفة تهيئة قائمة .وعندما نقوم بذلك ،يمكننا حذف الحجم.
إذا حذفنا الحجم ،فإن املرتجم يستنتجها من عدد العنارص املهيئة. •
أما إذا حددنا حجماً ،فيجب أال يتجاوز عدد العنارص املهيئة الحجم املحدد. •
فإذا كان الحجم أكرب من عدد املهيئات ،يتم استخدام املهئي ألولى العنارص ويتم تهيئة أي عنارص متبقية : •
إن أبعاد a1هي ثالث خانات ؛ بينما أبعاد a2و a3كالهما أربع خانات.
يعد تعريف a4خاطئاً .فعلى الرغم من أن القيم الحرفية تحتوي فقط على ستة أحرف رصيحة ، •
يجب أن يكون حجم املصفوفة سبعة خانات على األقل -ستة لالحتفاظ بالحرفية وخانة للصفر. •
ال يمكننا تهيئة مصفوفة كنسخة من مصفوفة أخرى ،وال يجوز تعيني مصفوفة على أخرى:
تحذير
قد تسمح بعض املرتجمات بتعيني املصفوفة كامتداد للمرتجم. •
من الجيد عاد ًة تجنب استخدام مزيات غري قياسية. •
فلن تعمل الربامج اليت تستخدم مثل هذه املزيات مع مرتجم مختلف. •
Understanding Complicated Array Declarations فهم إعالنات املصفوفة املعقدة
عند قراءة هذا اإلعالن من الداخل إلى الخارج ،نرى أن arryعبارة عن مرجع. •
بالنظر إلى اليمني ،نرى أن الكائن الذي يشري إليه arryهو مصفوفة بحجم .10 •
بالنظر إلى اليسار ،نرى أن نوع العنرص هو مؤرش لعدد صحيح . •
وبالتالي ،فإن arryهي مرجع ملصفوفة من عرشة مؤرشات. •
تلميح
قد يكون من األسهل لفهم تعريفات املصفوفة البدء باسم املصفوفة وقراءتها من الداخل إلى الخارج.
تمارين القسم 3.5.1
التمرين :3.27
-بافرتاض أن txt_sizeدالة ال تأخذ أي وسيطات وتقوم بإعادة قيمة عدد صحيح ،
-فأي التعريفات التالية تعترب غري رشعية؟ ارشح السبب.
;unsigned buf_size = 1024
;](a) int ia[buf_size
;](b) int ia[4 * 7 - 14
;])((c) int ia[txt_size
;"(d) char st[11] = "fundamental
تمرين :3.28
ما هي القيم املوجودة في املصفوفات التالية؟
;]string sa[10
;]int ia[10
{ )(int main
;]string sa2[10
;]int ia2[10
}
التمرين :3.29
ضع قائمة ببعض عيوب استخدام املصفوفات بدال ً من املتجهات.
باستثناء أن املصفوفات ذات حجم ثابت ،فإننا نستخدمها بطرق مشابهة لكيفية استخدامنا للمتجهات.
فمثالً ،يمكن إعادة تنفيذ برنامجنا للتقدير من فقرة 3٫3٫3الستخدام مصفوفة لتثبيت عدادات املجموعة :
…// count number of grades by clusters of ten: 0-9, 10-19, 90-99, 100
unsigned scores[11] = {}; // 11 buckets, all value initialized to 0
;unsigned grade
{ )while (cin >> grade
)if (grade <= 100
++scores[grade/10]; // increment counter for current cluster
}
االختالف الوحيد الواضح بني هذا الربنامج والربنامج املوجود في الصفحة 104هو إعالن .scores •
فإعالن scoresفي هذا الربنامج عبارة عن مصفوفة من 11عنرصًا بال_إشارة. •
االختالف غري الواضح هو أن عامل الفهرسة في هذا الربنامج هو الذي تم تعريفه كجزء من اللغة. •
يمكن استخدام هذا العامل في معامالت نوع املصفوفة. •
تم تعريف عامل الفهرسة املستخدم في الربنامج في الصفحة 104بواسطة قالب مكتبة املتجه وينطبق على •
معامالت نوع متجه.
كما في حالة السلسلة أو املتجه ،من األفضل استخدام forالنطاق عندما نريد عبور املصفوفة بأكملها.
على سبيل املثال ،يمكننا طباعة scoresالناتجة على النحو التالي :
مثل السلسلة واملتجه ،فإن األمر مرتوك للمربمج للتأكد من أن قيمة الفهرسة ضمن النطاق -
أي أن قيمة الفهرس تساوي الصفر أو أكرب من الصفر وأقل من حجم املصفوفة. •
ال يشء يمنع الربنامج من تخطي حدود املصفوفة باستثناء االهتمام الدقيق بالتفاصيل واالختبار الشامل •
للكود.
من املمكن أن يتم تجميع الربامج وتنفيذها لكنها ستظل في خطأ قاتل. •
تحذير
شيوعا ملشاكل األمان هو أخطاء تجاوز سعة املخزن املؤقت.
ً املصدر األكرث •
تحدث مثل تلك األخطاء عندما يفشل برنامج فحص الفهرسة ، •
ويستخدم ذاكرة عن طريق الخطأ خارج نطاق مصفوفة أو هيكل بيانات مماثل. •
وكحال أي كائن آخر ،يمكننا الحصول على مؤرش لعنرص مصفوفة من خالل أخذ عنوان هذا العنرص:
تلقائيا
ً مع ذلك ،فإن املصفوفات لها خاصية خاصة -ففي معظم األماكن عندما نستخدم مصفوفة ،يقوم املرتجم
باستبدالها بمؤرش ألول عنرص :
ملحوظة
في معظم التعبريات ،عندما نستخدم كائن نوع مصفوفة ،فإننا نستخدم مؤرشًا ﻷول عنرص في تلك املصفوفة.
هناك العديد من اآلثار املرتتبة على حقيقة أن العمليات على املصفوفات في الغالب تكون عمليات على مؤرشات.
معرف بـ autoفإن النوع املستنتج
كمهئي ملتغري ّ
• أحد تلك اآلثار الضمنية هو أنه عندما نستخدم مصفوفة ُ
سيكون مؤرشاً ،وليس مصفوفة :
;)]auto ia2(&ia[0 *// now it's clear that ia2 has type int
على سبيل املثال ،يمكننا استخدام عامل الزتايد لالنتقال من عنرص مصفوفة إلى التالي:
ومثلما يمكننا استخدام املكررات الجتياز عنارص في متجه ،يمكننا استخدام املؤرشات الجتياز عنارص في مصفوفة.
لكن بالطبع للقيام بذلك ،نحتاج إلى الحصول على مؤرشات ﻷول عنرص والعنرص ما بعد األخري. •
كما رأينا للتو ،يمكننا الحصول على مؤرش ﻷول عنرص باستخدام املصفوفة نفسها أو من عنوان أول عنرص. •
ويمكننا الحصول على مؤرش ما بعد-النهاية باستخدام خاصية خاصة أخرى للمصفوفات. •
يمكننا أن نأخذ عنوان ما بعد آخر عنرص غري موجود في املصفوفة :
باستخدام هذه املؤرشات ،يمكننا كتابة حلقة لطباعة العنارص في arrعلى النحو التالي:
The Library begin and end Functions دوال مكتبة بداية ونهاية
على الرغم من أنه يمكننا حوسبة مؤرش ما بعد نهاية العنارص ،إال أن فعل ذلك قد يكون عرضة للخطأ.
لجعل استخدام املؤرشات أسهل وأكرث أما ًنا ، •
تشتمل املكتبة الجديدة على دالتني ،يطلق عليهما بداية beginونهاية .end •
تعمل هاتان الدالتان مثل أعضاء الحاوية املسماة بشكل مشابه. •
مع ذلك ،وﻷن املصفوفات ليست أنواع فئات ،فال تعترب هاتان دالتا أعضاء. •
حيث تعيد بداية مؤرشًا ﻷول عنرص ،وتعيد نهاية مؤرشًا ملا بعد آخر عنرص في املصفوفة املحددة:
يتم تعريف هذه الدوال في العنوان .iterator •
وباستخدام بداية ونهاية ،من السهل كتابة حلقة ملعالجة العنارص في مصفوفة. •
فمثالً ،وبافرتاض أن arrعبارة عن مصفوفة تحتوي على قيم عدد صحيح ،فقد نجد أول قيمة سالبة في : arr
//pbeg points to first & pend points just past last element in arr
;)int *pbeg = begin(arr), *pend = end(arr
// find first negative element, stopping if we've seen all elements
)while (pbeg != pend && *pbeg >= 0
;++pbeg
ملحوظة
يترصف مؤرش "ما بعد" نهاية املصفوفة املدمجة بنفس طريقة املكرر املعاد بعملية نهاية املتجه.
باﻷخص ،ال يجوز لنا إلغاء مرجع أو تزايد مؤرش ما بعد النهاية.
يمكن للمؤرشات اليت تعالج عنارص مصفوفة استخدام جميع عمليات املكرر املدرجة في الجدول 3.6والجدول . 3.7
• هذه العمليات -كالتعيني ،الزتايد ،املقارنات ،إضافة قيمة عدد صحيح ،طرح مؤرشين -لها نفس املعىن
عند تطبيقها على مؤرشات تشري لعنارص مصفوفة مدمجة مثل تطبيقها على مكررات.
• عندما نضيف (أو نطرح) قيمة صحيحة إلى (أو من) مؤرش ،تكون النتيجة مؤرشًا جدي ًدا.
يشري هذا املؤرش الجديد إلى العنرص الذي يتقدم (أو يسبق) املؤرش األصلي: •
عندما نضيف szإلى ، arrيحول املرتجم arrإلى مؤرش ﻷول عنرص في .arr •
عندما نضيف szإلى هذا املؤرش ،نحصل على مؤرش يشري ملواضع ( szأي 5مواضع) بعد األول. •
أي أنه يشري مرة واحدة إلى آخر عنرص في .arr •
حوسبة مؤرش ألكرث من عنرص واحد ملا بعد آخر عنرص خطأ ، •
على الرغم من أنه من غري املرجح أن يكتشف املرتجم مثل هذه األخطاء. •
كحال املكررات ،فإن طرح مؤرشين يعطينا املسافة بينهما .يجب أن تشري املؤرشات لعنارص في نفس املصفوفة :
يمكننا استخدام العوامل العالئقية ملقارنة املؤرشات اليت تشري لعنارص من مصفوفة ،أو ملا بعد آخر عنرص فيها.
على سبيل املثال ،يمكننا عبور العنارص في arrعلى النحو التالي:
ال يمكننا استخدام العوامل العالئقية على مؤرشات تشري لكائنني غري مرتبطني:
;int i = 0, sz = 42
;int *p = &i, *e = &sz
!// undefined: p and e unrelated; comparison meaningless
)while (p < e
على الرغم من أن حساب املؤرش قد يكون غامضا في هذه املرحلة ، •
أيضا للمؤرشات الفارغة وللمؤرشات اليت تشري لكائن ليس مصفوفة.
فمن الجدير بالذكر أن األداة صالحة ً •
في الحالة األخرية ،يجب أن تشري املؤرشات لنفس الكائن ،أو ما بعد ذلك الكائن. •
فارغا ،فيمكننا إضافة أو طرح تعبري ثابت ال يتجزأ تكون قيمته من 0إلى .p
ً إذا كان pمؤرشًا •
أيضا طرح مؤرشين فارغني من بعضهما ،وفي هذه الحالة تكون النتيجة .0
يمكننا ً •
يقوم التعبري ( *)ia + 4بحساب عنوان أربعة عنارص بعد iaويلغي املرجع عن املؤرش الناتج.
هذا التعبري يعادل كتابة ].ia[4 •
تذكر أنه الحظنا سابقاً أن األقواس مطلوبة في تعبريات تحتوي على عوامل مرجع وعوامل نقطة. •
وباملثل ،تعترب األقواس حول إضافة املؤرش رضورية. •
فكتابة :
يعين إلغاء املرجع عن iaوإضافة 4إلى القيمة غري املرجعية .سنغطي أسباب هذا السلوك في .4.1.2
كما رأينا ،في معظم األماكن عندما نستخدم االسم ملصفوفة ،
فإننا نستخدم بالفعل مؤرشًا ﻷول عنرص في تلك املصفوفة. •
هناك مكان واحد حيث يقوم املرتجم بإجراء هذا التحويل هو عندما نقوم بفهرسة مصفوفة. •
بافرتاض :
يمكننا استخدام عامل الفهرسة على أي مؤرش ،طاملا أن هذا املؤرش يشري إلى عنرص (أو ما بعد آخر عنرص) فيها :
يشري هذا املثال األخري إلى اختالف مهم بني املصفوفات وأنواع مكتبة كاملتجه والسلسلة لها عوامل فهرسة. •
تفرض أنواع املكتبة على الفهرس املستخدم مع الكود أن يكون قيمة بال_إشارة. •
عامل الفهرسة املدمج ال يقوم بذلك. •
يمكن أن يكون الفهرس املستخدم مع عامل الفهرسة املدمج قيمة سالبة. •
بالطبع ،يجب أن يشري الناتج إلى عنرص في (أو ما بعد نهاية) املصفوفة اليت يشري إليها املؤرش األصلي. •
تحذير
على عكس فهرسة املتجه والسلسلة ،فإن فهرس عامل الفهرسة املدمج هو نوع مؤرش.
تحذير
بالرغم من دعم يس ++لسالسل نمط اليس إال أنه ال ينبغي استخدامها في برامجها .تعد تلك السالسل
غنيا لألخطاء بشكل مدهش وهي سبب جذري ملشكالت أمان عديدة .كما أن استخدامها أصعب! مصدرا ً
ً
تُعد حرفيات سلسلة حرف مثياًل لبنية أكرث عمومية ترثها لغة يس ++من سالسل أحرف أنماط لغة اليس :سالسل
نمط اليس.
إن سالسل نمط اليس ليست نوعا .بل هي اصطالح لكيفية تمثيل واستخدام سالسل األحرف.
• يتم تخزين السالسل اليت تتبع هذا االصطالح في مصفوفات أحرف تنتهي بقيمة خالية null
. terminated
• نعين بقيمة خالية أن آخر حرف في السلسلة يُتبع بحرف خال.
وعادة نستخدم املؤرشات ملعالجة تلك السالسل. •
توفر مكتبة-يس القياسية مجموعة دوال مدرجة في الجدول ، 3.8واليت تعمل على سالسل نمط اليس.
يتم تعريف هذه الدوال في العنوان ، cstringوهو نسخة يس ++من العنوان .string.h
تحذير
يجب أن يشري املؤرش(ــات) الذي تم تمريره(ــا) لهذه اإلجراءات ملصفوفة(ــات) منتهية بقيمة خالية :
معرف.
في هذه الحالة ca ،عبارة عن مصفوفة من charولكن ﻻ تنتهي بقيمة خالية .النتيجة سلوك غري ّ •
التأثري األكرث احتماال لهذا االستدعاء هو استمرار strlenفي البحث عرب الذاكرة اليت تلي caحىت تواجه •
حر ًفا خالياً .
مقارنة السالسل
تذكر أننا عندما نستخدم مصفوفة ،فإننا نستخدم مؤرشًا يشري ﻷول عنرص في املصفوفة. •
فعليا قيمتني ثابتتني ملؤرش حرف *.
ً ومن ثم ،فإن هذا الرشط يقارن •
هذه املؤرشات ال تعالج نفس الكائن ،لذا فاملقارنة سلوك غري معرف. •
ملقارنة سالسل نمط اليس ،وبدال ً من قيم املؤرش ،يمكننا استدعاء .strcmp
تعيد هذه الدالة صفراً إن كانت السالسل متساوية ،أو قيمة موجبة أو سالبة ، •
اعتما ًدا على ما إذا كانت أول سلسلة أكرب أو أصغر من الثانية : •
if (strcmp(ca1, ca2) < 0) // same effect as string comparison s1 < s2
تكمن املشكلة في أنه يمكننا بسهولة أن نخطئ في تقدير الحجم املطلوب لـ .largeStr •
عالوة على ذلك ،في أي وقت نقوم فيه بتغيري القيم اليت نريد تخزينها في ، largeStr •
علينا أن نتذكر التحقق جي ًدا من أننا حسبنا حجمها بشكل صحيح. •
لسوء الحظ ،يتم توزيع برامج مشابهة لهذا الرمز على نطاق واسع. •
وغالبا ما تؤدي إلى ترسيبات أمنية خطرية.
ً الربامج اليت تحتوي على مثل هذا الكود معرضة لألخطاء •
تلميح
بالنسبة ملعظم التطبيقات من األفضل استخدام سالسل املكتبة بدال ً من سالسل نمط اليس،
أيضا.
إضافة لكونها أكرث أما ًنا ً
التمرين :3.40
برنامجا لتعريف مصفوفتني أحرف تمت تهيئتهما من سلسلة حرفية.
ً -اكتب
-عرف اآلن مصفوفة حرف ثالثة لتحمل تجميع املصفوفتني .
-استخدم strcpyو strcatلنسخ املصفوفتني في الثالث .
العديد من برامج يس ++املكتبة القياسية وال تستخدم أنواع السالسل واملتجهات. تسبق
عالوة على ذلك ،تتفاعل العديد من برامج يس ++مع برامج مكتوبة بلغة اليس أو لغات أخرى ال يمكنها •
استخدام مكتبة يس.++
ومن ثم ،قد يتعني على الربامج املكتوبة بلغة يس ++الحديثة أن تتعامل مع أكواد استخدمت مصفوفات •
و/أو سالسل حرف نمط اليس.
توفر مكتبة يس ++أقساماً لتجعل إدارة الواجهة أسهل. •
في الفقرة 3.2.1رأينا أنه يمكننا تهيئة سلسلة على حرفية سلسلة :
بشكل عام ،يمكننا استخدام مصفوفة أحرف منتهية بقيمة خالية في أي مكان يمكننا فيه استخدام حرفية سلسلة:
يمكننا استخدام مصفوفة أحرف منتهية بقيمة خالية لتهيئة سلسلة أو تعيينها. •
ويمكننا استخدام مصفوفة أحرف منتهية بقيمة خالية كمعامل واحد (لكن ليس كال املعاملني) إلى عامل تزايد •
السلسلة أو كمعامل أيمن في التعيني املركب ( )=+لسلسلة.
;char *str = s // error: can't initialize a char* from a string
;)(const char *str = s.c_str // ok
يشري االسم c_strإلى أن الدالة تقوم بإعادة سالسل أحرف نمط اليس. •
أي أنها تعيد مؤرشًا لبداية مصفوفة أحرف تنتهي بقيمة خالية تحتوي على نفس البيانات مثل األحرف •
املوجودة في السلسلة.
نوع املؤرش حرف ثابت ، * const charما يمنعنا من تغيري محتويات املصفوفة. •
املصفوفة املعادة من c_strليست مضمونة أن تكون صالحة إلى ما ﻻ نهاية. •
أي استخدام الحق لـ sقد يغري قيمة sيمكن أن يبطل هذه املصفوفة. •
تحذير
إذا احتاج الربنامج إلى وصول مستمر ملحتويات املصفوفة املعادة من () ، strفيجب على الربنامج
نسخ املصفوفة املعادة من ().c_str
في الفقرة 3.5.1الحظنا أنه ال يمكننا تهيئة مصفوفة مدمجة على مصفوفة أخرى .وال يمكننا تهيئة مصفوفة على
متجه.
ومع ذلك ،
يمكننا استخدام مصفوفة لتهيئة متجه .للقيام بذلك ،نحدد عنوان أول عنرص وما بعد أخر عنرص نرغب في نسخه :
يشري املؤرشان املستخدمان في إنشاء ivecإلى نطاق القيم املراد استخدامها لتهيئة العنارص في .ivec •
يشري املؤرش الثاني ملا بعد آخر عنرص يراد نسخه .في هذه الحالة ، •
استخدمنا داليت beginو endللمكتبة لتمرير املؤرشات ﻷول عنرص وما بعد آخر عنرص في .int_arr •
نتيجة لذلك ،سيكون لدى ivecستة عنارص سيكون لكل منها نفس قيمة العنرص املقابل في .int_arr •
تنئش هذه التهيئة subVecبثالثة عنارص .قيمها هي نسخ من القيم من ] int_arr[1وحىت ].int_arr[3
املؤرشات واملصفوفات عرضة للخطأ بشكل مدهش .جزء من املشكلة يتعلق باملفاهيم : •
تُستخدم املؤرشات في عمليات معالجة منخفضة املستوى حيث من السهل حصول أخطاء في معالجة •
امللفات.
تنشأ مشاكل أخرى بسبب بناء الجملة ،وال سيما صيغة اإلعالن املستخدمة مع املؤرشات. •
يجب أن تستخدم برامج يس ++الحديثة املتجهات واملكررات بدال ً من املصفوفات واملؤرشات املدمجة ، •
وأن تستخدم السالسل بدال ً من سالسل أحرف مستندة إلى مصفوفة ذات نمط اليس. •
نعرف املصفوفة اليت تكون عنارصها مصفوفات من خالل توفري بعدين :بُعد املصفوفة نفسها وأبعاد عنارصها:
int ia[3][4]; // array size 3; each element is array of ints size 4
// array size 10; each element 20-element array whose elements arrays
// of 30 ints
كما رأينا في الفقرة ، 3.5.1يمكننا بسهولة فهم هذه التعريفات بقراءتها من الداخل إلى الخارج. •
سنبدأ باالسم الذي نعرفه ( )iaونرى أن iaعبارة عن مصفوفة بحجم .3 •
أيضا بُعد.
باالستمرار في النظر إلى اليمني ،نرى أن عنارص iaلها ً •
وبالتالي ،فإن العنارص املوجودة في iaهي نفسها مصفوفات بحجم .4 •
بالنظر إلى اليسار ،نرى أن نوع هذه العنارص عبارة عن .int •
إذن ia ،عبارة عن مصفوفة بحجم ، 3كل عنرص من عنارصه عبارة عن مصفوفة من أربعة أعداد صحيحة •
.ints
كحال أي مصفوفة ،يمكننا تهيئة عنارص مصفوفة متعددة األبعاد من خالل توفري قائمة بني قوسني من املهيئات.
يمكن تهيئة املصفوفات متعددة األبعاد عن طريق تعريف القيم املوضوعة بني قوسني لكل صف:
{ = ]int ia[3][4 // three elements; each element array of size 4
{0, 1, 2, 3}, // initializers for row indexed by 0
{4, 5, 6, 7}, // initializers for row indexed by 1
}{8, 9, 10, 11 // initializers for row indexed by 2
;}
وضوحا إلى حد كبري :
ً تعترب األقواس املتداخلة اختيارية .التهيئة التالية مكافئة ،على الرغم من أنها أقل
// equivalent initialization without optional nested braces for each row
;}int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11
كحال املصفوفات أحادية البعد ،يمكن ترك العنارص خارج قائمة التهيئة.
يمكننا تهيئة أول عنرص فقط على كل صف على النحو التالي:
يتم تهيئة العنارص املتبقية بنفس طريقة تهيئة املصفوفات العادية أحادية البعد.
تماما .فالكود التالي:
ً إذا تم حذف األقواس املتداخلة ،فستكون النتائج مختلفة
يقوم بتهيئة عنارص أول صف .بينما تتم تهيئة العنارص املتبقية على .0
كما هو حال أي مصفوفة ،يمكننا استخدام فهرسة للوصول إلى عنارص املصفوفة متعددة األبعاد.
للقيام بذلك ،نستخدم رمز فهرسة منفصاًل لكل بُعد. •
فإذا كان التعبري يوفر عد ًدا من الفهارس بقدر عدد األبعاد ،فإننا نحصل على عنرص من النوع املحدد. •
إذا قدمنا عدد فهارس أقل من األبعاد ،فإن النتيجة هي عنرص املصفوفة الداخلي في الفهرس املحدد :
// assigns first element of arr to last element in last row of ia
;]ia[2][3] = arr[0][0][0
int (&row)[4] = ia[1]; //binds row to second four-element array in ia
في املثال األول نوفر مؤرشات لجميع األبعاد لكل من املصفوفتني. •
على الجانب األيرس ،يعيد ] ia[2الصف األخري في .ia •
إنه ال يقوم بجلب عنرص من تلك املصفوفة ولكنه يعيد املصفوفة نفسها. •
نقوم بتدوين هذه املصفوفة ،وإحضار العنرص [ ، ]3وهو العنرص األخري في تلك املصفوفة. •
مثال آخر :من الشائع استخدام زوج حلقات forمتداخلة ملعالجة عنارص في مصفوفة متعددة األبعاد:
;constexpr size_t rowCnt = 3, colCnt = 4
;]int ia[rowCnt][colCnt // 12 uninitialized elements
// for each row
{ )for (size_t i = 0; i != rowCnt; ++i
// for each column within the row
{ )for (size_t j = 0; j != colCnt; ++j
// assign the element's positional index as its value
;ia[i][j] = i * colCnt + j
}
}
بموجب املعيار الجديد ،يمكننا تبسيط الحلقة السابقة باستخدام نطاق :for
تعطي هذه الحلقة عنارص iaنفس قيم الحلقة السابقة ،لكن هذه املرة نسمح للنظام بإدارة املؤرشات لنا. •
نريد تغيري قيمة العنارص ،لذلك نعلن متغريات التحكم لدينا rowو colمراجع. •
يكرر forاألول عرب العنارص في .iaهذه العنارص عبارة عن مصفوفات بحجم .4 •
وبالتالي ،فإن نوع rowهو مرجع ملصفوفة من أربعة .ints •
يكرر forالثاني عرب إحدى تلك املصفوفات املكونة من 4عنارص. •
ومن ثم ،فإن العمود هو .&intوفي كل تكرار نعني قيمة cntللعنرص التالي في iaو نزايد قيمة .cnt •
في املثال السابق ،استخدمنا املراجع كمتغريات تحكم في الحلقة ألننا أردنا تغيري العنارص في املصفوفة. •
لكن ،هناك سبب أعمق الستخدام املراجع. •
)for (const auto &row : ia // for every element in the outer array
)for (auto col : row // for every element in the inner array
;cout << col << endl
نعرف متغري التحكم للحلقة الخارجية كمرجع.
ال تكتب هذه الحلقة على العنارص ،مع ذلك ما زلنا ّ
نقوم بذلك لتجنب تحويل املصفوفة العادية إلى مؤرش .فلو أهملنا املرجع وكتبنا هذه الحلقات على النحو التالي:
ملحوظة
الستخدام مصفوفة متعددة األبعاد مع forالنطاق ،يجب أن يكون متغري التحكم في الحلقة للجميع
مرجعا ما عدا املصفوفة الداخلية.
ملحوظة
عندما تعرف مؤرش ًا ملصفوفة متعددة األبعاد ،تذكر أن تلك املصفوفة هي في الواقع مصفوفة من مصفوفات.
ونظرًا ألن املصفوفة متعددة األبعاد هي في الواقع مصفوفة من مصفوفات ،فإن نوع املؤرش الذي تتحول إليه
املصفوفة هو مؤرش ألول مصفوفة الداخلية :
;]int ia[3][4 //array of size 3; each element is array ints of size 4
;int(*p)[4] = ia // p points to array of four ints
;]p = &ia[2 // p now points to last element in ia
بتطبيق اإلسرتاتيجية من الفقرة ، 3.5.1نبدأ باإلشارة إلى أن ( )*pتقول أن pعبارة عن مؤرش. •
بالنظر إلى اليمني ،نرى أن الكائن الذي تشري إليه pله بُعد بحجم ، 4 •
وبالنظر إلى اليسار أن نوع العنرص هو .intومن ثم ،فإن pمؤرش ملصفوفة من أربعة .ints •
ملحوظة
األقواس في هذا اإلعالن رضورية:
;]int *ip[4 // array of pointers to int
int (*ip)[4]; // pointer to an array of four ints
// print value each element in ia, with each inner array on its own line
// p points to an array of four ints
{ )for (auto p = ia; p != ia + 3; ++p
;// q points to first element of array of four ints
// that is, q points to an int
)for (auto q = *p; q != *p + 4; ++q
;' ' << cout << *q
;cout << endl
}
بالطبع ،يمكننا كتابة هذه الحلقة بسهولة أكرب باستخدام داليت beginو endللمكتبة:
هنا ندع املكتبة تحدد مؤرش ، endونستخدم autoلتجنب االضطرار إلى كتابة النوع املعاد من .begin •
في الحلقة الخارجية ،هذا النوع هو مؤرش ملصفوفة من أربعة .ints •
في الحلقة الداخلية ،هذا النوع هو مؤرش لـ .int •
أسماء النوع املستعارة تبسط املؤرشات ملصفوفات متعددة اﻷبعاد
Type Aliases Simplify Pointers to Multidimensional Arrays
يمكن أن يسهل النوع املستعار قراءة وكتابة وفهم املؤرشات إلى مصفوفات متعددة األبعاد .فمثال:
تسمح املكررات
بالوصول غري املبارش إلى الكائنات املخزنة في حاوية. •
وتُستخدم للوصول إلى العنارص والتنقل بينها في السالسل واملتجهات. •
توفر املصفوفات واملؤرشات لعنارص املصفوفة نظائر منخفضة املستوى ملكتبات املتجهات والسلسلة.
• بشكل عام ،ينبغي استخدام فئات املكتبة بشكل مفضل على البدائل منخفضة املستوى من املصفوفات
واملؤرشات املدمجة في اللغة.
مصطلحــــــــــات معــــــــــرفة
Defined Terms
مصفوفة أحرف خالية النهاية .قيم حرفية سلسلة هي سالسل من نمط لغة اليس .وهي بطبيعتها
C-style strings
عرضة للخطأ.
مخطط يمكن من خالله إنشاء أنواع فئات معينة .الستخدام قالب فئة ،يجب علينا تحديد معلومات
class template
نعرف نوع العنرص :متجه < >intيحمل .ints إضافية .على سبيل املثال ،لتعريف متجه ّ ،
compiler مزية تمت إضافتها إلى اللغة بواسطة مرتجم معني .ال يمكن نقل الربامج اليت تعتمد على امتدادات
extension املرتجم بسهولة إلى برامج الرتجمة الربمجية األخرى.
container نوع تحتوي كائناته على مجموعة كائنات من نوع معني .املتجه عبارة عن نوع حاوية.
copy نموذج تهيئة يستخدم = .الكائن الذي تم إنشاؤه حديثًا هو نسخة من املُهئي املحدد.
initialization
difference_type نوع رقم صحيح بإشارة يعرفه املتجه والسلسلة يمكنه االحتفاظ باملسافة بني أي مكررين.
عضو سلسلة ومتجه .يقوم بإعادة قيمة منطقية ،واليت تكون صحيحة إذا كان الحجم صفرًا ،وإعادة
empty
قيمة خطأ في الحاالت األخرى.
دالة معرفة في عنوان سلسلة .تأخذ قناة مدخالت وسلسلة .تقوم بقراءة القناة حىت السطر الجديد
getline
التالي ،وتخزن ما قرأته في السلسلة ،وتعيد قناة املدخالت .تتم قراءة السطر الجديد والتخلص منه.
قيمة فهرس مستخدمة في عامل الفهرسة لتشري إلى العنرص املراد اسرتداده من سلسلة أو متجه أو
index
مصفوفة.
instantiation عملية مرتجم إلنشاء مثيل حيث تقوم بإنشاء فئة قالب معينة أو دالة.
عمليات على متجه أو مكرر سلسلة :إضافة أو طرح قيمة عدد صحيح وينتج عن املكرر العديد من
iterator العنارص قبل أو خلف املكرر األصلي .ينتج عن طرح مكرر واحد من آخر املسافة بينهما .يجب أن
arithmetic
تشري املكررات إلى عنارص في نفس الحاوية أو ما بعد آخرها.
off-the-end مكرر يتم إعادته بـ endيشري إلى عنرص غري موجود يقع بعد نهاية الحاوية.
iterator
pointer عمليات حسابية يمكن تطبيقها على مؤرشات .تدعم مؤرشات املصفوفات نفس العمليات الحسابية
arithmetic للمكرر.
push_back عضو متجه .يقوم بإلحاق عنارص إلى الجزء الخلفي من املتجه.
size عضو سلسلة ومتجه .يعيد عدد األحرف أو العنارص ،على التوالي .يعيد قيمة نوع . size_type
اسم أنواع معرفة بواسطة فئات سلسلة ومتجهات قادرة على احتواء حجم أي سلسلة أو متجه ،على
size_type
تعرفها كنوع بال_إشارة.
التوالي .فئات املكتبة اليت تحدد ( size_typeنوع_املقاس) ّ
using لجعل اسم من مساحة اسم قابل للوصول إليه مبارشة Using namepsace::name .؛ يجعل
declarations االسم قابال للوصول إليه بدون البادئة.
تهيئة يتم فيها تهيئة أنواع مدمجة على الصفر وتهيئة أنواع فئات بواسطة ُمنشئة الفئة االفرتاضية.
value يمكن تهيئة كائنات نوع فئة فقط إذا كان للفئة ُمنشئة افرتاضية .يستخدم لتهيئة عنارص الحاوية عند
initialization
تحديد حجم وليس ُمهئي عنرص .تتم تهيئة العنارص كنسخة من هذه القيمة الناتجة عن املرتجم.
تعرف أنواع املكرر واملؤرشات عامل الزتايد "إلضافة واحد" عن طريق تحريك املكرر لإلشارة إلى
++ operator
العنرص التالي.
ينتج ] obj[iعنرصا في املوضع iمن كائن حاوية .عدد الفهارس يبدأ من الصفر -العنرص األول
[ ] operator هو العنرص 0والعنرص األخري هو العنرص املفهرس بواسطة .obj.size()-1يقوم الفهرس
بإعادة كائن .إذا كانت pعبارة عن مؤرش و nعدد صحيح ،فإن ] p[nمرادف لـ * (.)p + n
-> operator عامل سهم .يجمع بني عمليات إزالة املرجع وعوامل النقطة a->b :هو مرادف لـ (* .b. )a
<< operator عامل املخرجات في نوع مكتبة سلسلة .عامل السلسلة يطبع األحرف في سلسلة.
عامل املدخالت في نوع مكتبة سلسلة .يقرأ عامل السلسلة قطع األحرف املحددة بمسافات بيضاء ،
>> operator
ويخزن ما يقرأ في املعامل األيمن (سلسلة).
! operator تعيد معكوس القيمة املنطقية ملعاملها .تكون النتيجة صحيحة إن كان املعامل خطأ والعكس صحيح.