سری جدیدی از آموزشهای برنامهنویسی آغاز شده است. این سری منقضی شده است. پیشنهاد میکنیم این سری را ادامه ندهید!
در بخش قبلی در مورد برنامه، متغیرها و چند تابع از پاسکال چیزهایی یادگرفتیم. حال میخواهیم سراغ فیلترکردن اطلاعات برویم.
شرطها در پاسکال
در بیشتر مواقع ما نیاز به تصمیمگیری در مورد اطلاعات ورودی کاربر داریم. مثلا یک ماشینحساب ساده نیاز دارد بداند که در حال حاضر کدام عملگر را بین دو عدد ورودی اعمال کند. یعنی نیاز است که بررسی کنیم که کاربر کدام علامت (+ – / ×) را وارد کرده است؛ این کار با اعمال شروط امکانپذیر است.
ساختار کلی شرطها
در پاسکال شرطها به شکل زیر نوشته میشوند:
if {} then {Do something};
که پس از if باید شرط خود را قرار دهیم و پس از then نیز دستوری قرار میگیرد که اگر شرط درست بود باید اجرا شود.
کامنتها
در بیشتر مواقع در برنامهنویسی شما نیاز خواهید داشت که توضیحاتی برای کدهای خود بنویسید. بزارید اینطور توضیح دهم که فرض کنید شما برنامهای با ۱۸۰۰۰ خط نوشتهاید و در هنگام اجرا در خط ۱۵۴۳۶ام آن مشکلی پیش آمده است. مطمئنا انرژی خیلیخیلیخیلی زیادی باید صرف کنید تا بفهمید که قرار بوده در خط ۱۵۴۳۶ چه اتفاقی بیافتد (در این حد که در زبانی مثل پاسکال شاید مجبور باشید ۱۰۰۰ خط قبل و بعد از آن را بررسی کنید تا بفهمید! ولی نگران نباشید، قرار نیست شما برنامهنویس پاسکال باشید!). ولی در هنگام برنامهنویسی کافی است ۱ میلیونیم آن انرژی را صرف کتید و جلوی آن خط کامنتی بگذارید که قرار است چه اتفاقی بیافتد (به همین سادگی! در مورد انرژی زیاد اغراق نمیکنم. در پروژهی خامهعسل ما با همین مشکل روبرو هستیم و هنوز هم نتوانستیم خودمان را از این باتلاق بیرون بکشیم!)
در پاسکال کامنتها به دو صورت در کدهای شما قرار میگیرند:
(*your comment line 1 Line 2 Line 3 Line 4*)
یا
{your comment line 1 Line 2 Line 3 Line 4}
که تا آنجایی که ما فهمیدیم هیچ فرقی با یکدیگر ندارند!
خوب برگردیم سراغ شرطهای خودمان.
فرض کنید که میخواهیم سن کاربرمان را بپرسیم. در مرحلهی اول لازم است چک کنیم که کاربر سنش را غلط وارد نکند. پس با فرض این موضوع که در زمان نوح (ع) زندگی نمیکنیم بیشترین سن را ۲۰۰ سال و کمترین را ۰ در نظر میگیریم. پس برنامه به شکل زیر خواهد بود:
var age: integer; ageOK: boolean; begin writeln('plz enter you age:'); readln(age); ageOK:= false; if a>0 then if a<200 then ageOK:= true; {do another things} end.
خوب در برنامهی بالا ما دو شرط را درون هم قرار دادیم. یعنی در کل به این صورت میشود که اگر شرط اول درست باشد، پاسکال دستور درون شرط را اجرا میکند که از قضا اینجا یک شرط دیگر است و آن هم اجرا میشود و پس از پایان شروط نیز پاسکال به انجام دستورات بعدی ادامه میدهد.
دورزدن پاسکال با begin و end; !
اگر متوجه شدهباشید در دستور پس از if شما اجازه دارید فقط یک دستور را اجرا نمایید و این موضوع مطمئنا مشکلزا خواهد بود. برای همین هم ما میتوانیم با یک «تکهبرنامه» این محدودیت را دور بزنیم. مثلا فرض کنید در برنامهی بالا به کاربر بگوییم که شما که سنتان از ۰ کمتر است در زمان سفر کردهاید یا اگر سنشان از ۲۰۰ بیشتر است میتوانند خودشان را به کتاب رتبههای سالیانهی گینس معرفی کنند!
پس برنامه به شکل زیر تغییر میکند:
var age: integer; ageOK: boolean; begin writeln('plz enter you age:'); readln(age); ageOK:= false; if a>0 then begin if a<200 then begin ageOK:= true; end; if ageOK=false then writeln('The Guinness Book should know you!'); end; if ageOK=false then writeln('Did you do time travelling?!? Or did you see Karim Khan Zand?!? '); {do another things} end.
پس ما بهجای قرار دادن یک دستور، چند دستور را در قالب یک «تکهبرنامه» قرار دادیم. توجه داشته باشید که طریقهی نوشتن تکهبرنامهها به صورت خطی است یعنی هر begin با اولین end; پایان مییابد و تکهبرنامهها یکدیگر را قطع نمیکنند (یعنی نمیشود یک تکهبرنامه (پسر) داخل یک تکهبرنامهی دیگر (پدر) آغاز شود ولی پدر قبل از پسر به اتمام برسد {احترامی چیزی گفتن!})
البته این برنامه، برنامهی بزرگی شد چون هنوز مبحث بعدی را نیاموختهایم!
انجام کاری در صورت درست نبودن شرط
در برنامهی بالا برای اینکه بفهمیم که شرط غلط انجام شده یا نه مجبور شدیم چک کنیم که دستوری که درون شرط بوده انجام شده یا نه ولی همیشه از این شانسها نداریم که بتوانیم انجامشدن دستور را چک کنیم (مثلا فرض کنید درون دستور فقط نوشتهای چاپ میکردیم. در آنصورت بعید میدانم با پاسکال میتوانستیم چک کنیم که چیزی در کنسول چاپ شده است یا نه!)
برای انجام کاری در صورت درست نبودن شرط باید از کلیدواژهی else استفاده کرد. ساختار کلی if – else به شکل زیر است:
if {if statement} then begin {do something} end; else begin {do something} end;
پس حالا برنامهای که نوشتیم به شکل زیر در میآید:
var age: integer; ageOK: boolean; begin writeln('plz enter you age:'); readln(age); ageOK:= false; if a>0 then begin if a<200 then begin ageOK:= true; end; else writeln('The Guinness Book should know you!'); end; else writeln('Did you do time travelling?!? Or did you see Karim Khan Zand?!?'); {do another things} end.
که از برنامهی قبلی جمعوجورتر است.
خوب با این اوصاف ما میتوانیم برنامهای چندمنظوره برای کاربر بسازیم. یعنی در ابتدا یک منو چاپ کنیم و به کاربر اجازه دهیم تا از بین گزینههای موجود یکی را انتخاب کند. مثلا برنامهی زیر میتواند مثال مناسب و انعطافپذیری باشد {برنامهای جامع برای همهی سلیقهها!}
var menu: integer; begin writeln('Hi, Welcome to my beautiful user friendly application designed for 2013 uesrs!'); writeln('Please chose one the items below:'); writeln('- Press 1 for Do job 1'); writeln('- Press 2 for Do job 1'); writeln('- Press 3 for Do job 1'); writeln('- Press 4 for Do job 1'); writeln('- or Press anything else to close this beautiful application'); writeln('I"m waiting …'); readln(menu) if menu=1 then begin {Do Job 1} end; if menu=2 then begin {Do Job 2} end; if menu=3 then begin {Do Job 3} end; if menu=4 then begin {Do Job 4} end; writeln('I"m Happy you used my beautiful user friendly application!'); writeln('Have a good time'); writeln('Good Bye!'); readln(); end.
خوب فکر نمیکنم نیازی به توضیح داشتهباشید {اگر در مورد نوشتههای انگلیسی نیاز به توضیح دارید در دیدگاه بیان کنید!} پس بهتر است تا دیر نشده به سراغ مبحث بعدی برویم {الان ساعت ۲:۱۳ بامداد!}
کدهای چرخشی
در مواقعی شما نیاز دارید تا کاری را چندبار انجام دهید. مثلا بخواهید نمرهی ۲۰ نفر را از کاربر بگیرید و میانگین آنها را برای آنها چاپ کنید {این مثال واقعا تکراری بود! فکر کنم هر کتاب آموزشی را که باز کنید این مثال را بتوانید تویش پیدا کنید!} یا کارهای جالبتر مثلا چاپ یک مثلث متساویالساقین ستارهای به ساق ۲۰ خط {از این کارها هم انجام میدهیم! کمی صبر کنید} مطمئنا استفاده از کپی و پیست {مثلا ۲۰ تا readln بنویسیم!} ، روش جالبی برای گرفتن ورودی (نمرات) یا چاپ خروجی (یک مثلث نسبتا بزرگ!) نخواهد بود.
اینجاست که چرخشها یا Loopها به کمک شما میآیند.
for
میتوان گفت for معمولترین دستور چرخشی در زبانهای برنامهنویسی است. در دستور for ما یک شمارنده داریم و یک هدف و از مقدار اولیهی شمارنده یکییکی به آن اضافه میکنیم و در هر بار اضافهکردن به شمارنده، یک بار دستوری که قرار است اجرا شود را اجرا میکنیم {نگران نباشید. ما قرار نیست این کار را انجام دهیم. پاسکال خودش این کار را برای ما انجام میدهد!}
چون در دستور for ما نیاز به یک متغیر به عنوان شمارنده داریم، فرض میکنیم که متغیر i در ابتدای برنامه تعریف شده است. پس ساختار for به شکل زیر خواهد بود:
for i:=0 to 100 do {do something}
یا اگر بخواهیم پاسکال را دور بزنیم به شکل زیر در خواهد آمد:
for i:=0 to 100 do begin {do something} end;
ساختار چینش درختی برنامه
اگر دقت کرده باشید در برنامههایی که در بالا مثال زدیم هروقت که دستورات بهعنوان فرزند دستورات دیگری بودند از یک Tab (یا ۸ تا اسپیس) استفاده کردیم. این ساختار به خواناتر شدن کد کمک بسیاری میکند و به کسی که کد را میخواند کمک میکند تا راحتتر آن را درک کنند. به شما پیشنهاد میکنیم که شما هم در کدهایتان از این ساختار استفاده کنید.
البته زیاد لازم نیست زحمت بکشید. فقط محیط ویرایشگر پاسکال بلد نیست خودش کدها رو مرتب کنه. چند وقت دیگه که وارد سیپلاسپلاس و سیشارپ شدیم دیگه در این مورد مشکلی نخواهیم داشت چون هزار ماشاالله همهی محیطهای جدید در جهت راحتی و تنبلی برنامهنویسها کار میکنند و کم مونده ازشون درخواست کنیم که کد رو برامون بنویسند! البته الانش هم همین کامپایلرها یهجورایی دارن برامون کدها رو مینویسن. {داستان اسمبلی رو که یادتون نرفته؟!؟}
خوب بهتره بحث for رو ادامه بدیم.
به رسم اکثر آموزشها اول برنامهی میانگین رو به عنوان مثال در اینجا قرار میدیم:
var now: integer; avg: real; i: integer; begin readln(now); avg:=now; for i:=1 to 19 do begin readln(now); end; avg:=avg/20; writeln(avg); end.
خوب در برنامهی بالا for را تا ۱۹ رفتیم چون یکی از نمرهها را قبلا از کاربر گرفتهبودیم. توجه داشته باشید که حتی میتوان تعداد ورودیها را نیز از کاربر گرفت. یعنی لزومی ندارد که نقاط شروع و پایان for را از قبل تعیین کنیم و میتوانیم آنها را نیز به کاربر بسپاریم.
حالا میخواهیم مثلثی مثل مثلث زیر چاپ کنیم
* ** *** **** ***** ******
برای اینکار لازم است از یک for تو در تو استفاده کنیم. به این معنی که درون یک for، یک for دیگر قرار دهیم.
برای جالبتر شدن نیز تعداد خطوط را به کاربر میسپاریم {در هنگام نگارش این سطور یعنی ساعت ۲:۵۱ بامداد نویسنده کمی خوابش میاید. اگر برنامه کمنمک یا پرنمک بود ببخشید!}
var i,j,n: integer; begin writeln('Welcome to my wonderful mathematical application.'); writeln('You are here and want me to draw a triangle for you!'); writeln('So I"m waiting for you to give me length of it"s leg …'); readln(n); for i:=1 to n do begin for j:=1 to I do write('*'); writeln(); end; writeln('I finished drawing. Don"t forget to pay me otherwise I will not draw any other things for you! :X'); writeln('Honestly there are a lot of consumers waiting for me to draw things for them!'); end.
و خوب فکر میکنم برنامه نیاز به توضیح ندارد. فقط اینکه for پدر در برنامهی ما نقش اشارهگر خط را بازی میکرد و با هر حرکت آن یک خط رسم میشد و به همین دلیل نیز در انتهای دستورات آن writeln() مشاهده میشود (برای اینکه در خروجی به خط بعدی برویم!). {ساعت ۳ بامداد است. ادامهاش برای فردا!}
تا نشدهست آن تمام
{صبح بخیر!} بعد از for پرکاربرد ترین دستور چرخشی while است. مفهوم کلی آن این است که تا وقتی که یک شرط صحیح است کاری را انجام بده. مثلا منوی کاربرپسند (User Friendly!) که با if نوشتیم اگر تنها یک بار اجرا شود کاربردی ندارد (برای هر ابزار برنامه باید دوباره اجرا شود. مثل اینکه کاربر برنامههای جداگانهی مختلف را اجرا کند) ولی اگر کاربر بتواند ابزارهای مختلف را استفاده کند و هروقت که خواست خارج شود مثلا ۰ را بزند، برنامهی ما کاربرپسندتر میشود!
پس برنامهی کاربرپسندمان را اینطور ویرایش میکنیم:
var menu: integer; mCheck: integer; begin writeln('Hi, Welcome to my beautiful user friendly application designed for 2013 uesrs!'); mCheck:= true; while mCheck do begin writeln('Please chose one the items below:'); writeln('- Press 1 for Do job 1'); writeln('- Press 2 for Do job 1'); writeln('- Press 3 for Do job 1'); writeln('- Press 4 for Do job 1'); writeln('- or Press anything else to close this beautiful application'); writeln('I"m waiting …'); readln(menu) if menu=1 then begin {Do Job 1} continue; end; if menu=2 then begin {Do Job 2} continue; end; if menu=3 then begin {Do Job 3} continue; end; if menu=4 then begin {Do Job 4} continue; end; mCheck:= false; end; writeln('I"m Happy you used my beautiful user friendly application!'); writeln('Have a good time'); writeln('Good Bye!'); readln(); end.
continue و break، دو دستور کاربردی برای کنترل چرخشها
گاهی اوقات لازم است که ما اجرای دستورات چرخش را متوقف کنیم و به چرخش ادامه دهیم و یا کلا از چرخش بیرون بیاییم. مثلا در برنامهی بالا لازم است که پس از اینکه کاری که کاربر تعیین کردهاست را انجام دادیم، دیگر به کارمان ادامه ندهیم (وگرنه mCheck برابر false میشود و حلقه ادامه نمییابد!) برای همین از دستور continue استفاده کردیم.
اما در برنامهی بالا میتوانستیم بهجای تعریف یک متغیر اضافی از دستور break استفاده کنیم که نتیجهی نهایی میشود برنامهی پایین:
var menu: integer; begin writeln('Hi, Welcome to my beautiful user friendly application designed for 2013 uesrs!'); while true do begin writeln('Please chose one the items below:'); writeln('- Press 1 for Do job 1'); writeln('- Press 2 for Do job 1'); writeln('- Press 3 for Do job 1'); writeln('- Press 4 for Do job 1'); writeln('- or Press anything else to close this beautiful application'); writeln('I"m waiting …'); readln(menu) if menu=1 then begin {Do Job 1} continue; end; if menu=2 then begin {Do Job 2} continue; end; if menu=3 then begin {Do Job 3} continue; end; if menu=4 then begin {Do Job 4} continue; end; break; end; writeln('I"m Happy you used my beautiful user friendly application!'); writeln('Have a good time'); writeln('Good Bye!'); readln(); end.
اعمال منطقی پاسکال
اگر تا حالا فکر میکردید که کامپیوتر دنیای درهم و برهمی است اشتباه میکردید! بلکه کامپیوتر منطقیترین موجود جهان است {البته از مجموع همهی منطقها چیزهای درهم و برهمی ساخته میشوند مثل ویندوز، اینترنت و کلی چیز دیگر! اشتباه نکنید! کامیپوتر منطقی است، اما ما کاملا منطقی نیستیم و این باعث آشوب میشد!}
اما خیلی وقتها لازم است که در یک شرط چند گزارهی منطقی را باهم چک کنیم. مثلا در مثالی که برای if آوردیم، خیلی بهتر میشد اگر آن شرط تو در تو را در یک شرط بزرگتر جمع آوری کنیم. اما مانند دنیای منطق، اینجا هم چند عملگر منطقی برای گزارهها وجود دارد که آنها را بررسی میکنیم:
and
اگر لازم باشد که هر دو (یا چند) شرط در یک زمان برقرار باشند باید از and استفاده کرد. مثلا برنامهی مثال را میتوان به شکل زیر نوشت:
var age: integer; ageOK: boolean; begin writeln('plz enter you age:'); readln(age); ageOK:= false; if (a>0) and (a<200) then ageOK:= true; {do another things} end.
توجه دقت کنید که حتما از پرانتز () برای جداکردن گزارهها استفاده کنید.
or
گاهی اوقات درست بودن یکی از شروط کافی است. مثلا میخواهیم نمرات دانشآموز را از طریق ایمیل برای پدر یا مادر او ارسال کنیم {فرستادن ایمیل در پاسکال؟!؟ عمرا!} و ما لیستی داریم که شامل ایمیل دانشآموز، ایمیل پدر و ایمیل مادر اوست. پس لازم است که فردی که ایمیل براش ارسال میشود پدر یا مادر دانشآموز باشد. در این حالت شرط ما به شکل زیر خواهد آمد (فرض میکنیم متغیر type مقادیر s (دانش آموز)، f (پدر) و m (مادر) را داشته باشد)
if (type='f') or (type='m') then {send mail!}
یا میتوان از یک راه بهتر استفاده کرد و آن این است که چک کنیم که فرد دانشآموز نباشد. پس if ما به شکل زیر خواهد آمد:
if type<>'s' then {send email!}
not
اگر بخواهیم برعکس یک گزارهی شرطی را چک کنیم، باید از عملگر not استفاده کنیم. مثلا در مثال بالا «اگر فرد دانشآموز نبود» را به شکل زیر هم میتوان نوشت
if not (type='s') then {send email!}
البته در برنامهنویسی کاربردی پیشنهاد میشود که از حالت اول استفاده کنید. چون در حالت دوم شما دو عمل منطقی روی گزاره انجام میدهید (اول گزارهی منطقی true یا false را برمیگرداند و سپس آنرا برعکس میکنیم!) که در کارهای واقعی همین باعث مشکلاتی در ساختار برنامه میشود {اندک، اندک جمع گردد وانگهی دریا شود. همینا جمع میشه بعد برنامهتون نیمساعت طول میکشه تا یه جمع ساده رو انجام بده!}
عملگرهای مقایسهای
در مثالهای این بخش از عملگرهای مختلفی در شرایط مختلف استفاده کردیم که بد نیست آنها را نیز توضیح دهیم {در اصل در یک جا جمعآوری کنیم برای شب امتحان!} (چون مثال در بالا وجود دارد دیگر آنها را تکرار نمیکنیم}
- تساوی: اگر بخواهیم تساوی بین دو متغیر (یا یک متغیر و یک چیز ثابت) را چک کنیم از علامت = استفاده میکنیم.
- کوچکتر، بزرگتر: برای بررسی کوچکتری و بزرگتری مانند ریاضیات شیرین دورهی ابتدایی {از ابتدایی شروع و تا کنون ادامه دارد!} از < و > استفاده میکنیم و اگر بخواهیم بزرگتر مساوی یا کوچکتر مساوی را چک کنیم از <= یا >= استفاده میکنیم.
- نامساوی: برای این چک کنیم که دو عبارت مساوی نباشند باید از <> استفاده کنیم.
خوب در این بخش شروط و چرخشها (حلقهها) را آموختیم. بخش بعدی مفاهیم برنامهنویسی به اتمام میرسد و وارد برنامهنویسی سیپلاسپلاس میشویم {بخش بعدی پاسکال تمام میشود! هورا!} تا کمی عملیتر برنامهنویسی یاد بگیریم.
تمرینها
با تشکر از اینکه تمارین بخش قبلی را حل کردید برای این بخش هم تعدادی تمرین در نظر گرفتهایم. اگر احیانا کسی زحمت کشید و هر کدام از تمارین را حل کرد ما هم کمی انگیزه پیدا میکنیم و جواب تمرینها را در نوشتهای منتشر میکنیم {به قول استاد خوب حسابانمان :نمیخواهید یاد بگیرید اصلا چرا میاد نوشته رو میخونید. برید به مامانتون بگید من نمیخوام یاد بگیرم برید سیگار فروش شید چرا هی وقتتون رو با خوندن این چرتوپرتها تلف میکنید؟ :دی}
- ب.ب.ک (برنامهای بنویسید که) قد دانشآموزان را بگیرد (تعداد دانشآموزان را نیز کاربر تعیین میکند) و میانگین، کوتاهترین و بلندترین قد آنها را چاپ کند.
- ب.ب.ک ابتدا دو عدد از کاربر بگیرد و سپس با یک محیط کاربرپسند از او بپرسد که قرار است با آن عددها چه کاری بکند (جمع، صرب، تقسیم، تفریق) و نتیجه را چاپ کند.
- برنامهای بنویسید که یکسری آدرس صفحات بگیرد و تعداد آنهایی که از سایت دو برنامهنویس هستند را چاپ کند.
پینوشت: اگر مشکلی دارید میتوانید در دیدگاهی مشکل خود را بیان کنید و یا اگر بخشی از این آمورش نادرست است لطفا اطلاع دهید {متشکرم!}
یک نکتهی مهم {سوال انحرافی}: در مثالهای بالا (در کدهای بالا) اشتباه در دو مثال تکرار شده (راهنمایی یک کلیدواژه اشتباها بهعنوان متغیر استفاده شده) آیا میتوانید آن را بیابید؟
کاش در کدها Tab میزدی تا بهتر خونده بشن، به خصوص اون که به گینس و سفر در زمان مربوط میشه. سعی کردم فاصله اضافه کنم، نشد. لطفاً خودت یه کاریش بکن احمد!
مشکل حل شد. من قبل از ارسال نوشته چندین بار این کار رو میکردم ولی وردپرس گند میزد. امیدوارم دیگه خراب نکنه
سلام من تازه شروع کردم به یادگرفتن برنامه نویسی ولی معلم ما به خوبی شما به ما این مباحث را توضیح ندادن
واقعا خیلی کارتون درسته :)
ممنون
راستی مسئله هم بدین مثلا از فاکتوریول یا میانگین یا….
سلام.میگم اینا رو که یادبگیریم چی میشه اونوقت. یعنی الان من باید برنامه ای رو نصب کرده باشم و اینارو اونجا تمرین کنم؟چه برنامه ای؟اصلا الان کجای دنیای برنامه نویسی هستیم؟
سلام!
اول اینکه این سری آموزش منقضی شده و ما آموزش سیپلاسپلاس رو شروع کردیم (باید از http://2bn.ir/170 نوشتهی «شروع دوباره» شروع کنید)
در مورد این سری در ابتدای این نوشته http://2bn.ir/171 گفتیم که برنامههای پاسکال رو توی ویندوز باید توی محیط free pascal بنویسید. و تمرین کنید.
و الان میشه گفت ما هیچ جا نیستیم توی دنیای برنامهنویسی. کاری که ما الان داریم انجام میدیم (چه توی این دورهی منقضیشده و چه توی دورهای که توش هستیم) اینه که پایههای برنامهنویسی که توی اکثر زبانهای برنامهنویسی مشترک هستند رو یاد بگیریم. بعد از اون میریم سراغ زبانهای کاربردی تر مثل سیشارپ برای ویندوز و سرور و مثلا جاوااسکریپ برای وب و تکنولوژیهای مرتبط با اونها مثل جیکوئری رو یاد میگیریم.
البته تا سال آینده چون هر سه ما درگیر کنکور هستیم اگر آموزش پایه تموم بشه خیلی خوبه و البته از سال آینده فعالتر آموزشهامون رو ادامه میدیم (و مهدی و محمد هم آموزشهای خودشون رو پس از اتمام آموزشهای پایه شروع میکنن)