اذهب إلى المحتوى

تتوفَّر تَعْليمَتين للتَفْرِيع (branching statements) بلغة الجافا، وفي هذا القسم، سنتناول تَعْليمَة التَفْرِيع الأولى if، والتي قد سبق وتَعرَّضنا لها بالفعل بالقسم ٣.١.

تُكتب تَعْليمَة التَفْرِيع الشَّرْطيّة if بالصياغة التالية:

if ( <boolean-expression> )
     <statement-1>
else
     <statement-2>

تُسمى هذه الصياغة من if بتَعْليمَة التَفْرِيع الثنائي (two-way branch)، وكما هو مُتوقَّع، يُمكِن للتعليمتين و -بالأعلى- أن تَكونا كُتلَتي البِنْية (block statement). لاحِظ أنه من المُمكن حَذْف الجزء else المُكوَّن من الكلمة else والتعليمة .

مشكلة تَّدَلِّي else

لمّا كانت تَعْليمَة if هي بالنهاية مُجرَّد تَعْليمَة، فإنه من المُمكن لإحدى التعليمتين أو أو حتى كلتيهما أن يَكونا تَعْليمَة if بذاتهما، ولكن قد يتَسبَّب ذلك بحُدوث مشاكل في بعض الأحيان.

فمثلًا، إذا اِستخدَمت تَعْليمَة if بدون الجزء else محل التعليمة ، كما في الشيفرة التالية:

if ( x > 0 )
    if (y > 0)
       System.out.println("First case");
else
    System.out.println("Second case");

قد يُعطيك اِستخدَامك للمسافات البادئة (indentation) -ببداية كل سطر من الشيفرة- انطباعًا خاطئًا بأن الجزء else هو النصف الآخر من تَعْليمَة if (x > 0‎)‎، لكن هذا غَيْر صحيح. لا يُعطِي الحاسوب في الواقع أيّ اعتبار لتلك المسافات، وإنما يَتبِّع -في هذه الحالة بالتَحْدِيد- قاعدة بسيطة، وهي ربْط الجزء else بأقرب تَعْليمَة if ليس لديها جزء else خاص بها، مما يَعني أنه سيَربُط الجزء else بتَعْليمَة if (y > 0)‎؛ لأنها الأقرب. ولهذا يَقرأ الحاسوب التَعْليمَات بالأعلى كما لو كانت مُرَتَّبة على النحو التالي:

if ( x > 0 )
    if (y > 0)
       System.out.println("First case");
    else
        System.out.println("Second case");

تستطيع مع ذلك إجبار الحاسوب على اِستخدَام التفسير الآخر بتَضْمِين تَعْليمَة if الداخلية داخل كُتلَة (block)، كالتالي:

if ( x > 0 ) {
    if (y > 0)
       System.out.println("First case");
}
else
    System.out.println("Second case");

تختلف بالطبع نتائج تَعْليمَتي if السابقتين. فمثلًا إذا كانت قيمة المُتَغيِّر x أقل من أو تُساوِي الصفر، لا تَطبع التَعْليمَة الأولى شيئًا، بينما تَطبع الثانية السِلسِلة النصية "Second case".

التفريع المتعدد (Multiway Branching)

من الجهة الآخرى، تُصبِح الأمور أكثر تشويقًا عندما تَستخدِم تَعْليمَة if محل التعليمة ، وفي هذه الحالة، ستبدو تَعْليمَة التَفْرِيع (branching) كالتالي -ربما بدون الجزء else الأخير-:

if ( <boolean-expression-1> )
     <statement-1>
else
     if ( <boolean-expression-2> )
         <statement-2>
     else
         <statement-3>

ولمّا كان الحاسوب لا يَهتم بطريقة تَنْسِيق الشيفرة على الصفحة، فتقريبًا دائمًا ما يُكتَب المثال السابق بالصيغة التالية:

if ( <boolean-expression-1> )
     <statement-1>
else if ( <boolean-expression-2> )
     <statement-2>
else
     <statement-3>

تُسمى هذه الصياغة من if -بالأعلى- بتَعْليمَة التَفْرِيع الثلاثي (three-way branch)، وينبغي أن تُفكر بها كتَعْليمَة واحدة؛ فبالنهاية، ستُنفَّذ واحدة فقط من التعليمات الثلاثة و و أثناء تَّنْفيذ تلك التَعْليمَة. تُحسَب أولًا قيمة التعبير ، فإذا كانت تؤول إلى القيمة المنطقية true، سيُنفِّذ الحاسوب التعليمة ، ثم سيَقفِز مباشرة إلى نهاية تَعْليمَة if الخارجية مُتخَطِّيًا بذلك العبارتين الآخريتين تمامًا. أما إذا آلت قيمتها إلى القيمة المنطقية false، فإنه سيتَخَطَّى التعليمة فقط، وينتقل إلى تَعْليمَة if الثانية المُتداخِلة (nested)؛ ليَفحْص قيمة التعبير ، ويُقرِّر ما إذا كان سيُنفِّذ التعليمة أم .

مثلًا، يَطبع المثال التالي واحدة من ثلاث رسائل مُحتمَلة وفقًا لقيمة المُتَغيِّر temperature:

if (temperature < 50)
   System.out.println("It's cold.");
else if (temperature < 80)
   System.out.println("It's nice.");
else
   System.out.println("It's hot.");

على سبيل المثال، إذا كان المُتَغيِّر temperature يَحمِل القيمة ٤٢، فسيَتحقَّق أول شَّرْط، ومِنْ ثَمَّ تُطبَع الرسالة "It's cold"، لينتقل بَعْدها الحاسوب إلى ما بعد التَعْليمَة مُتخَطِّيًا بقيتها، وبدون حتى محاولة اختبار الشَّرْط الثاني. أما إذا كانت قيمته تُساوِي ٧٥، فلن يتحقَّق أول شَّرْط، لذلك سينتقل الحاسوب لاختبار الشَّرْط الثاني، الذي سيتحقَّق لتتم طباعة الرسالة "It's nice"، ثم سيتَخَطَّى بقية التَعْليمَة. أخيرًا إذا كانت قيمته تُساوِي ١٧٣، لا يتحقَّق أي من الشَّرْطين، وتُطبَع الرسالة "It's hot" (لو لم تَكن دوائره الكهربية قد اِحترقَت بفِعْل الحرارة).

يُمكنك الاستمرار بإضافة المزيد من عبارات else-if بأيّ عَدَد، وفي تلك الحالة، يُطلَق عليها اسم تَعْليمَة التَفْرِيع المُتعدِّد (multiway branches)، كالتالي:

if ( <test-1> )
     <statement-1>
else if ( <test-2> )
     <statement-2>
else if ( <test-3> )
     <statement-3>
  .
  . // أضف المزيد
  .
else if ( <test-N> )
     <statement-N>
else
     <statement-(N+1)>

الاختبارات ** **-بالأعلى- هي تعبيرات منطقية (boolean expressions)، تُحسَب قيمها واحدة تلو الآخرى، إلى أن تؤول إحداها إلى القيمة المنطقية true، فيُنفِّذ عندها الحاسوب التعليمة ‎> التي تُناظِر الاختبار ‎> المُتحقِّق ويتَخَطَّى البقية. أمّا إذا لم تؤول أي واحدة منها إلى القيمة المنطقية true، تُنفَّذ عندها التعليمة (n+1)‎> الموجودة ضِمْن الجزء else. لاحِظ أنه دائمًا ما ستُنفَّذ واحدة فقط لا غَيْر من كل هذه التعليمات ‎>، وهذا هو سبب تسميتها باسم تَعْليمَة التَفْرِيع المُتعدِّد (multiway branch). يمُكنك أيضًا حَذْف الجزء else الأخير، ولكن -في تلك الحالة- إذا لم تتحقَّق أيّ من التعبيرات المنطقية، وآلت جميعا إلى القيمة المنطقية false، فلن تُنفَّذ أيّ عبارة نهائيًا. يُمكن بالطبع لأيّ من التعليمات ‎> أن تكون كُتليّة البِنْية (block)، أي مُكوَّنة من أيّ عدد من التَعْليمَات طالما أُحيطَت بزوج من الأقواس. ‎>

قد يَنْتابك شُعور بالارتباك لوجود الكثير من قواعد الصياغة (syntax) الجديدة هنا، ولكن أَضمَن لك أنه مع قليل من الممارسة، ستعتاد عليها. يُمكنك أيضًا أن تُلقي نظرة على المُخطط التالي، والذي يُوضِح مَسار التحكُّم (flow control) أثناء تَّنْفيذ الصيغة الأعم من تَعْليمَة if..else if والمعروفة باسم تَعْليمَة التَفْرِيع المُتعدِّد:

001Multiway_If_Flow_Control.png

أمثلة

لنفْترَض أن لدينا ثلاثة مُتَغيِّرات x و y و z من النوع العددي int، يَحتوِي كل منها على قيمة عددية معينة. المطلوب هو طباعة قيم المُتَغيِّرات الثلاثة بحيث تكون مُرَتَّبة ترتيبًا تصاعديًا. فمثلًا، إذا كانت قيم المُتَغيِّرات هي ٤٢ و ١٧ و ٢٠، فلابُدّ من طباعتها على الترتيب ١٧ و ٢٠ و ٤٢.

لحل هذه المسألة، سنحاول الإجابة على السؤال التالي: "لنتخيل أن لدينا قائمة مُرَتَّبة بالفعل، فبأيّ مكان يَنبغي للمُتَغيِّر x أن يقع؟" ببساطة، إذا كانت قيمة المُتَغيِّر x أصغر من قيمة كلا المُتَغيِّرين y و z، فإنه سيأتي بأول القائمة، أما إذا كان أكبر من كليهما، فإنه سيأتي بذيل القائمة، وأخيرًا، سيأتي بوسط القائمة في أيّ حالة غَيْر تلك الحالتين. يُمكن التعبير عن الحالات الثلاثة السابقة بتَعْليمَة التَفْرِيع الثلاثي if، مع ذلك ما يزال أمامنا تحديًا لإيجاد طريقة نُحدِّد من خلالها ترتيب طباعة المُتَغيِّرين y و z. انظر الشيفرة الوهمية (pseudocode):

if (x < y && x < z) {
    // ‫اطبع x متبوعة بكلا من y و z بترتيبها الصحيح
    output x, followed by y and z in their correct order
}
else if (x > y && x > z) {
    // ‫اطبع y و z بترتيبها الصحيح متبوعين بقيمة x
   output y and z in their correct order, followed by x
}
else {
    // ‫اطبع x بين y و z بترتيبها الصحيح
    output x in between y and z in their correct order
}

يتطلب تَحْدِيد ترتيب طباعة المُتَغيِّرين y و z تَعْليمَة if آخرى داخلية. انظر الشيفرة التالية بلغة الجافا:

if (x < y && x < z) {        // ‫إذا كانت x بالبداية
    if (y < z)
       System.out.println( x + " " + y + " " + z );
    else
       System.out.println( x + " " + z + " " + y );
}
else if (x > y && x > z) {   // ‫إذا كانت x بالنهاية
    if (y < z)
       System.out.println( y + " " + z + " " + x );
    else
       System.out.println( z + " " + y + " " + x );
}
else {                       // ‫إذا كانت x في الوسط
    if (y < z)
       System.out.println( y + " " + x + " " + z);
    else
       System.out.println( z + " " + x + " " + y);
}

حَاوِل اختبار ما إذا كانت الشيفرة بالأعلى ستَعمَل بشكل سليم حتى في حالة وجود أكثر من مُتَغيِّر يَحمِل نفس القيمة. عمومًا إذا كان هناك مُتَغيِّرين بنفس القيمة، فإنه لم يَعُدْ مهمًا بأيّ ترتيب سيَتِمّ طباعتهما.

بخلاف اللغات الطبيعية التي تَسمَح بكتابة جملة مثل "إذا كان x أصغر من y و z"، لا يُمكنك أن تَفعَل الشيء نفسه -أيّ كتابة التعبير if (x < y && z)‎- بلغة الجافا. لا تَسير الأمور بهذه البساطة، فلابُدّ أن يَستقبِل العَامِل (operator) المنطقي && مُعامِلين منطقيين (boolean)، ولهذا ستحتاج إلى إِجراء الاختبارين x<y و x<z بشكل منفصل، ثم تُطبِّق العَامِل المنطقي && على نتيجتيهما.

ربما تَتَّخذ منحى آخر لحل نفس المسألة، وذلك بمحاولة الإجابة على السؤال: "بأيّ ترتيب يَنبغي طباعة المُتَغيِّرين x و y؟". بمُجرَّد أن تتَوصَّل لإجابة، سيتبقَّى فقط أن تُحدِّد مكان المُتَغيِّر z. انظر الشيفرة التالية بلغة الجافا:

if ( x < y ) {  // x comes before y
   if ( z < x )   // z comes first
      System.out.println( z + " " + x + " " + y);
   else if ( z > y )   // z comes last
      System.out.println( x + " " + y + " " + z);
   else   // z is in the middle
      System.out.println( x + " " + z + " " + y);
}
else {          // y comes before x
   if ( z < y )   // z comes first
      System.out.println( z + " " + y + " " + x);
   else if ( z > x )  // z comes last
      System.out.println( y + " " + x + " " + z);
   else  // z is in the middle
      System.out.println( y + " " + z + " " + x);
}

تتوفَّر عادةً عدة طرائق وأساليب مختلفة لحل نفس المشكلة. فمثلًا، بالمثال السابق، تَعرَّضنا لحلّين فقط ضِمْن عدة حلول مُحتمَلة آخرى كثيرة. فمثلًا، قد يقوم حل آخر ثالث بتبديل قيمة (swap) المُتَغيِّرين x و y إذا كانت قيمة x أكبر من قيمة y، ومِنْ ثَمَّ سيكون من الضروري طباعة قيمة المُتَغيِّر x قبل y.

سنحاول أخيرًا كتابة برنامج كامل يَستخدِم تَعْليمَة if بطريقة مُشوِّقة. هدف البرنامج عمومًا هو تَحْوِيل قياسات الطول (measurements of length) من إحدى وَحَدات قياس الطول (units of measure) إلى آخرى، فمثلًا من المِيل (miles) إلى اليَارْدَة (yards)، أو من البُوصَة (inches) إلى القَدَم (feet). سنحتاج بالتأكيد أن نكون أكثر تحديدًا بخُصوص مُتطلَّبات البرنامج؛ فما تزال المسألة غَيْر واضحة المعالِم حتى الآن، ولهذا سنفْترَض أن البرنامج يتَعامَل فقط مع وَحَدات القياس التالية: البُوصَة، والقَدَم، واليَارْدَة، والمِيل؛ وسيكون من السهل إضافة المزيد منها فيما بَعْد. سيُدْخِل المُستخدِم قياس الطول بأي وَحدة من وَحَدات القياس المسموح بها، كأن يَكتُب "١٧ قدم" أو "٢.٧٣ ميل"، ربما بَعْدها قد تَطلُب من المُستخدِم إِدْخَال اسم وَحدة القياس المطلوب التَحْوِيل إليها، بحيث تُطبَع كخَرْج (output) للبرنامج. لكننا في الواقع سنكتفي بطباعة قياس الطول بجميع وَحَدات القياس المسموح بها؛ وذلك في محاولة لتبسيط المسألة. انظر الخوارزمية التالية المبدئية:

// اقرأ كلا من قياس الطول ووحدة القياس المستخدمة
Read the user's input measurement and units of measure
// حول قيمة قياس الطول المعطاة إلى وحدات القياس الأخرى
Express the measurement in inches, feet, yards, and miles
// اطبع قياسات الطول بالوحدات الأربعة
Display the four results

لابُدّ أن يَستقبِل البرنامج مُدْخَلين (input) من المُستخدِم، هما قياس الطول ذاته بالإضافة إلى وَحدة القياس المُستخدَمة (units of measure)، ولهذا تُستخدَم الدالتين TextIO.getDouble()‎ و TextIO.getlnWord()‎؛ لقراءة كلًا من قياس الطول العددي واسم وَحدة القياس من نفس السَطْر على الترتيب.

سنبدأ دائمًا بتَحْوِيل قياس الطول المُعْطى إلى إِحدى وَحَدات قياس الطول -ولتكن البُوصَة-؛ وذلك لتوحيد الخطوات التالية المسئولة عن التَحْوِيل إلى وَحَدات القياس الأخرى. يَلزَمنا الآن فقط تَحدِّيد وَحدة القياس التي أَدْخَل بها المُستخدِم قياس الطول؛ وذلك لنتمكن من تَحْوِيلها إلى وَحدة البُوصَة. بَعْد إجراء ذلك التَحْوِيل، سيكون من السهل تَحْوِيل قياس الطول بوَحدة البُوصَة إلى كلًا من القَدَم، واليَارْدَة، والمِيل. اُنظر الخوارزمية التالية:

Let measurement = TextIO.getDouble()
Let units = TextIO.getlnWord()
// إذا اسم وحدة القياس المعطى هو البوصة
if the units are inches
   Let inches = measurement
// إذا اسم وحدة القياس المعطى هو القدم
else if the units are feet
   Let inches = measurement * 12         // 12 inches per foot
// إذا اسم وحدة القياس المعطى هو الياردة
else if the units are yards
   Let inches = measurement * 36         // 36 inches per yard
// إذا اسم وحدة القياس المعطى هو الميل
else if the units are miles
   Let inches = measurement * 12 * 5280  // 5280 feet per mile
// إذا لم يكن اسم وحدة القياس المعطى أي من القيم الأربعة السابقة
else
   // اسم وحدة القياس المعطى غير صالح
   The units are illegal!
   // اطبع رسالة خطأ واوقف المعالجة
   Print an error message and stop processing
// إجراء التحويلات
Let feet = inches / 12.0
Let yards = inches / 36.0
Let miles = inches / (12.0 * 5280.0)
// اعرض النتائج
Display the results

لمّا كنا سنقرأ اسم وَحدة القياس المُعْطاة إلى المُتَغيِّر units، وهو من النوع String، فسنحتاج إلى إجراء موازنة نصية (comparison) لتَحدِّيد وَحدة القياس المُناظِرة. تُستخدَم الدالة units.equals("inches")‎ لفَحْص ما إذا كانت قيمة المُتَغيِّر units تُساوِي السِلسِلة النصية "inches"، لكن لا يَنطوِي إِلزام المُستخدِم على إِدْخَال الكلمة "inches" حرفيًا على أفضل تجربة للمُستخدِم (user experience)؛ فمن الأفضل أن نَسمَح له بكتابة كلمات أخرى مثل "inch" أو "in"، ولذلك سنُجري الفَحْص على التعبير المنطقي التالي:

units.equals("inches") || units.equals("inch") || units.equals("in")‎

وذلك للسماح بالاحتمالات الثلاثة. يُمكننا أيضًا أن نَسمَح له بكتابة وَحدة القياس بحروف كبيرة (upper case) مثل "Inches" أو "IN" إِمّا عن طريق تَحْوِيل السِلسِلة النصية المُعْطاة units إلى حروف صغيرة (lower case) قبل إجراء الفَحْص، أو باِستخدَام الدالة units.equalsIgnoreCase للموازنة بدلًا من units.equals.

تَسمَح النسخة النهائية من البرنامج للمُستخدِم بتَكْرار عمليتي الإِدْخَال والطباعة أكثر من مرة؛ حيث سيَتوقَف البرنامج فقط عند إِدْخَال القيمة صفر. كل ما تَطلبه الأمر هو إِحاطة الخوارزمية بالأعلى ضِمْن حَلْقة التَكْرار while، والتأكد من إِيقافها عندما يُدخِل المُستخدِم القيمة صفر. اُنظر الشيفرة بالكامل:

import textio.TextIO;

public class LengthConverter {

    public static void main(String[] args) {

        double measurement;  // قياس الطول المعُطى
        String units;        // اسم وحدة قياس المعطاة

        // قياس الطول بوحدات القياس الأربعة المتاحة
        double inches, feet, yards, miles;  

        System.out.println("Enter measurements in inches, feet, yards, or miles.");
        System.out.println("For example:  1 inch    17 feet    2.73 miles");
        System.out.println("You can use abbreviations:   in   ft  yd   mi");
        System.out.println("I will convert your input into the other units");
        System.out.println("of measure.");
        System.out.println();

        while (true) {

            // اقرأ مُدخَل المستخدم 
            System.out.print("Enter your measurement, or 0 to end:  ");
            measurement = TextIO.getDouble();
            if (measurement == 0)
                break;  // ‫اِنهي حلقة while
            units = TextIO.getlnWord();            
            units = units.toLowerCase();  // صغر الحروف

            // حول قياس الطول المعطى إلى وحدة البوصة
            if (units.equals("inch") || units.equals("inches") 
                || units.equals("in")) {
                inches = measurement;
            }
            else if (units.equals("foot") || units.equals("feet") 
                     || units.equals("ft")) {
                inches = measurement * 12;
            }
            else if (units.equals("yard") || units.equals("yards") 
                     || units.equals("yd")) {
                inches = measurement * 36;
            }
            else if (units.equals("mile") || units.equals("miles") 
                     || units.equals("mi")) {
                inches = measurement * 12 * 5280;
            }
            else {
                System.out.println("Sorry, but I don't understand \"" 
                                   + units + "\".");
                continue;  // ‫عد إلى بداية حلقة while
            }

            // حوِّل قياس الطول بوحدة البوصة إلى وحدات القياس الآخرى
            feet = inches / 12;
            yards = inches / 36;
            miles = inches / (12*5280);

            // اطبع قياس الطول بوحدات القياس الأربعة
            System.out.println();
            System.out.println("That's equivalent to:");
            System.out.printf("%14.5g inches%n", inches);
            System.out.printf("%14.5g feet%n", feet);
            System.out.printf("%14.5g yards%n", yards);
            System.out.printf("%14.5g miles%n", miles);
            System.out.println();

        } // ‫نهاية تعليمة while

        System.out.println();
        System.out.println("OK!  Bye for now.");

    } // ‫نهاية برنامج main

} // ‫نهاية الصنف LengthConverter

لمّا كنا غَيْر مُتحكِّمين بقيم الأعداد الحقيقية (real numbers) المُدْخَلة؛ حيث تَعتمِد على المُستخدِم الذي ربما قد يَرغَب بإِدْخَال قياسات صغيرة جدًا أو ربما كبيرة جدًا، فكان لابُدّ من صياغة الخَرْج باِستخدَام مُحدِّدات الصيغة ‫(format specifiers). اُستخدِم تحديدًا مُحدِّد الصيغة g -بالبرنامج-، والذي يَعمَل كالتالي: إذا كان العَدَد كبيرًا جدًا أو صغيرًا جدًا، فإنه يَطبَعه ‫بصيغة أسّية (exponential form)، أمّا إن لم يَكُن كذلك، فإنه يَطبَعه بالصيغة الرقمية (decimal form) العادية. تَذَكَّر أن القيمة 5، مثلًا، بمُحدِّد الصيغة ‎%14.5g‎ تُشير إلى العدد الكلي للأرقام المعنوية (significant digits) المَطبُوعة، وبذلك سنَحصُل دائمًا على نفس العَدَد من الأرقام المعنوية (significant digits) بالخَرْج بِغَضّ النظر عن قيمة العَدَد المُدْخَل. يَختلف ذلك عن مُحدِّد الصيغة f، والذي يَطبَع الخَرْج بصيغة رقمية (decimal form)، ولكن تُشير فيه القيمة 5، مثلًا، بمُحدِّد الصيغة ‎%14.5f إلى عَدَد الأرقام بَعْد العلامة العَشريّة (decimal point)، أيّ إذا كان لدينا العَدَد 0.000000000745482 فإن مُحدِّد الصيغة f سيَطبَعه إلى 0.00000، بدون أيّ أرقام معنوية (significant digits) على الإطلاق، أما مُحدِّد الصيغة g فسيَطبَعه 7.4549e-10.

التعليمة الفارغة (Empty Statement)

تُوفِّر لغة الجافا تَعْليمَة آخرى يُطلَق عليها اسم التَعْليمَة الفارغة (empty statement)، وهي ببساطة مُجرَّد فاصلة منقوطة ;، وتَطلُب من الحاسوب أن يَفعَل "لا شيء". اُنظر المثال التالي:

if (x < 0) {
    x = -x;
};

عملية إِضافة فاصلة منقوطة (semicolon) بَعْد القوس {، كما بالمثال السابق، هي عملية صحيحة تمامًا وِفقًا لقواعد بناء الجملة (syntax)، لكن، في هذه الحالة، لا يعدّها الحاسوب جزءًا من تَعْليمَة if، وإنما يُعامِلها معاملة تَعْليمَة فارغة (empty statement) مستقلة بذاتها. عمومًا ليس هذا الغرض من تَوفَّر التَعْليمَة الفارغة بلغة الجافا، ولن تجدها مُستخدَمة بهذه الطريقة إلا نادرًا، وإنما ستَستخدِمها أحيانًا عندما تُريد أن تَطلُب من الحاسوب ألا يَفعَل شيئًا. على سبيل المثال:

if ( done )
   ;  // تعليمة فارغة
else
   System.out.println( "Not done yet.");

تَطلُب الشيفرة بالأعلى من الحاسوب ألا يَفعَل شيئًا إذا كانت قيمة المُتَغيِّر المنطقي done مساوية للقيمة المنطقية true، وأن يَطبَع السِلسِلة النصية "Not done yet" إذا كانت قيمته مُساوية للقيمة المنطقية false. لا يمكنك في هذه الحالة أن تَحذِف الفاصلة المنقوطة (semicolon)؛ لأن قواعد الصياغة بلغة الجافا (Java syntax) تَتَطلَّب وجود تَعْليمَة بين if و else. يُفضِّل الكاتب على الرغم من ذلك اِستخدَام كُتلَة (block) فارغة أي اِستخدَام قوسين فارغين في تلك الحالات.

عادةً ما تَتسبَّب إضافة التَعْليمَة الفارغة ; دون قصد بحُدوث أخطاء (errors) يَصعُب إِيجادها. انظر المثال التالي:

for (i = 0; i < 10; i++);
    System.out.println("Hello");

يَطبَع المثال بالأعلى كلمة "Hello" مرة واحدة فقط وليس عشر مرات كما قد تَظُنّ -بالأخص مع وجود المسافة البادئة (indentation) ببداية السطر الثاني-. السبب ببساطة هو وجود فاصلة منقوطة ; بنهاية تَعْليمَة for بنهاية السَطْر الأول. تُعدّ هذه الفاصلة المنقوطة ; -في هذه الحالة- تَعْليمَة بحد ذاتها، هي التَعْليمَة الفارغة (empty statement)، وهي في الواقع ما يتم تَّنْفيذه عشر مرات، أي أن حَلْقة التَكْرار for بالأعلى تَفعَل "لا شئ" عشر مرات. في المقابل، لا تُعدّ التَعْليمَة System.out.println جزءً من تَعْليمَة for أساسًا، ولذلك تُنفَّذ مرة واحدة فقط بعد انتهاء تَعْليمَة حَلْقة for.

ترجمة -بتصرّف- للقسم Section 5: The If Statement من فصل Chapter 3: Programming in the Small II: Control من كتاب Introduction to Programming Using Java.


تفاعل الأعضاء

أفضل التعليقات

بتاريخ On 10/23/2021 at 11:54 قال اسماعيل Ismail:

غريب استعمال الكاتب لمصطلح تعليمة تفريغ على if و switch وهي حسب أوراكل تطلق على return , break , continue

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

إن لاحظت في الأمثلة الموجودة في الرابط المرسل، فهي مضافة ضمن تعليمة if، والكاتب شرح سبب التفريع ووضح ذلك بالصور. أما break و continue فهي تابعة لحلقات التكرار مثل حلقة for.

بتاريخ 13 ساعات قال جميل بيلوني:

إن لاحظت في الأمثلة الموجودة في الرابط المرسل، فهي مضافة ضمن تعليمة if، والكاتب شرح سبب التفريع ووضح ذلك بالصور. أما break و continue فهي تابعة لحلقات التكرار مثل حلقة for.

يقصد الكاتب بما أن if و switch يقومان بالتفريغ فهما تعليمتا تفريغ ؟

 

بتاريخ 10 ساعات قال اسماعيل Ismail:

يقصد الكاتب بما أن if و switch يقومان بالتفريغ فهما تعليمتا تفريغ ؟

 

صحيح، فهي تفرّع مسار تنفيذ البرنامج كما موضح بالصورة بالأعلى.



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...