|
جاوا از دو دستور انتخاب پشتيباني مي كنند : ifو switchو . با اين دستورات شما اجراي برنامه را براساس شرايطي كه فقط حين اجراي برنامه اتفاق مي افتند كنترل مي كنيد. اگر سابقه برنامه نويسي با C++/C را نداريد، از قدرت و انعطاف پذيري موجود در اين دو دستور متعجب و شگفت زده خواهيد شد .
if
دستور if دستور انشعاب شرطي در جاوا است . از اين دستور مي توان استفاده نمود و اجراي برنامه را طي دو مسير متفاوت به جريان انداخت . شكل كلي اين دستور بصورت زير است :
if( condition )statement 1; else statement 2;
دراينجا هر statement ممكن است يك دستور منفرد يا يك دستور مركب قرار گرفته در ابروها ( يعني يك بلوك ) باشد . condition ( شرط ) هر عبارتي است كه يك مقدار boolean را برمي گرداند . جمله else اختياري است . if بصورت زير كار مي كند : اگر شرايط محقق باشد ، آنگاه statement 1 اجرا مي شود . در غير اينصورت statement 2 ( در صورت وجود ) اجرا خواهد شد . تحت هيچ شرايطي هر دو دستور با هم اجرا نخواهند شد . بعنوان مثال ، در نظر بگيريد :
+ int a/ b; + //... + if(a < b )a = 0; + else b = 0;
در اينجا اگر a كوچكتر از b باشد ، آنگاه a برابر صفر مي شود . در غير اينصورت b برابر صفر قرار مي گيرد . در هيچ شرايطي اين دو متغير در آن واحد برابر صفر نمي شوند . غالب اوقات ، عبارتي كه براي كنترل if استفاده ميشود شامل عملگرهاي رابطه اي است . اما از نظر تكنيكي ضرورتي وجود ندارد . مي توان با استفاده از يك متغير boolean تكي ، if را همانطوريكه در بخش زير مشاهده مي كنيد ، كنترل نمود .
+ boolean dataAvailable; + //... + if( dataAvailable) + ProcessData)(; + else + waitForMoreData)(;
بياد آوريد كه فقط يك دستور مي تواند مستقيما" بعداز ifيا elseا قرار گيرد. اگر بخواهيد دستورات بيشتري داخل نماييد ، نيازي به ايجاد يك بلوك نداريد نظير اين قطعه كه در زير آمده است :
+ int bytesAvailable; + //... + if( bytesAvailable > 0 ){ + ProcessData)(; + bytesAvailable- = n; + } else + waitForMoreData)(;
در اينجا ، هر دو دستور داخل بلوك if اجرا خواهند شد اگر bytes Available بزرگتر از صفر باشد . برخي از برنامه نويسان راحت ترند تا هنگام استفاده از if ، از ابروهاي باز و بسته استفاده نمايند، حتي زمانيكه فقط يك دستور در هر جمله وجود داشته باشد. اين امر سبب مي شود تا بعدا" بتوان براحتي دستور ديگري را اضافه نمود و نگراني از فراموش كردن ابروها نخواهيد داشت . در حقيقت ، فراموش كردن تعريف يك بلوك هنگامي كه نياز است ، يكي از دلايل رايج بروز خطاها مي باشد . بعنوان مثال قطعه زير از يك كد را در نظر بگيريد :
+ int bytesAvailable; + //... + if( bytesAvailable > 0 ){ + ProcessData)(; + bytesAvailable- = n; + } else + waitForMoreData)(; + bytesAvailable = n;
بنظر خيلي روشن است كه دستور bytes Available=n طوري طراحي شده تا داخل جمله else اجرا گردد ، و اين بخاطر سطح طراحي آن است . اما حتما" بياد داريد كه فضاي خالي براي جاوا اهميتي ندارد و راهي وجود ندارد كه كامپايلر بفهمد چه مقصودي وجود دارد . اين كد بدون مشكل كامپايل خواهد شد ، اما هنگام اجرا بطور ناصحيح اجرا خواهد شد . مثال بعدي داخل كدي كه مشاهده مي كنيد تثبيت شده است :
+ int bytesAvailable; + //... + if( bytesAvailable > 0 ){ + ProcessData)(; + bytesAvailable- = n; + } else { + waitForMoreData)(; + bytesAvailable = n; + } if
Nested ifs هاي تودرتو شده يك nested if يك دستور if است كه هدف ifيا elseا ديگري باشد. if هاي تودرتو در برنامه نويسي بسيار رايج هستند. هنگاميكه if ها را تودرتو مي كنيد، مهمترين چيزي كه بايد بخاطر بسپاريد اين است كه يك دستورelse هميشه به نزديكترين دستور if خود كه داخل همان بلوك else است و قبلا" با يك else همراه نشده ، مراجعه خواهد نمود . مثالي را مشاهده نماييد :
+ if(i == 10 ){ + if(j < 20 )a = b; + if(k > 100 )c = d; // this if is + else a = c; // associated with this else + } + else a = d; // this else refers to if(i == 10)
همانگونه كه توضيحات نشان مي دهند ، else نهايي با (20 چون داخل همان بلوك قرار ندارد ( اگر چه نزديكترين if بدون else است ) . بجاي آن ، else نهايي با (i==10)if همراه مي شود . else داخلي به (100>k)if ارجاع مي كند ، زيرا نزديكترين if در داخل همان بلوك است .
نردبان if-else-if يك ساختار برنامه نويسي رايج براساس يك ترتيب از ifهاي تودرتو شده يا نردبان if-else-if است . اين ساختار بصورت زير است :
if(condition) statement; else if(condition)
statement; else if(condition) statement; . . . else statement;
دستورات if از بالا به پايين اجرا مي شوند . ماداميكه يكي از شرايط كنترل كننده if صحيح باشد (true)، دستور همراه با آن if اجرا مي شود ، و بقيه نردبان رد خواهد شد . اگر هيچكدام از شرايط صحيح نباشند، آنگاه دستور else نهايي اجرا خواهد شد . else نهايي بعنوان شرط پيش فرض عمل مي كند ، يعني اگر كليه شرايط ديگر صحيح نباشند ، آنگاه آخرين دستور else انجام خواهد شد . اگر else نهايي وجود نداشته باشد و ساير شرايط ناصحيح باشند ، آنگاه هيچ عملي انجام نخواهد گرفت . در زير ، برنامه اي را مشاهده مي كنيد كه از نردبان if-else-if استفاده كرده تا تعيين كند كه يك ماه مشخص در كدام فصل واقع شده است .
+ // Demonstrate if-else-if statement. + class IfElse { + public static void main(String args[] ){ + int month = 4; // April + String season; + + if(month == 12 || month == 1 || month == 2) + season = "Winter"; + else if(month == 3 || month == 4 || month == 5) + season = "Spring"; + else if(month == 6 || month == 7 || month == 8) + season = "Summer"; + else if(month == 9 || month == 10 || month == 11) + season = "Autumn"; + else + season = "Bogus Month"; + + System.out.println("April is in the" + season + "."); + } + }
خروجي اين برنامه بقرار زير مي باشد :
April is in the Spring.
ممكن است بخواهيد اين برنامه را تجربه نماييد . خواهيد ديد كه هيچ فرقي ندارد كه چه مقداري به month بدهيد ، يك و فقط يك دستور انتساب داخل نردبان اجرا خواهد شد .
switch
دستور switch ، دستور انشعاب چند راهه در جاوا است . اين دستور راه ساده اي است براي تغيير مسير اجراي بخشهاي مختلف يك كد براساس مقدار يك عبارت . اين روش يك جايگزين مناسب تر براي مجموعه هاي بزرگتر از دستورات if-else-if است . شكل كلي دستور switch بقرار زير مي باشد :
switch(expression){ case value1: // statement sequence break; case value2: // statement sequence break; . . . case valueN: // statement sequence break; default: // default statement sequence } expression
مي تواند هر نوع ساده اي را برگرداند ، هر يك از مقادير (values) در دستورات case بايد از نوع سازگار با عبارت باشند . هر يك از مقادير case بايد يك مقدار لفظي منحصر بفرد باشد ( يعني بايد يك ثابت ، نه متغير ، باشد ). دو برابر سازي مقادير case مجاز نيست . دستور switch بشرح فوق عمل مي كند : مقدار عبارت با هر يك از مقادير لفظي در دستورات case مقايسه مي شوند. اگر تطابق پيدا شود ، كد سلسله اي تعقيب كننده آن دستور case اجرا خواهد شد . اگر هيچيك از ثابت ها با مقدار عبارت تطابق نيابند ، آنگاه دستور پيش فرض (default) اجرا خواهد شد ، اما دستور default اختياري است . اگر هيچيك از case ها تطابق نيابد و default وجود نداشته باشد آنگاه عمل اضافي ديگري انجام نخواهد شد . از دستور break داخل دستور switch استفاده شده تا سلسله يك دستور را پايان دهد . هنگاميكه با يك دستور break مواجه مي شويم ، اجرا به خط اول برنامه كه بعد از كل دستور switch قرار گرفته ، منشعب خواهد شد . اين حالت تاثير پريدن switch است . در زير مثال ساده اي را مشاهده مي كنيد كه از دستور switch استفاده نموده است :
+ // A simple example of the switch. + class SampleSwitch { + public static void main(String args[] ){ + for(int i=0; i<6; i++) + switch(i ){ + case 0: + System.out.println("i is zero."); + break; + case 1: + System.out.println("i is one."); + break; + case 2: + System.out.println("i is two."); + break; + case 3: + System.out.println("i is three."); + break; + default: + System.out.println("i is greater then 3."); + } + } + }
خروجي اين برنامه بقرار زير مي باشد :
i is zero. i is one. i is two. i is three. i is greater than 3. i is greater than 3.
همانطوريكه مشاهده مي كنيد ، داخل حلقه ، دستوراتي كه همراه ثابت case بوده و با i مطابقت داشته باشند ، اجرا خواهند شد . ساير دستورات پشت سر گذاشته مي شوند (bypassed) . بعد از اينكه i بزرگتر از 3 بشود ، هيچ دستور همراه case مطابقت نداشته ، بنابراين دستور پيش فرض (default) اجرا خواهد شد . دستور break اختياري است . اگر break را حذف كنيد ، اجراي برنامه با case بعدي ادامه خواهد يافت . گاهي بهتر است چندين case بدون دستورات break در بين آنها داشته باشيم . بعنوان مثال ، برنامه بعدي را در نظر بگيريد :
+ // In a switch/ break statements are optional. + class MissingBreak { + public static void main(String args[] ){ + for(int i=0; i<12; i++) + switch(i ){ + case 0: + case 1: + case 2: + case 3: + case 4: + System.out.println("i is less than 5"); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + System.out.println("i is less than 10"); + break; + default: + System.out.println("i is 10 or more"); + } + } + }
خروجي اين برنامه بقرار زير خواهد بود :
i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is 10 or more i is 10 or more
همانطوريكه مشاهده مي كنيد، اجرا طي هر case، بمحض رسيدن به يك دستور break ( يا انتهاي switch ) متوقف مي شود . در حاليكه مثال قبلي براي توصيف نظر خاصي طراحي شده بود ، اما بهر حال حذف دستور break كاربردهاي عملي زيادي در برنامه هاي واقعي دارد . براي نشان دادن كاربردهاي واقعي تر اين موضوع ، دوباره نويسي برنامه نمونه مربوط به فصول سال را مشاهده نماييد . اين روايت جديد همان برنامه قبلي از switch استفاده مي كند تا پياده سازي موثرتري را ارائه دهد .
+ // An improved version of the season program. + class Switch { + public static void main(String args[] ){ + int month = 4; + String season; + switch( month ){ + case 12: + case 1: + case 2: + season = "Winter"; + break; + case 3: + case 4: + case 5: + season = "Spring"; + break; + case 6: + case 7: + case 8: + season = "Summer"; + break; + case 9: + case 10: + case 11: + season = "Autumn"; + break; + default: + season = "Bogus Month"; + } + System.out.println("April is in the" + season + "."); + + } + }
تودرتو كردن دستورات switch مي توانيد از يك switch بعنوان بخشي از ترتيب يك دستور switch خارجي تر استفاده نماييد. اين حالت را switch تودرتو مينامند. از آنجاييكه دستور switch تعريف كننده بلوك مربوط به خودش مي باشد، هيچ تلاقي بين ثابتهاي caseدر switchر داخلي و آنهايي كه در switch خارجي قرار گرفته اند ، بوجود نخواهد آمد . بعنوان مثال ، قطعه بعدي كاملا" معتبر است .
+ switch(count ){ + case 1: + switch(target ){ // nested switch + case 0: + System.out.println("target is zero"); + break; + case 1 :// no conflicts with outer switch + System.out.println("target is one"); + break; + } + break; + case 2 ://...
در اينجا دستور :case 1در switchر داخلي با دستور :case 1در switchر خارجي تلاقي نخواهد داشت . متغير count فقط با فهرست case ها در سطح خارجي مقايسه مي شود. اگر count برابر 1 باشد، آنگاه target با فهرست case هاي داخلي مقايسه خواهد شد . بطور خلاصه ، سه جنبه مهم از دستور switch قابل توجه هستند : ؤ switchبا ifا متفاوت است چون switch فقط آزمايش كيفيت انجام مي دهد ، در حاليكه if هر نوع عبارت بولي را ارزيابي مي كند . يعني كه switch فقط بدنبال يك تطابق بين مقدار عبارت و يكي از ثابت هاي case خودش مي گردد . ؤ دو ثابت caseدر switchر مشابه نمي توانند مقادير يكسان داشته باشند . البته ، يك دستور switch قرار گرفته داخل يك switch خارجي تر مي تواند ثابتهاي case مشترك داشته باشد . ؤ يك دستور switch معمولا" بسيار كاراتر از يك مجموعه از if هاي تودرتو شده است . آخرين نكته بخصوص جالب توجه است زيرا روشنگر نحوه كار كامپايلر جاوا مي باشد . كامپايلر جاوا هنگاميكه يك دستور switch را كامپايل مي كند ، به هر يك از ثابتهاي case سركشي نموده و يك جدول jump table مي سازد كه براي انتخاب مسير اجرا براساس مقدار موجود در عبارت استفاده مي شود . بنابراين ، اگر بايد از ميان گروه بزرگي از مقادير انتخاب نماييد ، يك دستور switch نسبت به يك ترتيب از if-else ها كه بطور معادل و منطقي كد بندي شده باشد ، بسيار سريعتر اجرا خواهد شد. كامپايلر قادر است اينكار را انجام دهد چون مي داند كه ثابتهاي case همه از يك نوع بوده و بايد خيلي ساده با عبارت switch براي كيفيت مقايسه شوند . كامپايلر چنين شناسايي را نسبت به يك فهرست طولاني از عبارات if ندارد .
دستورات تكرار iteration statements دستورات تكرار در جاوا عبارتند از for، while،و do-whileو . اين دستورات آن چه را ما " حلقه " مي ناميم ، ايجاد مي كنند . احتمالا" مي دانيد كه حلقه يك مجموعه از دستورالعملها را بطور تكراري اجرا مي كند . تا اينكه يك شرط پاياني را ملاقات نمايد . همانطوريكه بعدا" خواهيد ديد، جاوا حلقه اي دارد كه براي كليه نيازهاي برنامه نويسي مناسب است .
while
حلقه while اساسي ترين دستور حلقه سازي (looping) در جاوا است . اين دستور ماداميكه عبارت كنترل كننده ، صحيح (true) باشد، يك دستور يا يك بلوك را تكرار مي كند . شكل كلي اين دستور بقرار زير است :
while(condition ){ // body of loop }
شرط يا condition ممكن است هر عبارت بولي باشد . ماداميكه عبارت شرطي صحت داشته باشد ، بدنه حلقه اجرا خواهد شد . هنگاميكه شرط صحت نداشته باشد ، كنترل بلافاصله به خط بعدي كدي كه بلافاصله پس از حلقه جاري قرار دارد ، منتقل خواهد شد . اگر فقط يك دستور منفرد در حال تكرار باشد ، استفاده از ابروها غير ضروري است . در اينجا يك حلقه while وجود دارد كه تا 10 را محاسبه كرده و دقيقا" ده خط "tick" را چاپ مي كند .
+ // Demonstrate the while loop. + class While { + public static void main(String args[] ){ + int n = 10; + + while(n > 0 ){ + System.out.println("tick" + n); + n--; + } + } + }
هنگاميكه اين برنامه را اجرا مي كنيد، ده مرتبه "tick" را انجام خواهد داد:
tick 10 tick 9 tick 8 tick 7 tick 6 tick 5 tick 4 tick 3 tick 2 tick 1
از آنجاييكه حلقه while عبارت شرطي خود را در بالاي حلقه ارزيابي ميكند، اگر شرط ابتدايي ناصحيح باشد ، بدنه حلقه اجرا نخواهد شد . بعنوان مثال ، در قطعه زير ، فراخواني ()println هرگز اجرا نخواهد شد .
+ int a = 10/ b = 20; + + while(a < b) + System.out.println("This will not be displayed");
بدنه while يا هر حلقه ديگر در جاوا ) ممكن است تهي باشد. زيرا دستور تهي دستوري كه فقط شامل ; باشد ) از نظر قواعد تركيبي در جاوا معتبراست . بعنوان مثال ، برنامه زير را در نظر بگيريد :
+ // The target of a loop can be empty. + class NoBody { + public static void main(String args[] ){ + int i/ j; + + i = 100; + j = 200; + + // find midpoint between i and j + while(++i <-- j); // no body in this loop + + System.out.println("Midpoint is" + i); + } + }
اين برنامه نقطه مياني (midpoint) بين iو jو را پيدا مي كند و خروجي زير را توليد خواهد كرد :
Midpoint is 150
در اينجا چگونگي كار حلقه while را مي بينيد . مقدار i افزايش و مقدار j كاهش مي يابد . سپس اين دو مقدار با يكديگر مقايسه مي شوند . اگر مقدار جديد i همچنان كمتر از مقدار جديد j باشد ، آنگاه حلقه تكرار خواهد شد . اگر i مساوي با يا بزرگتر از j بشود ، حلقه متوقف خواهد شد . تا هنگام خروج از حلقه ، i مقداري را مي گيرد كه بين مقادير اوليه iو jو مي باشد . ( بديهي است كه اين رويه هنگامي كار مي كند كه i كوچكتر از مقدار اوليه j باشد . ) همانطوريكه مي بينيد ، نيازي به بدنه حلقه نيست ، كليه عمليات داخل خود عبارت شرطي اتفاق مي افتد . در كدهاي حرفه اي نوشته شده ديگر جاوا ، وقتي كه عبارت كنترل كننده توانايي مديريت كليه جزئيات خود را داشته باشد ، حلقه هاي كوتاه غالبا" بدون بدنه كد بندي مي شوند .
do-while
گفتيم اگر عبارت شرطي كنترل كننده يك حلقه while در ابتدا ناصحيح باشد آنگاه بدنه حلقه اصلا" اجرا نمي شود . اما گاهي مايليم در چنين شرايطي ، بدنه حلقه حداقل يكبار اجرا شود . بعبارت ديگر، در حالات خاصي مايليد تا عبارت پايان دهنده در انتهاي حلقه را آزمايش كنيد. خوشبختانه ، جاوا حلقه اي را عرضه مي كند كه دقيقا" همين كار را انجام مي دهد : do-while . حلقه do-while همواره حداقل يكبار بدنه خود را اجرا مي كند، زيرا عبارت شرطي آن در انتهاي حلقه قرار گرفته است . شكل كلي آن بصورت زير است :
do{ // body of loop } while(condition);
هر تكرار از حلقه do-while ابتدا بدنه حلقه را اجرا نموده ، سپس به ارزيابي عبارت شرطي خود مي پردازد . اگر اين عبارت صحيح (true) باشد ، حلقه اجرا خواهد شد . در غير اينصورت حلقه پايان مي گيرد . نظير كليه حلقه هاي جاوا ، شرط بايد يك عبارت بولي باشد . اينجا يك روايت ديگر از برنامه (tick) وجود دارد كه حلقه do-while را نشان مي دهد . خروجي اين برنامه مشابه برنامه قبلي خواهد بود :
+ // Demonstrate the do-while loop. + class DoWhile { + public static void main(String args[] ){ + int n = 10; + + do { + System.out.println("tick" + n); + n--; + } while(n > 0); + } + }
حلقه موجود در برنامه قبلي ، اگر چه از نظر تكنيكي صحيح است ، اما مي توان آن را به شكل كاراتري بصورت زير دوباره نويسي نمود : + do { + System.out.println("tick " + n); + } while--(n > 0);
در اين مثال ، عبارت (0>n) عمل كاهش n و آزمايش براي صفر را در يك عبارت گنجانده است . عملكرد آن بقرار بعدي است . ابتدا دستور n اجرا مي شود و n را كاهش داده و مقدار جديد را به n برمي گرداند . اين مقدار سپس با صفر مقايسه مي شود . اگر بزرگتر از صفر باشد ، حلقه ادامه مي يابد . در غير اينصورت حلقه پايان مي گيرد . حلقه do-while بويژه هنگام پردازش انتخاب منو بسيار سودمند است ، زيرا معمولا" مايليد تا بدنه يك حلقه منو حداقل يكبار اجرا شود . برنامه بعدي را كه يك سيستم Help ساده را براي دستورات تكرار و انتخاب در جاوا پياده سازي مي كند در نظر بگيريد :
+ // Using a do-while to process a menu selection -- a simple help system. + class Menu { + public static void main(String args[]) + throws java.io.IOException { + char choice; + + do { + System.out.prinln("Help on:"); + System.out.prinln(" 1 .if"); + System.out.prinln(" 2 .switch"); + System.out.prinln(" 3 .while"); + System.out.prinln(" 4 .do-while"); + System.out.prinln(" 5 .for\n"); + System.out.prinln("Choose one:"); + choice =( char )System.in.read)(; + } while(choice < '1' || choice > '5'); + + System.out.println("\n"); + switch(choice ){ + case '1': + System.out.println("The if:\n"); + System.out.println("if(condition )statement;"); + System.out.println("else statement;"); + break; + case '2': + + System.out.println("The switch:\n"); + System.out.println("switch(expression ){"); + System.out.println(" case constant:"); + System.out.println(" statement sequence"); + System.out.println(" break;"); + System.out.println(" //... "); + System.out.println("}"); + break; + case '3': + System.out.println("The switch:\n"); + System.out.println(while(condition )statement;"); + break; + case '4': + System.out.println("The do-while:\n"); + System.out.println("do {"); + System.out.println(" statement;"); + System.out.println("} while( condition);"); + break; + case '5': + System.out.println("The for:\n"); + System.out.print("for(init; condition; iteration)"); + System.out.println(" statement;"); + break; + } + } + }
اكنون يك اجراي نمونه توليد شده توسط اين برنامه را مشاهده مي كنيد :
Help on: 1 .if 2 .switch 3 .while 4 .do-while 5 .for Choos one: 4
The do-while:
do { statement; } while( condition);
در برنامه ، از حلقه do-while براي تصديق اينكه كاربر يك گزينه معتبر را وارد كرده باشد ، استفاده مي شود . در غير اينصورت ، به كاربر مجددا" اعلان خواهد شد . از آنجاييكه منو بايد حداقل يكبار بنمايش درآيد ، do-while حلقه كاملي براي انجام اين مقصود است . چند نكته ديگر درباره اين مثال : دقت كنيد كه كاراكترهااز صفحه كليد بوسيله فراخواني ()system.in.read خوانده مي شوند . اين يكي از توابع ورودي كنسول در جاوا است . اگر چه بررسي تفصيلي روشهاي l/o جاوا به بحثهاي بعدي موكول شده ، اما از ()system.in.read در اينجا براي بدست آوردن گزينه كاربر استفاده شده است . اين تابع كاراكترها را از ورودي استاندارد مي خواند ( كه بعنوان عدد صحيح برگردان شد ، اين دليلي است كه چرا مقدار برگردان از طريق تبديل (cast) به char تبديل شده است ). بصورت پيش فرض ، ورودي استاندارد، بافر شده خطي است (line buffered) بنابراين قبل از اينكه كاراكترهايي را كه تايپ كرده ايد به برنامه اتان ارسال كنيد ، بايد كليد ENTER را فشار دهيد . ( اين حالت مشابه C++/C است و احتمالا" از قبل با آن آشنايي داريد ) . ورودي كنسول در جاوا كاملا" محدود شده و كار با آن بسيار مشكل است . بعلاوه اكثر برنامه و ريز برنامه هاي واقعي نوشته شده با جاوا گرافيكي و پنجره اي هستند. از سوي ديگر : چون از ()system.in.read استفاده شده ، برنامه بايد جمله throwsjava.io.loException را كاملا" توصيف نمايد . اين خط براي مديريت خطاهاي ورودي ضروري است . اين بخشي از جنبه هاي مختلف اداره استثنائ در جاوا است كه بعدا" بررسي خواهد شد .
for
خواهيد ديد كه حلقه for يك ساختار قدرتمند و بسيار روان است .شكل كلي دستور for بصورت زير است :
for(initialization; condition; iteration; ){ // body }
اگر فقط يك دستور بايد تكرار شود ، نيازي به ابروها نيست . عملكرد حلقه for بشرح بعدي است . وقتي كه حلقه براي اولين بار شروع مي شود بخض مقدار دهي اوليه در حلقه اجرا مي شود . معمولا" ، اين بخش يك عبارت است كه مقدار متغير كنترل حلقه را تعيين مي كند ، كه بعنوان يك شمارشگر ، كنترل حلقه را انجام خواهد داد . مهم است بدانيم كه عبارت مقدار دهي اوليه فقط يكبار اجرا مي شود . سپس شرط مورد ارزيابي قرار مي گيرد . اين شرط بايد يك عبارت بولي باشد . اين بخش معمولا" مقدار متغير كنترل حلقه را با مقدار هدف مقايسه مي كند. اگر عبارت صحيح (true) باشد، آنگاه بدنه حلقه اجرا خواهد شد . اگر ناصحيح باشد حلقه پايان مي گيرد . بعد، بخش تكرار (iteration) حلقه اجرا مي شود . اين بخش معمولا" عبارتي است كه مقدار متغير كنترل را افزايش يا كاهش مي دهد. آنگاه حلقه تكرار خواهد شد ، ابتدا عبارت شرطي را ارزيابي مي كند ، سپس بدنه حلقه را اجرا مي كند و سرانجام عبارت تكرار را در هر گذر (pass) اجرا ميكند. اين روال آنقدر دادمه مي يابد تا عبارت شرطي ناصحيح (false) گردد . در زير روايت جديدي از برنامه "tick" را مي بينيد كه از يك حلقه for استفاده كرده است :
+ // Demonstrate the for loop. + class ForTick { + public static void main(String args[] ){ + int n; + for(n=10; n>0; n)-- + System.out.println("tick" + n); + } + }
اعلان متغيرهاي كنترل حلقه داخل حلقه for غالبا" متغيري كه يك حلقه for را كنترل مي كند ، فقط براي همان حلقه مورد نياز بوده و كاربري ديگري ندارد . در چنين حالتي ، مي توان آن متغير را داخل بخش مقدار دهي اوليه حلقه for اعلان نمود . بعنوان مثال در اينجا همان برنامه قبلي را مشاهده مي كنيد كه متغير كنترل حلقه يعني n بعنوان يك int در داخل حلقه for اعلان شده است .
+ // Declare a loop control variable inside the for. + class ForTick { + public static void main(String args[] ){ + + // here/ n is declared inside of the for loop + for(int n=10; n>0; n)-- + System.out.println("tick" + n); + } + }
هنگاميكه يك متغير را داخل يك حلقه for اعلان مي كنيد ، يك نكته مهم را بايد بياد داشته باشيد : قلمرو آن متغير هنگاميكه دستور for انجام مي شود ، پايان مي يابد . ( يعني قلمرو متغير محدود به حلقه for است . ) خارج از حلقه for حيات آن متغير متوقف مي شود . اگر بخواهيد از اين متغير كنترل حلقه در جاي ديگري از برنامه اتان استفاده كنيد ، نبايد آن متغير را داخل حلقه for اعلان نماييد . درشرايطي كه متغير كنترل حلقه جاي ديگري موردنياز نباشد، اكثر برنامه نويسان جاوا آن متغير را داخل for اعلان مي كنند . بعنوان مثال ، در اينجا يك برنامه ساده را مشاهده مي كنيد كه بدنبال اعداد اول مي گردد. دقت كنيد كه متغير كنترل حلقه ، چون جاي ديگري مورد نياز نيست ، داخل for اعلان شده است .
+ // Test for primes. + class FindPrime { + public static void main(String args[] ){ + int num; + boolean isPrime = true; + + num = 14; + for(int i=2; i < num/2; i++ ){ + if((num % i )== 0 ){ + isPrime = false; + break; + } + } + if(isPrime )System.out.println("Prime"); + else System.out.println("Not Prime"); + } + }
استفاده از كاما Comma شرايطي پيش مي آيد كه مايليد بيش از يك دستور در بخش مقدار دهي اوليه (initalization) و تكرار (iteration) بگنجانيد . بعنوان مثال ، حلقه موجود در برنامه بعدي را در نظر بگيريد :
+ class Sample { + public static void main(String args[] ){ + int a/ b; + + b = 4; + for(a=1; a + System.out.println("a = " + a); + System.out.println("b = " + b); + b--; + } + } + }
همانطوريكه مي بينيد ، حلقه توسط ارتباط متقابل دو متغير كنترل مي شود . از آنجاييكه حلقه توسط دو متغير اداره مي شود ، بجاي اينكه b را بصورت دستي اداره كنيم ، بهتر است تا هر دو را در دستور for بگنجانيم . خوشبختانه جاوا راهي براي اينكار دارد . براي اينكه دو يا چند متغير بتوانند يك حلقه for را كنترل كنند ، جاوا به شما امكان مي دهد تا چندين دستور را در بخشهاي مقدار دهي اوليه و تكرار حلقه for قرار دهيد . هر دستور را بوسيله يك كاما از دستور بعدي جدا مي كنيم . حلقه for قبلي را با استفاده از كاما ، خيلي كاراتر از قبل مي توان بصورت زير كد بندي نمود :
+ // Using the comma. + class Comma { + public static void main(String args[] ){ + int a/ b; + + for(a=1/ b=4; a + System.out.println("a = " + a); + System.out.println("b = " + b); + } + } + }
در اين مثال ، بخش مقدار دهي اوليه ، مقادير aو bو را تعيين مي كند . هربار كه حلقه تكرار مي شود ، دو دستور جدا شده توسط كاما در بخش تكرار (itration) اجرا خواهند شد . خروجي اين برنامه بقرار زير مي باشد :
a=1 b=4 a=2 b=3
نكته : اگر با C++/C آشنايي داريد ، حتما" مي دانيد كه در اين زبانها ، علامت كاما يك عملگر است كه در هر عبارت معتبري قابل استفاده است . اما در جاوا اينطور نيست . در جاوا ، علامت كاما يك جدا كننده است كه فقط در حلقه for قابل اعمال مي باشد .
برخي گوناگونيهاي حلقه for حلقه for از تعدادي گوناگونيها پشتيباني مي كند كه قدرت و كاربري آن را افزايش مي دهند . دليل انعطاف پذيري آن است كه لزومي ندارد كه سه بخش مقداردهي اوليه ، آزمون شرط و تكرار ، فقط براي همان اهداف مورد استفاده قرار گيرند . در حقيقت ، سه بخش حلقه for براي هر هدف مورد نظر شما قابل استفاده هستند . به چند مثال توجه فرمائيد . يكي از رايجترين گوناگونيها مربوط به عبارت شرطي است . بطور مشخص ، لزومي ندارد اين عبارت ، متغير كنترل حلقه را با برخي مقادير هدف آزمايش نمايد . در حقيقت ، شرط كنترل كننده حلقه for ممكن است هر نوع عبارت بولي باشد . بعنوان مثال ، قطعه زير را در نظر بگيريد :
+ boolean done = false; + + for(int i=1; !done; i++ ){ + //... + if(intettupted ))(done = true; + }
در اين مثال ، حلقه for تا زمانيكه متغير بولي done معادل true بشود ، اجرا را ادامه خواهد داد . اين مثال مقدار i را بررسي نمي كند . اكنون يكي ديگر از گوناگونيهاي جالب حلقه for را مشاهده مي كنيد. ممكن است يكي يا هر دو عبارت مقدار دهي اوليه و تكرار غايت باشند ، نظير برنامه بعدي :
+ // Parts of the for loop can be empty. + class ForVar { + public static void main(String args[] ){ + int i; + boolean done = false; + + i = 0; + for (; !done; ) { + System.out.println("i is" + i); + if(i == 10 )done = true; + i++; + } + } + }
در اينجا عبارتهاي مقدار دهي اوليه و تكرار به خارج ازfor انتقال يافته اند. برخي از بخشهاي حلقه for تهي هستند . اگر چه در اين مثال ساده چنين حالتي هيچ ارزشي ندارد ، اما در حقيقت شرايطي وجود دارد كه اين روش بسيار كارا و سودمند خواهد بود. بعنوان مثال ، اگر شرط اوليه بصورت يك عبارت پيچيده و در جاي ديگري از برنامه قرار گرفته باشد و يا تغييرات متغير كنترل حلقه بصورت غير ترتيبي و توسط اعمال اتفاق افتاده در داخل بدنه حلقه تعيين شود ، پس بهتر است كه اين بخشها را در حلقه for تهي بگذاريم . اكنون يكي ديگر از گوناگونيهاي حلقه for را مشاهده مي كنيد. اگر هر سه بخش حلقه for را تهي بگذاريد ، آنگاه بعمد يك حلقه نامحدود ( حلقه اي كه هرگز پايان نمي گيرد ) ايجاد كرده ايد . بعنوان مثال :
+ for (; ; ) { + //... + }
اين حلقه تا ابد ادامه خواهد يافت ، زيرا هيچ شرطي براي پايان گرفتن آن تعبيه نشده است . اگر چه برخي برنامه ها نظير پردازشهاي فرمان سيستم عامل مستلزم يك حلقه نامحدود هستند ، اما اكثر حلقه هاي نامحدود در واقع حلقه هايي هستند كه ملزومات پايان گيري ويژه اي دارند . بزودي خواهيد ديد ، راهي براي پايان دادن به يك حلقه حتي يك حلقه نامحدود نظير مثال قبلي وجود دارد كه از عبارت شرطي معمولي حلقه استفاده نمي كند .
حلقه هاي تودرتو نظير كليه زبانهاي برنامه نويسي ، جاوا نيز امكان تودرتو كردن حلقه ها را دارد . يعني يك حلقه داخل حلقه ديگري قرار خواهد گرفت . بعنوان مثال ، در برنامه بعدي حلقه هاي for تودرتو نشده اند :
+ // Loops may be nested. + class Nested { + public static void main(String args[] ){ + int i/ j; + + for(i=0; i<10; i++ ){ + for(j=i; j<10; j++) + System.out.print("."); + System.out.println)(; + } + } + } |