درس ۶ از ۴۹ · جریان برنامه

شرط‌ها

با شرط‌ها برنامه بر پایه‌ی داده‌ها تصمیم می‌گیرد کدام راه را برود. سلام در شرط‌ها سخت‌گیر است: شرط همیشه یک مقدار منطقی واقعی است و مترجم شاخه‌هایی را که هرگز اجرا نمی‌شوند نشان می‌دهد.

اگر، وگرنه اگر، وگرنه

بدنه‌ی اگر فقط وقتی اجرا می‌شود که شرطش درست باشد. می‌توانید با وگرنه اگر شرط‌های بیشتری بیازمایید و با وگرنه هر حالت باقی‌مانده را پوشش دهید. شرط‌ها از بالا به پایین آزموده می‌شوند و تنها نخستین شاخه‌ای که شرطش درست است اجرا می‌شود؛ پس آزمون تنگ‌تر را بالاتر بنویسید.

conditions.salam
تابع رده(نمره: صحیح): رشته:
    اگر نمره >= ۹۰:
        برگشت "عالی"
    وگرنه اگر نمره >= ۷۰:
        برگشت "خوب"
    وگرنه:
        برگشت "تلاش بیشتر"
    پایان
پایان

تابع ریشه:
    سرچاپ رده(۹۵)
    سرچاپ رده(۷۲)
    سرچاپ رده(۴۰)
پایان
خروجیعالی خوب تلاش بیشتر

نمره‌ی ۹۵ از ۷۰ هم بیشتر است، اما برنامه فقط عالی را چاپ می‌کند: وقتی یک شاخه اجرا شد، بقیه کنار گذاشته می‌شوند.

شرط کوتاه و ترکیب شرط‌ها

شرط کوتاه را می‌شود در یک خط نوشت و پایان را در انتهای همان خط گذاشت. برای ترکیب شرط‌ها از و و یا کمک بگیرید.

cond-inline.salam
تابع ریشه:
    عدد := ۷
    اگر عدد % ۲ == ۰: سرچاپ "زوج" وگرنه: سرچاپ "فرد" پایان
    اگر عدد > ۰ و عدد < ۱۰:
        سرچاپ "عدد تک‌رقمی مثبت است"
    پایان
پایان
خروجیفرد عدد تک‌رقمی مثبت است

واژه‌های مقایسه

هر عملگر مقایسه یک واژه‌ی هم‌معنا هم دارد: برابر برای ==، نابرابر برای !=، کوچکتر و بزرگتر برای < و >، و کوچکتربرابر و بزرگتربرابر برای <= و >=. دو واژه‌ی آخر را با فاصله هم می‌شود نوشت: کوچکتر برابر. هر کدام را که خواناتر است به کار ببرید؛ معنایشان دقیقا یکی است. این مثال شکل کوتاه وگرنه اگر را هم نشان می‌دهد: وگرنه که شرط مستقیم پس از آن می‌آید.

cond-words.salam
تابع بها بلیت(سن: صحیح): صحیح:
    اگر سن کوچکتر ۴:
        برگشت ۰
    وگرنه سن کوچکتربرابر ۱۲:
        برگشت ۴۰
    وگرنه سن بزرگتربرابر ۶۵:
        برگشت ۵۰
    وگرنه:
        برگشت ۹۰
    پایان
پایان

تابع ریشه:
    سرچاپ بها بلیت(۲)، بها بلیت(۹)، بها بلیت(۳۰)، بها بلیت(۷۰)
    صندلی‌ها := ۱۲
    فروخته := ۱۲
    اگر فروخته برابر صندلی‌ها: سرچاپ "همه‌ی بلیت‌ها فروخته شد" پایان
    اگر فروخته نابرابر صندلی‌ها: سرچاپ "هنوز جا هست" پایان
پایان
خروجی0 40 90 50 همه‌ی بلیت‌ها فروخته شد

و، یا و وارونه

و و یا همین که پاسخ روشن شد می‌ایستند. اگر طرف چپ و نادرست باشد، طرف راست اصلا حساب نمی‌شود؛ در یا هم وقتی طرف چپ درست باشد همین‌طور است. پس طرف چپ نگهبان طرف راست است: پیش از تقسیم بسنجید که تعداد صفر نباشد، و پیش از خواندن آرایه بسنجید که شماره در محدوده باشد.

cond-short.salam
تابع میانگین(جمع: صحیح، تعداد: صحیح): صحیح:
    اگر تعداد != ۰ و جمع / تعداد > ۰:
        برگشت جمع / تعداد
    پایان
    برگشت ۰
پایان

تابع ریشه:
    سرچاپ میانگین(۲۷۰، ۳)، میانگین(۰، ۰)
    نمره‌ها := [۱۲، ۱۸، ۷]
    ای := ۵
    اگر ای < طول(نمره‌ها) و نمره‌ها[ای] > ۱۰:
        سرچاپ "نمره‌ی بالا"
    وگرنه:
        سرچاپ "نمره‌ای در این جایگاه نیست:"، ای
    پایان
    واردشده := درست
    مسدود := نادرست
    اگر واردشده و وارونه مسدود:
        سرچاپ "خوش برگشتید"
    پایان
    موجودی := ۳
    اگر وارونه (موجودی > ۵):
        سرچاپ "وقت سفارش دوباره است"
    پایان
پایان
خروجی90 0 نمره‌ای در این جایگاه نیست: 5 خوش برگشتید وقت سفارش دوباره است

وارونه از مقایسه محکم‌تر می‌چسبد. وارونه موجودی > ۵ یعنی (وارونه موجودی) > ۵ و خطاست، چون موجودی منطقی نیست. بنویسید وارونه (موجودی > ۵) یا ساده‌تر موجودی <= ۵. سلام && و || و ! ندارد و مترجم واژه‌ای را که باید به‌جایشان بنویسید نام می‌برد.

انتخاب یک مقدار

متغیری که درون یک شاخه تعریف شود، با پایان همان شاخه از بین می‌رود. اگر هر شاخه قرار است مقداری را تعیین کند، متغیر را پیش از اگر با ناپایا تعریف کنید و در شاخه‌ها مقدار بدهید. برای انتخاب میان فقط دو مقدار، عملگر سه‌تایی شرط ? الف : ب کوتاه‌تر است و دو طرفش باید یک نوع داشته باشند.

cond-scope.salam
تابع ریشه:
    وزن := ۳
    پیشتاز := درست
    ناپایا هزینه := ۰
    اگر وزن <= ۱:
        هزینه = ۳۰
    وگرنه وزن <= ۵:
        هزینه = ۵۵
    وگرنه:
        هزینه = ۹۰
    پایان
    اگر پیشتاز:
        هزینه += ۲۵
    پایان
    سرچاپ "هزینه‌ی ارسال:"، هزینه
    برچسب := وزن > ۲ ? "سنگین" : "سبک"
    سرچاپ برچسب
پایان
خروجیهزینه‌ی ارسال: 80 سنگین

برگشت زودهنگام

اگرهای تودرتوی زیاد سخت خوانده می‌شوند. درون یک تابع، هر مشکل را جداگانه بسنجید و همین که یکی پیدا شد برگشت کنید. آنچه در پایین تابع می‌ماند حالت عادی است، بی هیچ تودرتویی.

cond-guard.salam
تابع بررسی سفارش(تعداد: صحیح، موجودی: صحیح، پرداخت‌شده: منطقی): رشته:
    اگر تعداد <= ۰:
        برگشت "تعداد باید دست‌کم ۱ باشد"
    پایان
    اگر تعداد > موجودی:
        برگشت "تنها " + موجودی + " عدد در انبار مانده است"
    پایان
    اگر وارونه پرداخت‌شده:
        برگشت "در انتظار پرداخت"
    پایان
    برگشت "سفارش پذیرفته شد"
پایان

تابع ریشه:
    سرچاپ بررسی سفارش(۰، ۱۰، درست)
    سرچاپ بررسی سفارش(۱۲، ۱۰، درست)
    سرچاپ بررسی سفارش(۲، ۱۰، نادرست)
    سرچاپ بررسی سفارش(۲، ۱۰، درست)
پایان
خروجیتعداد باید دست‌کم ۱ باشد تنها 10 عدد در انبار مانده است در انتظار پرداخت سفارش پذیرفته شد

مقایسه‌ی عددهای اعشاری

بیشتر کسرهای دهدهی را نمی‌شود در دودویی دقیق نگه داشت، پس در حساب کمی خطای گرد کردن پیدا می‌شود. ۰.۱ + ۰.۲ می‌شود 0.30000000000000004 و مقایسه‌اش با == و ۰.۳ نادرست درمی‌آید. عددهای اعشاری را با این پرسش مقایسه کنید که آیا فاصله‌شان به اندازه‌ی کافی کوچک است. برای پول، مبلغ را به واحد درست (ریال یا سنت) و با عدد صحیح نگه دارید یا از بسته‌ی اعشاری استفاده کنید.

cond-float.salam
واردسازی ریاضی

تابع ریشه:
    پرداختی := ۰.۱ + ۰.۲
    بها := ۰.۳
    سرچاپ پرداختی
    اگر پرداختی == بها:
        سرچاپ "برابر"
    وگرنه:
        سرچاپ "نابرابر"
    پایان
    اگر ریاضی.قدرمطلق(پرداختی - بها) < ۰.۰۰۰۰۰۱:
        سرچاپ "به اندازه‌ی کافی نزدیک"
    پایان
پایان
خروجی0.30000000000000004 نابرابر به اندازه‌ی کافی نزدیک

قواعد شرط

  • شرط باید منطقی باشد؛ اگر عدد: خطاست و باید بنویسید اگر عدد != ۰:.
  • اگر ک = ۳: خطاست و مترجم می‌گوید به‌جایش == (یا برابر) بنویسید.
  • اگر ک == ۱ یا ۲: هم خطاست، چون ۲ منطقی نیست. بنویسید ک == ۱ یا ک == ۲.
  • شرطی که همیشه درست یا همیشه نادرست است، مثل اگر ۲ > ۱:، پذیرفته نمی‌شود، چون یکی از شاخه‌ها هرگز اجرا نمی‌شود.
  • هیچ شاخه‌ای نباید خالی باشد. به‌جای شاخه‌ی خالی، شرط را با وارونه برعکس کنید.
  • متغیری که درون یک شاخه تعریف شده، پس از پایان آن شاخه در دسترس نیست.

وقتی یک مقدار با حالت‌های فراوانی سنجیده می‌شود، زنجیره‌ی بلند وگرنه اگر خسته‌کننده می‌شود. درس‌های بعدی به حلقه‌ها و سپس به همخوان و ترابرد می‌پردازند که درست برای همین کار ساخته شده‌اند.