آموزش برنامه‌نویسی – بخش هفتم – پایان حلقه‌های بی‌پایان!

سلام!
بعد از مدت‌ها (و احتمالاً پیش از مدت‌ها!) که نبودم و آموزش برنامه‌نویسی تعطیل شده بود بین درگیری‌های کنکور بالاخره وقتی پیدا شد که آموزش رو ادامه بدم و البته چون درگیری‌های کنکور روز به روز داره زیاد می‌شه معلوم نیست دوباره کی بتونم این کار رو ادامه بدم (امیدوارم که بشه ادامه بدم و اگر هم نشد مطمئناً بعد از کنکور ادامه میدم و برای همین هم توی پرانتز اول گفتم پیش از مدت‌ها!) و البته دیر و زود داره ولی سوخت و سوز نداره!

امروز می‌خواهیم باهم یادگیری حلقه‌ها رو ادامه بدیم.

اگر یادتون باشه جلسه‌ی قبل ما فهمیدیم که توی سی‌پلاس‌پلاس یه‌چیزی به اسم for وجود داره برای این که به تعداد معینی یه کاری رو تکرار کنیم. و ازش برای کارهای مختلفی استفاده کردیم (و توی تمرین‌ها کردید!) و استفاده خواهیم کرد. بزارید برای این که یادآوری بشه یه تیکه‌کد برای گرفتن میانگین n تا عدد (که n رو کاربر بهمون می‌ده) استفاده کنیم.

برنامه‌مون این‌جوری می‌شه:

int n=0;
double tmp=0;
cin >> n;
for( int i = 0 ; i> j;
tmp+=j;
}
cout << tmp/n;

و البته این برنامه که قرار بود جهت یادآوری باشه بار آموزشی هم داره!
ببینید ما توی خط دوم از نوع جدیدی از متغیرهای به اسم double استفاده کردیم. این نوع متغیر (به همراه نوع float) اعداد اعشاری رو توی سی‌پلاس‌پلاس ذخیره می‌کنن. یعنی اگر می‌خواهید اعداد اعشاری مثل ۲.۵ رو توی متغیری ذخیره کنید باید از این دو نوع استفاده کنید.

تفاوت float و double (که در‌واقع double float هست‌ش) در دقت اعشاری عددیه که ذخیره می‌کنید که دقت double از float بیش‌تره و اگر دقت اعشاری بیش‌تری می‌خواهید باید از double استفاده کنید که البته فضای رم بیش‌تری هم ازتون می‌گیره (هر چیز خوبی که می‌گیرید باید یه چیزی رو فداش کنید!)

من هم توی برنامه‌ی بالا طبق عادت و با توجه به این که بهینه‌سازی برنامه فعلاً برامون اهمیتی نداره از نوع double استفاده کردم.

خوب برنامه‌ی بالا تقریباً واضحه ولی بازم توضیح‌ش می‌دیدم. اول از همه یه متغیر تعریف می‌کنیم که مجموع همه‌ی عددهایی که از کاربر می‌گیریم رو توش ذخیره کنیم (می‌دونیم که میانگین برابر جمع همه‌ی اعداد تقسیم بر تعدادشونه) و یک عدد صحیح هم تعریف می‌کنیم که تعداد عددهاییه که قراره میانگین‌شون رو بگیریم. و این عدد رو از کاربر می‌گیریم و به تعدادش از کاربر عدد می‌گیریم (که می‌تونه اعشاری باشه یا نباشه ولی در هر صورت ما تو یه متغیر اعشاری ذخیره‌ش می‌کنیم) و در نهایت هم مجموع اعداد رو به تعدادشون تقسیم می‌کنیم و توی خروجی چاپ می‌کنیم.

خوب بعد از for سراغ نوع دیگه‌ای از حلقه‌ها می‌ریم که اون هم خیلی توی برنامه‌نویسی کاربردیه. خوب توی for ما لازم داریم که تعداد دفعات تکرار رو بدونیم. یعنی بدون اون اصلاً کارمون جلو نمی‌ره. ولی همیشه که تعداد دفعات تکرار یک چیز ثابت و معلوم نیست.

مثال غیر برنامه‌نویسی‌ش می‌شه اینکه وقتی می‌خواهیم چایی رو شیرین کنیم می‌گن تا وقتی که شکر توی چایی حل شده باید چایی رو هم بزنیم. نمی‌گن که ۲۳.۵ بار دقیقاً چایی رو هم بزنی تا شکر حل بشه که. بسته به مقدار شکری که داریم دفعات‌ش فرق می‌کنه!

توی برنامه‌نویسی هم قضیه همینه. مثلاً وقتی که می‌خواهیم از کاربر پسوردشون بپرسیم. مطمئناً اگر دفعه‌ی اول پسورد رو درست وارد کرد حلقه باید تموم بشه و نباید دو بار دیگه ازش پسورد بپرسیم! (اگر محدودیت واردشدن با پسورد درست ۳ باشه) یا یک‌سری از مسائلی که با for سخت‌تر حل می‌شده رو می‌تونیم با while آسون‌تر حل کنیم. جلوتر که بریم با این مسائل آشنا می‌شیم.

شکل کلی while این‌جوریه:

while({Boolean statement})
{
//do something
}

که مثل if و بخش دوم for این‌جا هم با یک عبارت منطقی (درست یا غلط) به while می‌گیم که کارش رو انجام بده یا نده. while وقتی کارش رو انجام می‌ده که اون عبارت منطقی درست باشه.

اصولاً برنامه وقتی به while می‌رسه اول شرط توی while رو چک می‌کنه.
بعد از اون اگر شرط درست نبود از while میاد بیرون و برنامه رو ادامه می‌ده (بعد از تکه‌کد while)
اگر شرط درست بود تا زمانی که شرط درست باشه تکه‌کد while تکرار می‌شه.

برای مثال بیاید یه برنامه بنویسیم که اولین عدد بزرگ‌تر از ۰ که هم مضرب ۲ باشه هم مضرب ۸۳ رو پیدا و چاپ کنه.

int i=1;
while(!((i%2==0)&&(i%83==0)))
{
i++;
}
cout << i << endl;

و خوب واضحه که خروجی برنامه عدد ۱۶۶ خواهد بود. چون while تا زمانی که نقیض شرط «(اگر i بر ۲ بخش‌پذیر بود) و (اگر i بر ۸۳ بخش‌پذیر بود)» برقرار باشه (یعنی از i=1 تا i=165) مقدار i را یکی زیاد می‌کنه تا به عدد ۱۶۶ برسه و چون توی عدد ۱۶۶ عبارت منطقی «(اگر i بر ۲ بخش‌پذیر بود) و (اگر i بر ۸۳ بخش‌پذیر بود)» مقدار «درست» رو خروجی می‌ده پس نقیضش می‌شه «غلط» که باعث می‌شه از while بیایم بیرون. و بعدش هم برنامه i که ۱۶۶ باشه رو خروجی می‌ده.

البته یکی از خواص for توی سی‌پلاس‌پلاس (و توی زبون‌هایی که ازش مشتق شده‌اند مثل سی‌شارپ و جاوا و زبون‌های دیگه) اینه که می‌شه با خالی گذاشتن یکی از اون بخش‌هاش اون رو به while تبدیل کرد.

ببینید توی for ما سه بخش داشتیم. توی بخش اول متغیر forمون رو تعریف می‌کردیم که فقط دفعه‌ی اول اجرا می‌شد. توی بخش دوم ما یه شرط داشتیم که for تا کجا باید تکرار بشه (چه جالب! مثل while!) و بخش سوم هم بلایی بود که بر سر متغیر for می‌آوردیم.

در‌واقع این نوع for توی سی‌پلاس‌پلاس ساخته شد و توی زبون‌هایی مثل پاسکال یا بیسیک کاربر for فقط شمارشی بود یعنی بهشون می‌گفتیم از ۱۰ تا ۲۰ برو و فلان کار رو انجام بده. و البته چون توی اکثر آموزش‌ها و کدها کاربرد شمارشی for‌ رو در نظر می‌گیرن ماهم از همین کاربردش استفاده می‌کنیم.

و این خوبه چون باعث خواناتر شدن کدمون می‌شه و موقع دیباگ خیلی به‌درد می‌خوره (خیلی راحت‌تر می‌شه فرق بین for و while رو تشخیص داد تا این که بخواهیم فرق بین for و forای که بخش اول و سوم نداره رو تشخیص بدیم!)

و البته for توی سی‌پلاس‌پلاس کاربرد شمارشی داره ولی توی زبون‌های دیگه ممکنه کاربردش ۱۸۰ درجه متفاوت باشه و اصلاً مفهوم شمارش توش مطرح نباشه (مثل زبان پایتون)

خوب برای این که مثال‌ش رو هم دیده باشید ما برنامه‌ی بالا رو با for بازنویسی می‌کنیم (و البته بعد از اون توبه می‌کنیم و دیگه این استفاده رو for رو به‌کار نمی‌بریم!)

int i=1;
for(;!((i%2==0)&&(i%83==0));)
{
i++;
}
cout << i << endl;

توی برنامه‌ی بالا چون می‌خواستیم از i بعد از for استفاده کنیم (یادمون نرفته که اگر i رو توی for تعریف کنیم فقط می‌شه توی همون for ازش استفاده کرد) اون رو خارج از for تعریف کردیم و بقیش هم مثل کد قبلی می‌شه. البته چون این‌جا توی for فقط یک کار انجام می‌دیم می‌تونیم برنامه رو به شکل پایین هم بنویسیم:

int i=1;
for(;!((i%2==0)&&(i%83==0));i++);
cout << i << endl;

که توی این‌جا برای کم‌تر کدنویسی (تنبلی برنامه‌نویس‌ها رو هم که یادتون نرفته!) و برای این که forمون دستور اضافی‌ای اجرا نکنه i++ رو به بخش سوم forمون منتقل کردیم. البته بهتره که وقتی که کمی خبره‌تر شدید از این روش استفاده کنید چون دیباگ کردن این نوع کد یه‌ذره از حالت قبلی سخت‌تره.

و آخرین نوع حلقه‌ای که یاد می‌گیریم خیلی به while شبیهه و کاربردش هم خیلی کم‌تره (تقریباً هیچ‌وقت ازش استفاده نکردم) ولی این رو هم مثل استفاده‌ی غیرمعمول از for که بالا گفتیم می‌گیم که اگر یه‌جایی دیدید بتونید بفهمید که چی‌کار می‌کنه. البته اگر هم نگم تشخیص این که چی‌کار می‌کنه خیلی آسونه.

اسم این نوع سوم do-while هست‌ش و این‌جوری هم توی کد میاد:

do
{
    //do something
}
while({Boolean statement});

که فرق‌ش با while اینه که دستورات while قبل از خودش میاد (و برای همین از do استفاده می‌کنیم که برنامه بفهمه که اینا دستورات متعلق به while هستن) و این که دستورات‌ش قبل از خودش میان باعث می‌شه که حتماً یک بار این تکه‌کد اجرا بشه. در حالی که توی while اگر عبارت شرطی‌مون «غلط» رو بر می‌گردوند کدهای while دیگه اجرا نمی‌شدن.

کاربرد این مثلاً توی کد چک کردن پسورده. یعنی حتماً پسورد یک بار باید چک بشه و اگر پسورد غلط بود دوباره از کاربر پسورد رو بگیره.

int pass=0; do { cin >> pass;
}
while(pass!=1234)

و توی کد بالا تا وقتی کاربر ۱۲۳۴ (که پسورد فرضی‌مونه) رو نزنه برنامه توی حلقه‌ی while گیر می‌کنه
و البته کد بالا اصلاً ایده‌آل نیست چون تعداد زیادی پسورد غلط زدن می‌تونه مشکل امنیتی توی سیستم به‌وجود بیاره. ولی خوب برای این مثال خوبه.

خوب تا این‌جا تقریباً مفاهیم پایه برنامه‌نویسی رو یاد گرفتیم. یعنی تا الان تقریباً تمام چیزهایی رو که پایه‌های برنامه‌نویسی سی‌پلاس‌پلاس (و اکثر زبان‌های برنامه‌نویسی) محسوب می‌شن رو یاد گرفتیم و این‌ها قراره پایه‌هایی بشن برای چیزایی که بعدن یاد می‌گیریم و البته اونا هم به نوبه‌ی خودشون پایه‌ی چیزهایی می‌شن که بعدن یاد می‌گیریم و در نهایت هم همه‌ی اینایی که یاد می‌گیریم پایه‌ای می‌شن برای زبان‌های کاربردی‌تری که در آینده یاد می‌گیریم. (خیلی پیچیده شد! نه؟)

برای تمرین:

-ب.ب.ک میانگین نمرات تعداد نامشخصی از دانش‌آموزها رو حساب کنه. (راهنمایی: تا زمانی که کاربر نمره -۱ رو وارد نکرده یعنی داره نمره وارد می‌کنه)
-سعی کنید برنامه‌ی بالا رو با for بنویسید.
-ب.ب.ک ۴۲۵۶امین عدد اول رو پیدا و چاپ کنه.
-ب.ب.ک با حداکثر ۱۰ با خطای ورود پسورد از کاربر پسورد رو بگیره و اگر پسورد غلط بود به کاربر خطا بده که پسورد غلطه و اگر درست بود بهش آفرین بگه!

5 دیدگاه در “آموزش برنامه‌نویسی – بخش هفتم – پایان حلقه‌های بی‌پایان!

    1. سلام دوست عزیز
      همونطور که ابتدای نوشته گفتم ما هر سه مون امسال درگیر کنکور هستیم و ترم پیش دانشگاهی مون هم شروع شده و به شدت کمبود وقت داریم. انشاالله بعد از کنکور وب نوشت رو بهتر میکنیم

  1. سلام اموزشتون عالیه ولی اگه مثل قسمت سوم با فیلم آموزش بدید بهتر میشه اگه میشه این کارو بکنید چون اونجوری راحت تر میشه فهمید و درک کرد
    ممنون

    1. مشکل من زمانه! تقریبا دو هفته ای میشه که فرصت نمیکنم بخش هشتم رو تموم کنم. سعیمو میکنم ولی قولی نمیدم

پاسخ دادن به احمدعلی شفیعی لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *