فرموله کردن الگوریتمها: عبارات کنترلی تودرتو
اجازه دهید تا به بررسی مسئله دیگری بپردازیم,عبارات کنترلی تودرتو. مجدداُ الگوریتم را با استفاده از شبهکد و از بالا به پایین، اصلاح گام به گام فرموله کرده و سپس برنامه C++ مربوط به آنرا خواهیم نوشت. در مثالهای قبلی مشاهده کردید که عبارتهای کنترلی همانند یک پشته یکی بر روی دیگری و به ترتیب قرار داده می شدند. در این مرحله، به معرفی روشی خواهیم پرداخت که عبارتهای کنترلی در آن را می توان با یکدیگر ترکیب کرد، بطوریکه عبارتی در درون عبارت دیگر جای می گیرد.
به صورت مسئله توجه نمائید:
یک کالج با برگزاری دورهای دانشجویان را آماده امتحان پایان ترم می کند. سال گذشته، ۱۰ تن از دانشجویان که این دوره را گذرانده بودند در امتحان پایان ترم شرکت کردند. مدیریت کالج می خواهد از وضعیت دانشجویان شرکت کرده در امتحان مطلع شود. از شما خواسته شده تا برنامهای بنویسید تا خلاصهای از نتایج آزمون ارائه دهد. لیستی از ۱۰ دانشجو دریافت کرده و سپس در کنار نام کسانی که در آزمون قبول شدهاند ۱ و کسانی که در آزمون مردود شدهاند ۲ چاپ شود.
این برنامه باید بصورت زیر نتایج آزمون را تحلیل نماید:
۱- وارد کردن نتیجه هر آزمون (برای مثال ۱ یا ۲). نمایش پیغام “Enter result” در هر بار که برنامه درخواست نتیجه آزمون می کند.
۲- شمارش تعداد قبولی ها و مردودی ها.
۳- نمایش خلاصهای از نتایج آزمون، شامل تعداد دانشجویان که موفق به گذراندن آزمون شدهاند و تعدادی که مردود شدهاند.
۴- اگر بیش از ۸ دانشجو از آزمون با موفقیت عبور کردهاند. پیغام “Raise tuition” به نمایش درآید.
پس از مطالعه صورت مسئله، تصمیمات زیر را برای حل آن اتخاذ می کنیم:
۱- برنامه باید بر روی نتایج آزمون ۱۰ دانشجو کار کند، از اینرو حلقه شمارنده – کنترل می تواند بکار گرفته شود.
۲- نتیجه هر آزمون عدد ۱ یا ۲ است. هر بار که برنامه اقدام به خواندن نتیجه یک آزمون می کند، برنامه باید یک ۱ یا ۲ دریافت نماید.
۳- دو شمارنده به ذخیرهسازی نتایج آزمون می پردازند. یکی برای شمارش تعداد دانشجویان که از آزمون با موفقیت عبور کردهاند و دیگری برای شمارش تعدادی که در آزمون مردود شدهاند.
۴- پس از اینکه برنامه تمام نتایج را مورد پردازش قرار داد، باید تعیین کند که آیا تعداد قبولی ها بیش از هشت نفر است یا خیر.
اجازه دهید تا با روش از بالا به پایین، اصلاح گامبهگام کار را دنبال کنیم. عبارت شبهکد زیر در بالاترین سطح (top) قرار دارد:
Analyze exam result and decide if tuition should be raised
مجدداً یادآوری می کنیم که عبارت top توصیف کلی در مورد برنامه است و قبل از اینکه بتوان شبهکد را به فرم یک برنامه C++ نوشت انجام چندین مرحله اصلاح گامبهگام ضروری است. اولین اصلاح عبارت است از:
Initialize variables
Input the 10 exam grades and count passes and failures
Print a summary of the exam result and decide if tuition should be raised
حتی زمانیکه یک تصور کامل از کل برنامه بدست آورده باشیم، انجام اصلاحات بعدی مورد نیاز است. باید به دقت به بررسی و مشخص کردن متغیرها پرداخت. شمارندهها به منظور ثبت قبولی ها و مردودی ها مورد نیاز هستند. یک شمارنده، کنترل کننده حلقه بوده و یک متغیر، ورودی کاربر را ذخیره می کند. عبارت شبهکد زیر
Initialize variables
میتواند بصورت زیر اصلاح شود:
Initialize passes to zero
Initialize failures to zero
Initialize student counter to one
فقط شمارندههای، تعداد قبولی ها و مردودی ها و تعداد دانشآموزان مقداردهی اولیه می شود. عبارت شبهکد
Input the 10 quiz grades and count passes and failures
مستلزم یک حلقه برای وارد کردن نتیجه هر آزمون است. در این برنامه بدلیل اینکه از همان ابتدا تعداد نتایج آزمون مشخص است (۱۰)، از اینرو می توان از روش شمارنده-کنترل تکرار استفاده کرد. در درون حلقه یک عبارت انتخابی دو گانه تعیین می کند که نتیجه آزمون قبولی است یا مردودی و شمارنده مربوطه یک واحد افزایش می یابد. اصلاح عبارت شبهکد قبلی می تواند بصورت زیر انجام شود:
While student counter is less than or equal to 10
Prompt the user to enter the next exam result
Input the next exam result
If the student passed
Add one to passes
Else
Add one to failures
Add one to student counter
به نحوه استفاده از خطوط خالی در میان مجموعه if..else دقت کنید که باعث افزایش خوانایی برنامه شده است. عبارت شبهکد
Print a summary of the exam results and decide if tuition should be raised
می تواند بصورت زیر اصلاح شود:
Print the number of passes
Print the number of failures
If more than eight student passed
Print “Raise tuition”
در شکل ۱۵-۴ دومین مرحله اصلاح بصورت کامل نشان داده شده است. به کاربرد خطوط خالی در میان ساختار while توجه کنید، که باعث افزایش خوانائی برنامه می شوند. اکنون این شبهکد بقدر کافی برای تبدیل به یک برنامه C++ آماده شده است.
Initialize passes to zero
Initialize failures to zero
Initialize student to zero
While student counter is less than or equal to ten
Input the next exam result
If the student passed
Add one to passes
Else
Add one to failures
Add one to student counter
Print the number of passes
Print the number of failures
If more than eight students passed
Print “Raise tuition”
شکل ۱۵-۴ | شبهکد برنامه نتیجه آزمون.
تبدیل به کلاس Analysis
کلاس C++ که مبادرت به پیادهسازی الگوریتم شبهکد کرده است در شکلهای ۱۶-۴ و ۱۷-۴ و دو اجرای نمونه در شکل ۱۸-۴ نشان داده است.
شکل ۱۶-۴ | برنامه بررسی نتیجه آزمون: فایل سرآیند Analysis.
شکل ۱۷-۴ |برنامه بررسی نتیجه آزمون: عبارات کنترلی تودرتو در فایل کد منبع Analysis
شکل ۱۸-۴ | برنامه تست کننده کلاس Analysis
خطوط ۱۶-۱۸ از برنامه۱۷-۴ متغیرهای اعلان کردهاند که تابع عضو processExamResults از کلاس Analysis از آنها برای پردازش نتایج آزمون استفاده می کند. توجه کنید که از یکی از ویژگی های زبان C++ استفاده کردهایم که به مقداردهی اولیه متغیر امکان میدهد تا با بخش اعلان یکی شود (passes با صفر، failures با صفر و studentCounter با ۱ مقداردهی اولیه شدهاند). امکان مقداردهی در ابتدای تکرار هر حلقه وجود دارد، معمولاً چنین مقداردهی های مجددی توسط عبارات تخصیصی بجای اعلانها یا انتقال اعلانها بدرون بدنه حلقه صورت میگیرند.
حلقهwhile ده بار تکرار میشود (خطوط ۲۲-۳۶). در هر تکرار، حلقه یک نتیجه آزمون دریافت و آن را پردازش میکند. دقت کنید که عبارت if..else در خطوط ۲۹-۳۲ برای پردازش هر نتیجه در عبارت whileresult برابر ۱ باشد، عبارت if..else یک واحد به passes اضافه می کند و در غیر اینصورت فرض می کند که result برابر ۲ بوده و یک واحد به failures اضافه می نماید. خط ۳۵ مبادرت به افزایش studentCouunter قبل از اینکه شرط تست حلقه در خط ۲۲ صورت گیرد می کند. پس دریافت ۱۰ مقدار، حلقه پایان یافته و خط ۳۹ تعداد قبولی ها (passes) و مردودی ها (failures) را به نمایش در می آورد. عبارت if در خطوط ۴۲-۴۳ تعیین می کند که آیا تعداد دانشجویان قبول شده بیش از هشت نفر است یا خیر. اگر چنین باشد پیغام “Raise Tuition” به نمایش در می آید. بصورت تودرتو قرار گرفته است. اگر
بررسی کلاس Analysis
در برنامه ۱۸-۴ یک شی Analysis ایجاد (خط ۷) و تابع عضو processExamResults فراخوانی می شود (خط ۸) تا مجموع نتایج آزمون وارد شده توسط کاربر پردازش شود. دو اجرای نمونه از برنامه ۱۸-۴ در خروجی نشان داده شده است. در انتهای اولین اجرا، شرط موجود در خط ۴۲ تابع عضو procesExamResults در شکل ۱۷-۴ برقرار شده (بیش از هشت دانشجو قبول شدهاند) و از اینرو پیغام “Raise Tuition” به نمایش درآمده است.
۱۱-۴ عملگرهای تخصیصدهنده
C++ دارای چندین عملگر تخصیصدهنده برای کاستن از طول عبارات تخصیصی است. برای مثال، عبارت
c = c + 3;
می تواند بصورت زیر و با استفاده از عملگر += نوشته شود
c += 3;
عملگر += مقدار عملوند قرار گرفته در سمت راست را به مقدار عملوند سمت چپ اضافه کرده و نتیجه آنرا در متغیر عملوند سمت چپ ذخیره میکند. هر عبارتی به فرم زیر را
;عبارت عملگر متغیر = متغیر
می توان به فرم زیر نوشت:
;عبارت = عملگر متغیر
عملگر یکی از عملگرهای باینری +، -، *، / یا % و متغیر یک مقدار سمت چپ (lvalue) است. مقدار سمت چپ، متغیری است که در سمت چپ یک عبارت تخصیصی جای می گیرد. جدول شکل ۱۹-۴ حاوی عملگرهای تخصیص دهنده محاسباتی و عبارات نمونهای است که از این عملگرها استفاده میکنند.
عملگر تخصیص دهنده |
عبارت نمونه |
معادل |
تخصیص |
با فرض c = 3، d=5، e=4، f=6 و g=12 |
|||
+= |
c += 7 |
c = c + 7 |
۱۰ به c |
-= |
d -= 4 |
d = d – 4 |
۱ به d |
*= |
e *= 5 |
e = e * 5 |
۲۰ به e |
/= |
f /= 3 |
f = f / 2 |
۲ به f |
%= |
g %= 9 |
g = g % 9 |
۳ به g |
شکل ۱۹-۴ | عملگرهای تخصیصدهنده.
۱۲–۴ عملگرهای افزاینده و کاهنده
علاوه بر عملگرهای محاسباتی تخصیص دهنده، زبان C++ دارای عملگر افزاینده غیرباینری ++ و عملگر کاهنده غیرباینری — است. این عملگرها در جدول شکل ۲۰-۴ توضیح داده شدهاند. اگر متغیر c++ را میتوان بجای استفاده از عبارت c = c + 1 یا c += 1 بکار گرفت. اگر عملگر افزاینده یا کاهنده قبل از یک متغیر قرار داده شود، به مفهوم پیشافزایش یافته یا پیشکاهش یافته خواهد بود. اگر عملگر افزاینده یا کاهنده پس از یک متغیر بکار گرفته شود، به مفهوم پسافزایشی یا پسکاهشی خواهد بود.در هر دو حالت افزایشی یا کاهشی مقدار متغیر یک واحد افزایش یا کاهش پیدا می کند. پس از انجام کار، مقدار جدید متغیر در عبارتی که حاوی آن است بکار گرفته می شود. بخواهد یک واحد افزایش پیدا کند، عملگر افزاینده
عملگر |
عبارت نمونه |
عنوان |
توضیح |
++ |
++a |
پیشافزایشی |
a یک واحد افزایش می یابد، سپس مقدار جدید a در عبارتی که حاوی a است بکار گرفته میشود. |
++ |
a++ |
پسافزایشی |
از مقدار جاری a در عبارتی که حاوی آن است استفاده شده، سپس مقدار a یک واحد افزایش مییابد. |
— |
–b |
پیشکاهشی |
b یک واحد کاهش می یابد، سپس مقدار جدید b در عبارتی که حاوی b است بکار گرفته می شود. |
— |
b– |
پسکاهشی |
از مقدار جاری b در عبارتی که حاوی آن است استفاده شده، سپس مقدار b یک واحد کاهش مییابد. |
شکل ۲۰-۴ | عملگرهای افزاینده و کاهنده.
برنامه شکل۲۱-۴ به توصیف تفاوت موجود مابین نسخههای پیشافزایش و پسافزایش عملگر افزاینده ++ میپردازد. عملگر کاهنده — نیز به طریق مشابهی کار می کند. توجه کنید که این مثال حاوی کلاس نمی باشد، اما فایل کد منبع با main تمام برنامهها کار می کند. در این فصل و فصل سوم شاهد مثالهای بودهاید که حاوی یک کلاس (شامل سرآیند و فایلهای کد منبع برای این کلاس بودهاند) به همراه فایل کد منبع دیگری برای تست کلاس بودند. این فایل کد منبع حاوی تابع main است که یک شی از کلاس ایجاد و توابع عضو خود را فراخوانی میکند. در این مثال، فقط خواستهایم تا مکانیزم عملگر++ را به نمایش در آوریم، از اینرو فقط از یک فایل کد منبع با تابع main استفاده کردهایم. خط ۱۲ مبادرت به مقداردهی اولیه متغیر c با ۵ و خط ۱۳ مقدار اولیه c را به نمایش در می آورد. خط ۱۴ مقدار عبارت c++ را چاپ می کند. این عبارت سبب پسافزایش متغیر c شده و در نتیجه مقدار اولیه c یعنی ۵ چاپ می گردد، سپس مقدار c افزایش می یابد. از اینرو، خط ۱۴ مقدار اولیه c یعنی ۵ را مجدداً چاپ می کند. خط ۱۵ مقدار جدید c یعنی ۶ را برای تاکید بر این نکته که مقدار متغیر براستی در خط ۱۴ افزایش یافته است چاپ می نماید.
شکل ۲۱-۴ |تفاوت مابین عملگرهای پیشافزایشی و پسافزایشی.
خط ۲۰ مقدار متغیر c را به ۵ باز می گرداند و خط ۲۱ مقدار c را چاپ می کند. خط ۲۲ مبادرت به چاپ مقدار عبارت ++c را میکند. این عبارت سبب پیشافزایش c شده است، از اینرو مقدار آن افزایش یافته و سپس مقدار جدید یعنی ۶ چاپ می شود. خط۲۳ مجدداً مقدار c را به نمایش در می آورد تا نشان دهد که مقدار c هنوز پس از اجرای خط ۲۲ برابر ۶ است.
عملگرهای تخصیص ریاضی و عملگرهای افزاینده و کاهنده می توانند عبارات برنامهنویسی را سادهتر کنند. سه عبارت تخصیصی در برنامه ۱۷-۴
passes = passes + 1;
failures = failures + 1;
studentCounter = studentCounter + 1;
را می توان با استفاده از عملگرهای تخصیصی بصورت زیر هم نوشت
passes += 1;
failures += 1;
student += 1;
با عملگرهای پیشافزایشی بصورت زیر
++passes;
++failures;
++studentCounter;
با عملگرهای پسافزایشی بصورت زیر نوشت
passes++
failures++;
studentCounter++;
جدول شکل ۲۲-۴ نمایشی از تقدم و ارتباط عملگرهای مطرح شده تا بدینجا را عرضه کرده است. نمایش عملگرها با تقدم آنها از بالا به پایین است. ستون دوم توصیف کننده ارتباط عملگرها در هر سطح تقدم است. دقت کنید که عملگر شرطی ( ?: ) ، عملگر غیرباینری پسافزایشی ( ++ ) ، پسکاهشی ( – – ) ، جمع ( + ) ، تفریق ( – ) ، و عملگرهای = ، += ، *= ، /= و %= از چپ به راست ارزشیابی می شوند. مابقی عملگرهای جدول شکل ۲۲-۴ از راست به چپ می باشند. ستون سوم اسامی عملگرها را نشان می دهد.
عملگر |
ارتباط |
نوع |
( ) |
چپ به راست |
پرانتز |
++ — static_cast< type >() |
چپ به راست |
غیرباینری |
++ — + – |
راست به چپ |
غیرباینری |
* / % |
چپ به راست |
تعددی |
+ – |
چپ به راست |
افزاینده کاهنده |
<< >> |
چپ به راست |
درج/استخراج |
< <= > >= |
چپ به راست |
رابطهای |
== != |
چپ به راست |
برابری |
?: |
راست به چپ |
شرطی |
= += -= *= /= %= |
راست به چپ |
تخصیصی |
شکل ۲۲-۴ |تقدم و رابطه عملگرهای مطرح شده تا این مرحله.
هیچ دیدگاهی نوشته نشده است.