Professional Documents
Culture Documents
5الجمــــــــــل
Chapter 5. Statements
الـمحتويات
Contents
تعترب الجملة الخالية مفيدة عندما تتطلب اللغة جملة لكن منطق الربنامج ال يتطلب ذلك.
شيوعا لها يكون عندما يمكن تنفيذ عمل بنية الحلقة عرب رشطها.
ً االستخدام األكرث •
على سبيل املثال ،قد نرغب في قراءة قناة مدخالت ،وتجاهل كل يشء نقرأه حىت نواجه قيمة معينة :
أفضل املمارسات
ينبغي التعليق على الجمل الخالية .هكذا يمكن ألي شخص يقرأ الكود أن يرى أن الجملة قد حذفت عن قصد.
احذر الفواصل املنقوطة املفقودة أو الغريبة
Beware of Missing or Extraneous Semicolons
ألن الجملة الخالية تعترب جملة ،فهي رشعية في أي مكان نتوقع فيه جملة.
غالبا ما تكون الفاصلة املنقوطة اليت قد تبدو غري رشعية أكرث من جملة خالية.
ً ولهذا ، •
يحتوي الجزء التالي على جملتني -واحدة تعبريية وأخرى خالية :
على الرغم من أن الجملة الخالية غري الرضورية غالبًا غري مرضة ، •
إال أن فاصلة منقوطة إضافية تتبع رشط whileأو ifبإمكانها تغيري نية املربمج بشكل كبري. •
جزءا من الحلقة.
ً على عكس املسافة الخالية ،فإن الزتايد ليس •
بنية الحلقة هي الجملة الخالية املكونة من الفاصلة املنقوطة اليت تتبع الرشط. •
تحذير
دائما لطيفة.
ً الجمل الخالية الدخيلة ليست
يتم استخدام الجمل املركبة عندما تتطلب اللغة جملة واحدة لكن منطق برنامجنا يحتاج إلى أكرث من واحدة.
مثالً ،يجب أن تكون بنية حلقة whileأو forجملة واحدة ، •
لكننا في الغالب سنحتاج لتنفيذ أكرث من جملة في بنية الحلقة. •
نقوم بذلك عن طريق إرفاق الجمل بأقواس معقوفة ،وبالتالي تحويل تسلسل جمل إلى كتلة. •
تطلب منطق برنامجنا جملتني لكن قد تحتوي حلقة whileعلى جملة واحدة فقط. •
وبإحاطة هذه الجمل بأقواس معقوفة ،جعلناها في جملة واحدة (مركبة). •
ملحوظة
أيض ا تعريف كتلة خالية عن طريق كتابة زوج من أقواس معقوفة بال جمل .فكتلة خالية تعادل جملة ﻻغية :
يمكننا ً
إذا احتجنا إلى الوصول إلى متغري التحكم ،فيجب تعريف ذلك املتغري خارج الجملة:
يتم استخدام قيمة الكائن املعرف في بنية تحكم بواسطة تلك البنية .لذلك ،يجب تهيئة مثل هذه املتغريات.
التمرين :5.4
-ارشح كاًل من األمثلة التالية ،
-قم بتصحيح أي مشاكل تكتشفها.
لحل هذه املشكلة ،يمكننا استخدام جملة إذا_ وإال لتنفيذ إجراءات مختلفة لفشل واجتياز الدرجات:
اعتما ًدا على قيمة الدرجة ،gradeنقوم بتنفيذ الجملة اليت تأتي بعد إذا_ أو بعد وإﻻ. •
ففي الحالة وإﻻ_ ،نحسب الفهرسة من gradeبطرح gradeمن 50لنحسب أكرب نطاق للدرجات الفاشلة. •
ثم نستخدم قسمة صحيحة بدون باقي لتحسب فهرس ( scoresالدرجة الحرفية) املناسب. •
سنجعل برنامجنا أكرث تشوي ًقا ،ونضيف إشارة موجب أو سالب إلى الدرجات الناجحة.
سنعطي عالمة موجب للدرجات املنتهية بـ 8أو ، 9وعالمة السالب لتلك اليت تنتهي بـ 0أو 1أو : 2
من الخطأ الشائع نسيان األقواس املتعرجة عندما يتوجب تنفيذ جمل متعددة ككتلة.
صحيحا.
ً صعبا للغاية ألن الربنامج يبدو
ً قد يكون الكشف عن خطأ كهذا •
دائما باستخدام األقواس بعد " "ifأو ""else
ً لتجنب مثل هذه املشاكل ،تويص بعض أنماط كتابة الكود •
(وكذلك حول بنية " "whileو ".)"for
فالقيام بذلك يؤدي إلى تجنب أي ارتباك محتمل. •
أيضا أن األقواس موجودة أصالً إذا تطلبت التعديالت الالحقة للكود إضافة جمل.
وهذا يعين ً •
أفضل املمارسات
تملك العديد من محررات وبيئات تطوير الربمجة أدوات تضع مسافة بادئة تلقائية ملصدر الكود ملطابقة
بنيتها .من الجيد استخدام هذه األدوات مىت توفرت.
عندما نقوم بتداخل ifداخل ifأخرى ،فمن املمكن أن تكون فروع إذا_ أكرث من فروع .else
في الواقع ،يشتمل برنامج الدرجات لدينا على أربعة ifواثنان من .else •
السؤال الذي يطرح نفسه :كيف نعرف أي ifينتمي إليه else؟ •
هذه املشكلة -واليت يشار إليها عاد ًة باسم متدليات - elseشائعة في العديد من لغات الربمجة اليت تحتوي على
جمل ifو .if else
تحل اللغات املختلفة هذه املشكلة بطرق مختلفة. •
في لغة يس ، ++يتم حل الغموض عرب مطابقة كل فرع elseمع أقرب حالة ifسابقة ال مثيل لها. •
يواجه املربمجون أحيا ًنا مشكلة عندما يكتبون أكواداً تحتوي على ifأكرث من فروع .else •
لتوضيح املشكلة ،سنعيد كتابة الجزء الداخلي if elseوالذي يضيف عالمة املوجب أو السالب باستخدام
مجموعة مختلفة من الرشوط:
// WRONG: execution does NOT match indentation; else goes with inner if
)if (grade % 10 >= 3
)if (grade % 10 > 7
;'lettergrade += '+ // grades ending in 8 or 9 get a +
else
;'lettergrade += '- // grades ending in 3, 4, 5, 6 will get -
تشري املسافة البادئة في الكود إلى أننا نعزتم استخدام " "elseمع ifالخارجية ، •
نعزتم تنفيذ فرع elseعندما تنتهي الدرجة برقم أقل من .3 •
ومع ذلك ،على الرغم من نوايانا ،وعلى عكس املسافة البادئة ، •
إال أن فرع elseيعترب جزءا من ifالداخلية. •
حيث سيضاف الرمز " "-إلى درجات تنتهي من 3إلى 7ضمناً! •
إن تم وضع مسافة بادئة بشكل صحيح ملطابقة التنفيذ الفعلي ،فسيصبح ما كتبناه هو:
Controlling the Execution Path with Braces التحكم بمسار التنفيذ عرب اﻷقواس
بدل_ طريقة مالئمة لالختيار من بني عدد (ربما كبري) من البدائل الثابتة.
توفر جملة ّ
كمثال ،افرتض أننا نريد حساب عدد مرات ظهور كل حرف من الحروف املتحركة الخمسة ضمن نص ما. •
سيكون منطق برنامجنا كما يلي: •
اقرأ كل حرف في املدخالت. •
قارن كل حرف بمجموعة حروف العلة. •
إذا كان الحرف يطابق أحد أحرف العلة ،أضف 1إلى عداد الحروف املتحركة. •
اعرض النتائج. •
فعلى سبيل املثال ،عند تشغيل الربنامج على نص هذا الفصل ،سيكون اإلخراج كالتالي:
بدل_:
يمكننا حل مشكلتنا مبارشة باستخدام جملة ّ
// initialize counters for each vowel
;unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0; char ch
{ )while (cin >> ch
// if ch is vowel, increment appropriate counter
{ )switch (ch
;case 'a': ++aCnt; break
;case 'e': ++eCnt; break
;case 'i': ++iCnt; break
;case 'o': ++oCnt; break
} ;case 'u': ++uCnt; break
}
// print results
'cout << "Number of vowel a: \t" << aCnt << '\n
'<< "Number of vowel e: \t" << eCnt << '\n
'<< "Number of vowel i: \t" << iCnt << '\n
'<< "Number of vowel o: \t" << oCnt << '\n
;<< "Number of vowel u: \t" << uCnt << endl
بدل_ عن طريق تقييم تعبري بني قوسني يتبع الكلمة املفتاحية .switch
يتم تنفيذ جملة ّ •
قد يكون هذا التعبري إعال ًنا عن متغري ُمهيأ. •
يتم تحويل التعبري إلى نوع رقمي صحيح. •
تتم مقارنة نتيجة التعبري بالقيمة املرتبطة بكل حالة .case •
إذا تطابق التعبري مع قيمة تسمية الحالة ، case labelيبدأ التنفيذ بالجملة األولى اليت تأتي بعد تلك •
التسمية.
يستمر التنفيذ بشكل طبيعي من هذا الجملة حىت نهاية switchأو حىت الجملة اكرس_ .break •
بدل_.
إذا لم يتم العثور على تطابق ،فسيتم التنفيذ في أول جملة تأتي بعد ّ
بدل_ إلى إعادة التحكم لرشط .while
كما نعلم بالفعل ،في هذا املثال ،يؤدي الخروج من ّ •
;)(char ch = getVal
;int ival = 42
{ )switch(ch
case 3.14: // error: noninteger as case label
case ival: // error: nonconstant as case label
… //
من املهم أن نفهم أن التنفيذ يتدفق عرب تسميات الحالة .بعد تطابق تسمية الحالة ،
يبدأ التنفيذ عند هذه التسمية ويستمر عرب جميع الحاالت املتبقية أو حىت يقاطعها الربنامج رصاح ًة. •
ولتجنب تنفيذ أكواد تسميات الحالة الالحقة ،يجب أن نخرب املرتجم رصاح ًة بإيقاف التنفيذ. •
في معظم الحاالت ،تكون الجملة األخرية قبل تسمية الحالة التالية هي اكرس_ .break •
تماما.
ً بدل_ االفرتايض هو املطلوب
ومع ذلك ،هناك مواقف يكون فيها سلوك ّ
يمكن أن يكون لكل تسمية حالة قيمة وحيدة فقط ، •
ولكن في بعض األحيان يكون لدينا قيمتان أو أكرث تشرتكان في مجموعة مشرتكة من اإلجراءات. •
في مثل هذه الحاالت ،نحذف جملة اكرس_ ، break •
مما يسمح للربنامج بالوقوع في تسميات حاالت متعددة. •
قمنا هنا بتكديس عدة تسميات حالة بال جمل اكرس_ .break •
سيتم تنفيذ نفس الكود عندما يكون chحر ًفا متحر ًكا. •
من املفاهيم الخاطئة الشائعة االعتقاد بأنه يتم فقط تنفيذ الجمل املرتبطة بتسمية الحالة املطابقة.
بدل_ حساب حروف العلة الخاص بنا:
على سبيل املثال ،إليك تنفيذ غري صحيح لجملة ّ
أفضل املمارسات
بالرغم من أنه ليس من الرضوري تضمني اكرس_ بعد آخر تسمية للحالة ، •
إﻻ أن الطريقة األكرث أما ًنا هي كتابة اكرس_. •
وهكذا ،إذا تمت إضافة حالة إضافية الح ًقا ،فسيكون اكرس_ في مكانه بالفعل. •
بدل_.
يتم تنفيذ الجمل اليت تلي التسمية "افرتايض" عندما ال تتطابق تسمية الحالة مع قيمة تعبري ّ
في هذا اإلصدار ،إذا لم يكن chحر ًفا متحر ًكا ،فسيبدأ التنفيذ عند التسمية افرتايض وسزنيد .otherCnt
أفضل املمارسات
قد يكون من املفيد تعريف التسمية افرتايض حىت إن لم يكن هناك عمل للحالة افرتايض.
يشري تعريف تسمية افرتايض خال للقراء الحقاً إلى أنه تم النظر في تلك الحالة.
قد ال تكون التسمية قائمة بذاتها ؛ يجب أن يسبق جملة أو تسمية حالة أخرى. •
بدل_ بحالة افرتايض ليس له عمل يقوم به ،
إذا انتهى ّ •
فيجب أن يتبع التسمية افرتايض جملة الغية أو كتلة خالية. •
بدل_
تعريف املتغري داخل بنية ّ
Variable Definitions inside the Body of a switch
اإلجابة هي أنه من غري الرشعي القفز من مكان يكون فيه املتغري باستخدام ُمهئي خارج النطاق إلى مكان يكون فيه
هذا املتغري في النطاق :
case true:
// this switch statement is illegal because
// these initializations might be bypassed
// error: control bypasses implicitly initialized variable
;string file_name
// error: control bypasses explicitly initialized variable
;int ival = 0
;int jval // ok: because jval is not initial
;break
case false:
// ok: jval is in scope but is uninitialized
jval = next_num(); // ok: assign a value to jval
if (file_name.empty()) // file_name in scope but wasn't initialized
// ...
ٍ
فعندئذ في أي وقت يقفز التحكم فيه إلى الحالة ، false إن كان هذا الكود رشعياً ، •
فإنه سيتجاوز تهيئة file_nameو .ival •
وهذه املتغريات ستكون في النطاق. •
يمكن أن تستخدم أكواد ما بعد حالة falseتلك املتغريات .مع ذلك ،لم يتم تهيئتها. •
نتيجة لذلك ،ال تسمح لنا اللغة بالقفز فوق التهيئة إن كان املتغري املهئي في النطاق عند النقطة اليت ينتقل •
إليها عنرص التحكم.
إذا احتجنا إلى تعريف متغري وتهيئته لحالة معينة ،
فيمكننا القيام بذلك عن طريق تعريف املتغري داخل كتلة ، •
وبالتالي التأكد من أن املتغري خارج النطاق عند نقطة أي تسمية الحقة. •
{ case true:
// ok: declaration statement within a statement block
;)(string file_name = get_file_name
… //
}
;break
case false:
if (file_name.empty()) // error: file_name is not in scope
التمرين :5.10
-هناك مشكلة واحدة في برنامج حساب الحروف املتحركة لدينا حيث قمنا بتطبيقه:
-ال يتم احتساب األحرف الكبرية كأحرف متحركة.
برنامجا يعد كاًل من األحرف الصغرية والكبرية كحرف متحرك مناسب
ً -اكتب
-أي ،يجب أن يحسب برنامجك كالً من " "aو " "Aكجزء من ، aCntوهكذا دواليك.
التمرين :5.11
-قم بتعديل برنامج حساب الحروف املتحركة الخاص بنا بحيث
أيض ا بحساب عدد املسافات الفارغة وعالمات التبويب واألسطر الجديدة اليت تمت قراءتها.
-يقوم ً
التمرين :5.12
-قم بتعديل برنامج حساب الحروف املتحركة الخاص بنا بحيث
-يحسب عدد مرات تكرارات التسلسالت التالية املكونة من حرفني ff :و flو .fi
التمرين :5.13
يحتوي كل برنامج في النص املمزي أدناه على خطأ برمجي شائع .قم بتحديد وتصحيح كل خطأ.
)(a
;unsigned aCnt = 0, eCnt = 0, iouCnt = 0
;)(char ch = next_text
{ )switch (ch
;case 'a': aCnt++
;case 'e': eCnt++
} ;default: iouCnt++
)(b
;)(unsigned index = some_value
{ )switch (index
case 1:
int ix = get_value(); ivec[ ix ] = index; break;
default:
ix = ivec.size()-1; ivec[ ix ] = index; }
(c)
unsigned evenCnt = 0, oddCnt = 0;
int digit = get_num() % 10;
switch (digit) {
case 1, 3, 5, 7, 9:
oddcnt++; break;
case 2, 4, 6, 8, 10:
evencnt++; break; }
(d)
unsigned ival=512, jval=1024, kval=4096;
unsigned bufsize;
unsigned swt = get_bufCnt();
switch(swt) {
case ival:
bufsize = ival * sizeof(int); break;
case jval:
bufsize = jval * sizeof(int); break;
case kval:
bufsize = kval * sizeof(int); break; }
5٫4الجمــــــــــل التكراريــــــة
5.4. Iterative Statements
صحيحا.
ً متكررا حىت يكون الرشط
ً توفر الجمل التكرارية ،املعروفة باسم الحلقات ،تنفيذًا
الجملتان طالـما_ whileو ألجل_ forتختربان الرشط قبل تنفيذ البنية. •
بينما تقوم الجملة افعل_طالـما_ do whileبتنفيذ البنية ثم اختبار رشطها. •
تقوم جملة طالـما_ whileبتنفيذ البنية بشكل متكرر طاملا كان الرشط صحيحاً .صياغتها النحوية هي :
ملحوظة
تُستخدم حلقة whileبشكل عام عندما نريد التكرار إلى ما ﻻ نهاية ،فمثال عندما نقرأ املدخالت.
أيضا عندما نريد الوصول إلى قيمة متغري التحكم في حلقة بعد انتهاءها.
تكون طالـما_ مفيدة ً •
فمثال:
غالبا ما يُشار إلى forوالجزء املوجود داخل األقواس باسم رأس .for
ً •
يجب أن تكون الجملة األولية جملة إعالن أو تعبري أو جملة خالية. •
أيضا اعتبار شكل نحوي آخر مثل
تنتهي كل من تلك الجمل بفاصلة منقوطة ،لذا يمكن ً •
بشكل عام ،يتم استخدام الجملة اﻷولية لتهيئة أو تعيني قيمة أولية يتم تعديلها على مدار الحلقة. •
بينما يعمل الرشط كعنرص تحكم في الحلقة. •
طاملا يتم تقييم الرشط على أنه صحيح ،يتم تنفيذ البنية. •
إذا أسفر أول تقييم للرشط عن خطأ ،فلن يتم تنفيذ البنية. •
يقوم التعبري عاد ًة بتعديل املتغري (ــات) املهيأ(ة) في الجملة اﻷولية واختبارهـ(ــا) في الرشط. •
يتم تقييم التعبري مع كل تكرار للحلقة. •
وكالعادة ،يمكن أن تكون البنية إما جملة واحدة أو جمالً مركبة. •
Execution Flow in a Traditional for Loop تدفق التنفيذ في حلقة ألجل_ تقليدية
ملحوظة
يجدر بنا أن نتذكر أن رؤية أي كائن معرف داخل رأس forيقترص على بنية حلقتها. •
بالتالي ،في هذا املثال ،ال يمكن الوصول إلى indexبعد اكتمال .for •
Multiple Definitions in the for Header التعريفات املتعددة في رأس حلقة ﻷجل_
كما هو حال أي إعالن آخر ،يمكن أن تعرف الجملة األولية عدة كائنات.
مع ذلك ،قد تكون الجملة األولية جملة إعالن وحيدة فقط. •
لذلك ،يجب أن يكون لجميع املتغريات نفس النوع األسايس. •
كمثال ،قد نكتب حلقة لتكرار عنارص متجه في النهاية على النحو التالي:
// remember size of v and stop when get to original last element
)for (decltype(v.size()) i = 0, sz = v.size(); i != sz; ++i
;)]v.push_back(v[i
في هذه الحلقة نعرف كالً من الفهرس ، i :واملتحكم في الحلقة ، sz :في الجملة األولية.
Omitting Parts of the for Header حذف أجراء من رأس حلقة ﻷجل_
يمكن أن يحذف رأس ﻷجل_ أياً من (أو كل) الجملة األولية ،أو الرشط أو التعبري.
فبإمكاننا استخدام جملة خالية للجملة األولية عندما تكون التهيئة غري رضورية. •
على سبيل املثال ،قد نعيد كتابة الحلقة اليت تبحث عن أول رقم سالب في متجه بحيث تستخدم : for
الحظ أن الفاصلة املنقوطة رضورية لتشري إلى عدم وجود جملة أولية. •
بشكل أكرث دقة ،تمثل الفاصلة املنقوطة جملة أولية خالية. •
أيضا ألن عمل الحلقة كلها يحدث داخل الرشط والتعبري.
في هذه الحلقة ،تكون بنية forخالية ً •
يقرر الرشط الوقت الذي يحني فيه التوقف عن البحث ويزتايد التعبري في املكرر. •
كمثال ،سنعيد كتابة حلقة whileاليت تقرأ املدخالت في متجه أعداد صحيحة :
;vector<int> v
) for (int i; cin >> i; /* no expression */
;)v.push_back(i
في هذه الحلقة ليست هناك حاجة لتعبري ألن الرشط يغري قيمة .i •
يخترب الرشط تدفق املدخالت بحيث تنتهي الحلقة عندما نقرأ كل املدخالت أو نواجه خطأ فيها. •
التمرين :5.16
-الحلقة whileجيدة بشكل خاص في التنفيذ بينما هناك رشط ما ؛
-على سبيل املثال ،عندما نحتاج إلى قراءة القيم حىت نهاية امللف.
عموما على أنها حلقة خطوة :يتخطى الفهرس نطا ًقا من القيم في مجموعة. ً -يُنظر إلى حلقة for
اصطالحيا لكل حلقة ثم أعد كتابة كل حلقة باستخدام بنية الحلقة األخرى.
ً استخداما
ً -اكتب
-إذا كان بإمكانك استخدام حلقة واحدة فقط ،فماذا ستختار؟ ملاذا ا؟
التمرين :5.17
برنامجا لتحديد ما إذا كان أحد املتجهني هو بادئة لآلخر.
ً -باستخدام متجهني من ، intsاكتب
-بالنسبة للمتجهات ذات الطول غري املتساوي ،قارن عدد عنارص املتجه األصغر.
-على سبيل املثال ،بالنظر إلى املتجهات اليت تحتوي على 0و 1و 1و 2و ، 8 ، 5 ، 3 ، 2 ، 1 ، 1 ، 0على التوالي ،
صحيحا.
ً يجب أن يعود برنامجك
قدم املعيار الجديد أبسط جملة ﻷجل_ يمكن استخدامها للتكرار عرب عنارص الحاوية أو تسلسالت أخرى.
الصياغة النحوية لجملة ألجل_للنطاق هي:
يجب أن يمثل التعبري تسلساًل ،مثل قائمة ُمهئي بأقواس ،أو مصفوفة ،أو كائن نوع مثل متجه أو سلسلة تملك
عضو بداية ونهاية تعود بمكررات.
يعرف اإلعالن متغرياً .يجب أن يكون من املمكن تحويل كل عنرص من عنارص التسلسل إلى نوع املتغري. ّ •
أسهل طريقة للتأكد من تطابق األنواع هي استخدام محدد النوع التلقائي .auto •
بهذه الطريقة سوف يستنتج املرتجم النوع بالنسبة لنا. •
مرجعيا.
ً نوعا
إذا أردنا الكتابة إلى عنارص في التسلسل ،فيجب أن يكون متغري الحلقة ً •
في كل تكرار ،يتم تعريف متغري التحكم وتهيئته على القيمة التالية في التسلسل ، •
وبعد ذلك يتم تنفيذ البنية .وكالعادة ،يمكن أن تكون البنية جملة واحدة أو كتلة. •
ينتهي التنفيذ بمجرد معالجة كل العنارص. •
لقد رأينا بالفعل العديد من هذه الحلقات ،ولكن للتأكد من تكاملها ،إليك حلقة تضاعف قيمة كل عنرص في متجه:
;}vector<int> v = {0,1,2,3,4,5,6,7,8,9
// range variable must be reference so we can write to elements
)for (auto &r : v // for each element in v
;r *= 2 // double value of each element in v
هنا يعلن رأس forعن متغري التحكم في الحلقة ، rويربطه بـ .v •
نستخدم autoللسماح للمرتجم باستنتاج النوع الصحيح لـ .r •
وألننا نريد تغيري قيمة العنارص في ، vفإننا نعلن عن rكمرجع. •
عندما نعني على rداخل الحلقة ،فإن هذا التعيني يغري العنرص الذي يرتبط به .r •
تعترب جملة افعل_طالـما_ do whileعبارة عن جملة طالـما_ whileلكن يتم اختبار رشطها بعد تنفيذ بنيتها.
وبغض النظر عن قيمة الرشط ،نقوم بتنفيذ البنية مرة على األقل .الشكل النحوي لها كما يلي:
do
statement بنية
;)رشط while (condition
ملحوظة
يمكننا كتابة برنامج يقوم بإجراء عمليات جمع (إلى ما ﻻ نهاية) باستخدام : do while
{ do
// . . .
;)mumble(foo
} while (int foo = get_foo()); // error: declaration in do condition
إذا تمكنا من تعريف املتغريات في الرشط ،فسيحدث استخدام للمتغري قبل تعريفه!
{ (b) do
// . . .
;))(} while (int ival = get_response
{ (c) do
;)(int ival = get_response
;)} while (ival
التمرين :5.19
برنامجا يستخدم حلقة do whileليطلب بشكل متكرر سلسلتني من املستخدم
ً -اكتب
-قم بإظهار السلسلة األقل من األخرى.
5٫5جمــــــــــل القفــــــز
5.5. Jump Statements
جمل القفز تقطع تدفق التنفيذ .تقدم لغة يس ++أربع جمل قفز :
اكرس_ ، breakو استمر_ ، continueو اذهب_إلى gotoسنغطيها في هذا الفصل ، •
وجملة ِ
أعد ، returnاليت سنتناولها في الفصل السادس. •
;string buf
{ ))(while (cin >> buf && !buf.empty
{ )]switch(buf[0
case '-':
// process up to first blank
{ )for (auto it = buf.begin()+1; it != buf.end(); ++it
)' ' == if (*it
break; // #1, leaves for loop
… //
}
// break #1 transfers control here
// remaining '-' processing:
break; // #2, leaves switch statement
case '+':
… //
} // end switch
// end of switch: break #2 transfers control here
} // end while
تنهي اكرس_ املصنفة 1#حلقة ﻷجل_ اليت تتبع تسمية حالة السالب. •
بدل_ املتضمنة وفي الواقع ال ينهي حىت معالجة الحالة الحالية.
فهو ال ينهي جملة ّ •
إضافيا للتعامل مع السالب أو اكرس_ اليت
ً تستمر املعالجة بأول جملة تأتي بعد ﻷجل_ ،واليت قد تكون كوداً •
تكمل هذه الحالة.
بدل_ لكنها ال تنهي حلقة whileاملتضمنة.
تنهي اكرس_ املصنفة ّ 2# •
تستمر املعالجة بعد اكرس_ هذه عن طريق تنفيذ الرشط في .while •
الجملة استمر_ تقطع التكرار الحالي ؛ حيث يبقى التنفيذ داخل الحلقة.
في حالة whileأو ، do whileيستمر التنفيذ من خالل تقييم الرشط. •
أما في حلقة forالتقليدية ،يستمر التنفيذ عند التعبري داخل رأس .for •
وفي حلقة forالنطاق ،يستمر التنفيذ عن طريق تهيئة متغري التحكم على العنرص التالي في التسلسل. •
;string buf
{ ))(while (cin >> buf && !buf.empty
)'_' =! ]if (buf[0
continue; // get another input
// still here? input starts with underscore; process buf . .
}
أفضل املمارسات
ينبغي أال تستخدم الربامج جمل gotoـ حيث تجعلها صعبة الفهم والتعديل.
;goto label
يعرف جملة.
معرف ّ
حيث التسمية labelهي ّ
ٍ
متبوع بنقطتني: أما الجملة املسماة فيمكن أن تكون أي جملة يسبقها معرف
… //
;goto end
int ix = 10; // error: goto bypasses initialized variable definition
end:
// error: code here could use ix but goto bypassed its declaration
;ix = 42
االستثناءات هي حاالت شاذة وقت التشغيل تحصل خارج األداء الطبيعي للربنامج -مثل فقد اتصال قاعدة البيانات
أو مواجهة مدخالت غري متوقعة .-
• يمكن أن يكون التعامل مع السلوك الشاذ أحد أصعب أجزاء تصميم أي نظام.
يتم استخدام معالجة االستثناءات بشكل عام عندما يكتشف جزء ما من الربنامج مشكلة ال يمكنه حلها، •
وتكون املشكلة بحيث ال يمكن متابعة جزء االكتشاف من الربنامج. •
في مثل هذه الحاالت ،يحتاج جزء الكشف إلى وسيلة لإلشارة إلى حدوث يشء ما وأنه ال يمكن أن يستمر. •
عالوة على ذلك ،يحتاج جزء الكشف إلى وسيلة لإلشارة إلى املشكلة ؛ •
دون معرفة أي جزء من الربنامج سيتعامل مع الحالة االستثنائية. •
بعد اإلشارة إلى ما حدث ،يتوقف جزء الكشف عن املعالجة. •
الربنامج الذي يحتوي على كود قد يثري استثناء (عادة) له جزء آخر للتعامل مع كل ما حدث.
على سبيل املثال ،إن كانت املشكلة عبارة عن مدخالت غري صالحة ، •
قد يطلب جزء املعالجة من املستخدم توفري املدخالت الصحيحة. •
إذا فقدت قاعدة البيانات ،فقد ينبه جزء املعالجة املشغل. •
يدعم التعامل مع االستثناءات هذا التعاون بني الكشف عن أجزاء الربنامج والتعامل معها.
في يس ، ++تتضمن معالجة االستثناءات : •
طرح التعبريات : throw expressions •
يستخدمها جزء الكشف ليرش إلى أنه واجه شيًئ ا ال يمكنه التعامل معه .نقول أن طرح يثري استثناء. •
جرب_ : try كتل ّ •
يستخدمها جزء املعالجة للتعامل مع استثناء. •
جرب_ بالكلمة tryوتنتهي بجملة التقط_ catchأو أكرث.
تبدأ كتلة ّ •
وكمثال بسيط ،تذكر الربنامج الوارد في الفقرة 1.5.2الذي جمع كائين عنرص املبيعات ،
قام ذلك الربنامج بفحص ما إذا كانت السجالت اليت قرأها تشري إلى نفس الكتاب. •
فإن لم تكن كذلك ،سيطبع رسالة ويخرج. •
في برنامج أكرث واقعية ،يمكن فصل جزء يضيف عنارص عن جزء يدير التفاعل مع املستخدم. •
في تلك الحالة ،قد نعيد كتابة الفحص لطرح استثناء بدال ً من إعادة مؤرش خطأ : •
نوع خطأ_وقت_التشغيل هو أحد أنواع استثناءات املكتبة القياسية ويتم تعريفه في عنوان .stdexcept
سيكون لدينا املزيد لنقوله عن هذه األنواع بعد قليل. •
يجب أن نهئي خطأ_وقت_تشغيل عن طريق إعطائه سلسلة نصية أو سلسلة أحرف على نمط اليس. •
توفر هذه السلسلة معلومات إضافية حول ماهية املشكلة. •
{ try
program-statements
{ ) } catch ( exception-declaration
handler-statements
{ ) } catch ( exception-declaration
handler-statements
… } //
جرب_ بكلمة tryمتبوعة بكتلة -كالعادة -عبارة عن سلسلة جمل محاطة بأقواس معقوفة.
تبدأ كتلة ّ •
جرب_ قائمة بجملة التقط_ catchأو أكرث.
تأتي بعد كتلة ّ •
تتكون التقط_ من ثالثة أجزاء: •
كلمة ، catchوإعالن كائن (قد يكون بدون اسم) بني قوسني (يشار إليه بإعالن االستثناء) ،وكتلة. •
عند تحديد التقاط ملعالجة استثناء ،يتم تنفيذ الكتلة املرتبطة. •
جرب_.
وبمجرد انتهاء التقط_ ،يستمر التنفيذ بجملة ما بعد الجملة التقط_ األخرية من كتلة ّ •
في املثال السابق ،استخدمنا throwلتجنب جمع عنرصي مبيعات يمثالن كتابني مختلفني.
تخيلنا أن جزء الربنامج الذي جمع عنرصي مبيعات كان منفصالً عن الجزء الذي يتواصل مع املستخدم. •
قد يحتوي الجزء الذي يتفاعل مع املستخدم على رمز مشابه ملا يلي للتعامل مع االستثناء الذي تم طرحه: •
جرب_ .try
املنطق العادي للربنامج الذي يدير التفاعل مع املستخدم يظهر داخل كتلة ّ •
استثناء من نوع .runtime_error
ً جرب_ ألنه قد يطرح
يتم تغليف هذا الجزء من الربنامج داخل ّ •
جرب_ هذه على جملة التقط_ catchواحدة ،تعالج استثناءات نوع خطأ_وقت_تشغيل.
تحتوي كتلة ّ •
جرب_ في خطأ_وقت_تشغيل.
يتم تنفيذ الجمل في كتلة ما بعد التقط_ إذا تسبب الكود املوجود داخل كتلة ّ •
يعالج التقاطنا الخطأ عرب طباعة رسالة ومطالبة املستخدم باإلشارة إلى ما إذا كان سيستمر أم ال. •
إذا قام املستخدم بإدخال " ، "nفسيتم تنفيذ الكرس ونخرج من .while •
عدا ذلك ،ينخفض التنفيذ إلى قوس اإلغالق من ، while •
والذي سينقل التحكم مرة أخرى إلى رشط whileللتكرار التالي. •
استثناء.
ً جرب_ قبل مواجهة كود يطرح
في األنظمة املعقدة ،قد يمر مسار تنفيذ الربنامج عرب عدة كتل ّ
جرب_ ،
جرب_ دالة بها كتلة ّ
فعلى سبيل املثال ،قد تستدعي كتلة ّ •
جرب_ خاصة بها ،وهكذا.
وبدورها تستدعي أخرى بكتلة ّ •
تعر ف مكتبة يس ++عدة فئات تستخدمها لإلبالغ عن مشكالت تمت مواجهتها في الدوال في املكتبة القياسية.
ّ
أيضا إلى استخدامها في الربامج اليت نكتبها.
تهدف فئات االستثناء هذه ً •
يتم تحديد هذه الفئات في أربعة عناوين: •
: The exception header - 1
يعرف النوع األكرث عمومية من فئة االستثناء املسماة .exception •
حيث أنها تشري فقط إلى حدوث استثناء لكنها ال تقدم معلومات إضافية. •
: The stdexcept header - 2
تعرف العديد من فئات استثناءات األغراض العامة ،واليت تم رسدها في الجدول .5.1 •
range_error خطأ وقت التشغيل :نتيجة تم إنشاؤها خارج نطاق القيم ذات املعىن.
التمرين :5.24
-راجع برنامجك لطرح استثناء إذا كان الرقم الثاني صفرًا.
-اخترب برنامجك بمدخالت صفرية ملعرفة ما يحدث على نظامك إذا لم يتم اكتشاف استثناءك.
التمرين :5.25
-قم بمراجعة برنامجك من التمرين السابق الستخدام كتلة tryاللتقاط االستثناء.
-يجب أن تطبع جملة catchرسالة إلى املستخدم وتطلب منه توفري رقم جديد وتكرار الكود داخل .try
ملخــــــــــص الفصــــــــــل
Chapter Summary
توفر يس ++عد ًدا محدو ًدا من الجمل .تؤثر معظمها على تدفق التحكم داخل الربنامج:
الجمل طالـما_ whileو ﻷجل_ forو افعل_طالـما_ do whileتوفر التنفيذ التكراري. •
وبدل_ switchالتنفيذ املرشوط.
توفر الجملتان إذا_ ّ if •
توفر الجملة استمر_ continueإيقاف التكرار الحالي للحلقة. •
بدل_.
توفر الجملة اكرس_ breakخروجاً من حلقة أو جملة ّ •
توفر الجملة اذهب_إلى gotoنقل عنرص التحكم إلى جملة مسماة. •
جرب_
جرب_ tryو التقط_ catchتعريفاً لكتلة ّ توفر الجمل ّ •
وتتضمن سلسلة من جمل قد تؤدي إلى استثناء. •
وتهدف الجملة (الجمل) التقط_ catchإلى معالجة استثناء (ــات) قد تطرحها األكواد املرفقة. •
الجملة طرح التعبري ، throw expression •
تخرج من كتلة من اﻷكواد ،وتحول التحكم إلى جملة التقط_ catchمرتبطة. •
الجملة ِ
أعد ، returnتوقف تنفيذ دالة. •
أعد returnفي الفصل السادس). (سنغطي جمل ِ •
بدل_.
تسمية الحالة :تعبري ثابت يتبع كلمة caseاألساسية في جملة ّ
case label
بدل_ نفس القيمة.
ال يجوز أن يكون لتسميات حالة في نفس جملة ّ
جملة التقط_ :الكلمة األساسية catchوإعالن استثناء بني قوسني وكتلة من الجمل.
catch clause يقوم الكود املوجود داخل جملة التقط_ بكل ما هو رضوري للتعامل مع استثناء من النوع املحدد
في إعالن االستثناء الخاص به.
compound
جملة مركبة :مرادف للكتلة.
statement
متدلية (وإﻻ_) :تستخدم لإلشارة إلى مشكلة كيفية معالجة جمل إذا_ املتداخلة اليت يوجد فيها
ifsأكرث من .else
dangling else دائما إقران elseبأقرب ما سبق مما ال مثيل له.
ً في يس ، ++يتم
الحظ أنه يمكن استخدام األقواس املتعرجة إلخفاء إذا_ الداخلي بشكل فعال إذا كان األمر كذلك
بحيث يمكن للمربمج التحكم في ما إذا كان يجب أن يتطابق مع .else
do while جملة افعل_طالـما_ :مثل جملة طالـما_ ،فيما عدا أنه يتم اختبار الرشط في نهاية الحلقة وليس
statement في بدايتها .يتم تنفيذ الجملة داخل افعل_طالـما_ مرة واحدة على األقل.
exception فئات االستثناء :مجموعة فئات تحددها املكتبة القياسية الستخدامها لتمثيل األخطاء.
classes يرسد الجدول 5.1فئات استثناءات األغراض العامة.
exception إعالن االستثناء :إعالن في جملة التقط_ .catchيعرف هذا اإلعالن نوع استثناءات يمكن
declaration اللتقط_ معالجتها.
exception معالج االستثناء :كود يتعامل مع استثناء مرفوع في جزء آخر من الربنامج.
handler مرادف ملصطلح التقط_.
exception safe يستخدم مصطلح االستثناء اآلمن لوصف برامج تترصف بشكل صحيح عند طرح استثناءات.
expression
جملة تعبريية متبوعة بفاصلة منقوطة .تؤدي جملة التعبري إلى تقييم التعبري.
statement
جملة اذهب_إلى :تتسبب في نقل غري مرشوط للتحكم إلى جملة معنونة محددة في مكان آخر
goto statement
في نفس الدالة goto .تشوش على تدفق التحكم داخل الربنامج وينبغي تجنبها.
if else جملة إذا_وإﻻ_ " :تنفيذ مرشوط" للشفرة بعد " ifأو بعد ، "else
statement اعتما ًد ا على القيمة الحقيقية للرشط.
صحيحا ،
ً بناء على قيمة رشط محدد .إن كان الرشط
ً جملة إذا_ :تنفيذ مرشوط
if statement
فسيتم تنفيذ بنية إذا_ .إذا لم يكن كذلك ،فإن التحكم يتدفق إلى جملة تأتي بعد إذا_.
range for
جملة ﻷجل_ للنطاق :جملة تتكرر عرب تسلسل.
statement
بد ل_ :جملة رشطية تبدأ بتقييم التعبري الذي يتبع الكلمة .switchجملة ّ
switch ينتقل عنرص التحكم إلى الجملة املسماة بتسمية حالة تطابق قيمة التعبري.
statement إذا لم يكن هناك تسمية مطابقة ،فسيستمر التنفيذ في التسمية "افرتايض" ،إن وجدت ،
بدل_ إن لم توجد تسمية "افرتايض”. أو يخرج من ّ
إنهاء وظيفة املكتبة اليت يتم استدعاؤها في حالة عدم اكتشاف استثناء.
terminate
إلنهاء أو إحباط الربنامج.
throw طرح تعبري :يقطع مسار التنفيذ الحالي .يقوم كل طرح بطرح كائن وتنقل التحكم إلى أقرب
expression جملة التقط_ catchمتضمنة يمكنها التعامل مع نوع االستثناء الذي تم طرحه.
جرب_ :كتلة محاطة بالكلمة األساسية tryوواحد أو أكرث من جمل التقط_. كتلة ّ
استثناء وكان أحد جمل التقط_ يتطابق مع نوعه،
ً جربإذا أثار الكود املوجود داخل كتلة ّ
try block
فسيتم معالجته بواسطة التقط_ هذا .عدا ذلك ،
جرب متضمنة أو بإنهاء الربنامج.
يتم التعامل مع االستثناء بواسطة كتلة ّ
جملة طالـما_ :تكرار ينفذ الجملة الهدف طاملا أن الرشط املحدد صحيح.
while statement
يتم تنفيذ الجملة صفر أو أكرث من املرات ،اعتما ًدا على صحة الرشط.