برای روشن کردن ترمینال، کلیک کن یا هر کلیدی را بزن

پرش به محتوای اصلی
>_
درس ۱۱مقدماتی

مرور حلقه for و معرفی while

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

معمولی
حلقه‌ها و کنترل جریان•صفحه ۲۰•۱۴ دقیقه•۱٬۳۱۸ کلمهزمان مطالعه: ۰ دقیقه
فهرست این درس
// اهداف۵
  • محاسبه مجموع اعداد ۱ تا n با حلقه for و درک مفهوم Accumulator
  • یافتن بزرگترین (max) عدد بین n ورودی با الگوی «اولین عدد به‌عنوان مقدار اولیه»
  • آشنایی با حلقه نزولی و انتساب مرکب (Compound Assignment)
  • محاسبه میانگین با تبدیل نوع (Type Casting) به float
  • یادگیری ساختار while و نوشتن اولین برنامه برای شمارش ارقام یک عدد

چرا حلقه می‌نویسیم؟

برنامه‌های واقعی معمولاً یک کار را بار‌ها و بار‌ها تکرار می‌کنند؛ مثلاً جمع کردن ۱۰۰ عدد، چاپ اعداد ۱ تا ۱۰۰۰ یا پیمایش ارقام یک عدد. اگر بخواهیم برای هر تکرار یک خط جداگانه بنویسیم، کد ما به سرعت طولانی و غیرقابل مدیریت می‌شود.

در ⁦C++⁩ دو ساختار کلاسیک برای تکرار داریم:

  • حلقه for — وقتی تعداد تکرار‌ها از قبل مشخص است (مثلاً از ۱ تا n).
  • حلقه while — وقتی شرط پایان مشخص است اما تعداد تکرار‌ها معلوم نیست (مثلاً تا وقتی کاربر صفر وارد نکرده).

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

مثال ۱: محاسبه مجموع اعداد ۱ تا n

الگوی کلی این الگوریتم به این شکل است: یک متغیر انباشتگر (Accumulator) به نام sum با مقدار اولیه ۰ تعریف می‌کنیم و در هر گام حلقه، مقدار جدید را به آن اضافه می‌کنیم (sum += i).

برنامه‌ای که عدد n را گرفته و ۱+۲+…+n را چاپ می‌کندcpp
خروجی برنامه
ورودی: 5
خروجی: 15
در حال باز کردن ویرایشگر…

فلوچارت: الگوریتم جمع ۱ تا n

flow.svg

عملگر‌های انتساب مرکب (Compound Assignment)

به جای نوشتن sum = sum + i می‌توانیم بنویسیم sum += i. ⁦C++⁩ برای همه عملگر‌های رایج معادل خلاصه‌ای دارد:

  • += جمع
  • -= تفریق
  • *= ضرب
  • /= تقسیم
  • %= باقیمانده

این نوشتار هم خواناتر و هم کم‌خطاتر است؛ چون نام متغیر یک‌بار نوشته می‌شود و احتمال اشتباه تایپی کاهش می‌یابد.

تله مهم: متغیر انباشتگر بدون مقداردهی

در نسخه اصلی جزوه، خط int n, sum; بدون مقداردهی اولیه نوشته شده بود. در ⁦C++⁩، متغیر‌های محلی مقداردهی‌نشده مقدار زباله (Garbage Value) دارند و خواندن آن‌ها رفتار نامشخص (Undefined Behavior) است.

خروجی برنامه در این حالت غیرقابل پیش‌بینی می‌شود؛ ممکن است هر بار عدد متفاوتی چاپ کند. همیشه متغیر‌های انباشتگر را با = 0 مقداردهی کنید:

int sum = 0;

مثال ۲: یافتن بزرگترین عدد بین n عدد

یک الگوی بسیار مهم در برنامه‌نویسی: به جای مقداردهی max با عدد خیلی کوچک (مثل INT_MIN)، اولین عدد را خارج از حلقه می‌گیریم و آن را به‌عنوان مقدار اولیه max قرار می‌دهیم. این کار کد را تمیزتر و قابل‌حمل‌تر می‌کند.

الگوی «اولین عدد به‌عنوان مقدار اولیه max»cpp
خروجی برنامه
ورودی: 5  3 9 2 11 4
خروجی: 11
در حال باز کردن ویرایشگر…

فلوچارت: الگوریتم یافتن max

flow.svg

اشکال‌زدایی: تعریف متغیر حلقه

در ⁦C++⁩ هر متغیر باید قبل از استفاده اعلام (Declare) شود. در نسخه خطای جزوه، متغیر i بدون تعریف نوع داده استفاده شده بود که باعث خطای کامپایل می‌شود. راه‌حل: تعریف داخل پرانتز for یا قبل از آن.

نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاح‌شده و استاندارد
کد صحیحcpp

مثال ۳: حلقه نزولی (Decreasing Loop)

حلقه for فقط برای شمارش صعودی نیست. با تغییر شرط به i >= 1 و گام به i-- می‌توانیم نزولی هم بشماریم. این الگو برای چاپ الگوهای گرافیکی یا معکوس کردن دنباله‌ها مفید است.

حلقه‌ای که از ۱۰ تا ۱ به‌صورت نزولی می‌شماردcpp
خروجی برنامه
10 9 8 7 6 5 4 3 2 1
در حال باز کردن ویرایشگر…

مثال ۴: محاسبه میانگین با تبدیل نوع (Type Casting)

اگر sum و n هر دو int باشند، عبارت sum / n تقسیم صحیح انجام می‌دهد و قسمت اعشاری حذف می‌شود. برای گرفتن خروجی اعشاری، باید حداقل یکی از دو طرف را با float(...) یا (float) به نوع اعشاری تبدیل (Cast) کنیم.

استفاده از float(n) برای تقسیم اعشاری صحیحcpp
خروجی برنامه
ورودی: 3  10 20 25
خروجی: 18.3333
در حال باز کردن ویرایشگر…

تبدیل نوع (Type Casting): چرا و چگونه؟

وقتی دو عدد int را تقسیم می‌کنیم، ⁦C++⁩ قبل از تقسیم هر دو طرف را int می‌بیند و نتیجه را هم int می‌دهد. یعنی 5 / 2 برابر 2 می‌شود، نه 2.5.

سه راه برای رفع این مشکل:

  1. Cast صریح: float(n) یا (float)n یا static_cast<float>(n)
  2. ضرب در 1.0: sum * 1.0 / n
  3. تعریف اعشاری: اگر از ابتدا double sum = 0; تعریف کنیم، تقسیم اعشاری انجام می‌شود.

روش اول تمیزتر و صریح‌تر است.

معرفی ساختار while

حلقه while زمانی استفاده می‌شود که تعداد تکرار‌ها معلوم نیست و فقط یک شرط پایان داریم. شکل کلی آن:

main.cppcpp

مهم‌ترین تفاوت با for: در while عملگر شروع، شرط و گام همه در یک خط نیستند؛ بنابراین باید دست مدیریت گام را خودمان بگیریم. اگر گام را فراموش کنیم، حلقه بی‌نهایت (Infinite Loop) ایجاد می‌شود.

قاعده طلایی: قبل از نوشتن while، از خود بپرسید «چه چیزی در هر تکرار تغییر می‌کند تا شرط روزی false شود؟»

مثال ۵: شمارش ارقام یک عدد با while

ایده اصلی: هر بار که عدد را بر ۱۰ تقسیم صحیح می‌کنیم، یک رقم از انتها حذف می‌شود. تعداد دفعاتی که می‌توانیم این کار را تا رسیدن به صفر انجام دهیم، برابر است با تعداد ارقام.

مثال: ۴۵۷ → ۴۵ → ۴ → ۰ (۳ تقسیم = ۳ رقم).

تعداد ارقام عدد صحیح مثبت را با تقسیم مکرر بر ۱۰ می‌شماردcpp
خروجی برنامه
ورودی: 457
خروجی: 3
در حال باز کردن ویرایشگر…

فلوچارت: شمارش ارقام با while

flow.svg

تله‌های حلقه while

سه خطای رایج هنگام استفاده از while:

۱. فراموش کردن گام تغییر: اگر در مثال بالا a = a / 10; را ننویسیم، a همیشه مقدار اولیه باقی می‌ماند و حلقه تا بی‌نهایت اجرا می‌شود (یا تا زمانی که حافظه تمام شود).

۲. شرطی که هرگز false نمی‌شود: مثلاً while (n >= 0) وقتی n مثبت است و در بدنه کاهش نمی‌یابد.

۳. شرطی که از ابتدا false است: در این حالت بدنه هرگز اجرا نمی‌شود؛ که می‌تواند مطلوب یا یک باگ باشد.

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

مرور سریع مطالب

۱۵ بخش در این درس

تمرین‌ها

01
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد n را بگیرد و حاصل‌جمع مربعات اعداد ۱ تا n (یعنی ۱²+۲²+…+n²) را چاپ کند.

نمایش راهنما
در بدنه for بنویسید: sum += i * i;
02
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد مثبت n را بگیرد و تعداد ارقام زوج آن را با while بشمارد (مثلاً ۴۵۸۲ سه رقم زوج دارد: ۴ و ۸ و ۲).

نمایش راهنما
در هر تکرار، رقم آخر را با a % 10 بگیرید و بررسی کنید زوج است یا نه، سپس a /= 10 کنید.
03
تمرین•حل کامل دارد

برنامه‌ای بنویسید که n عدد را بگیرد و میانگین آن‌ها را به‌صورت اعشاری چاپ کند. حتماً از Type Casting استفاده کنید.

نمایش راهنما
sum را به‌صورت int نگه دارید اما در خط آخر بنویسید cout << (float)sum / n;
04
تمرین•حل کامل دارد

برنامه‌ای بنویسید که عدد n را بگیرد و اعداد زوج بین ۱ تا n را به ترتیب نزولی چاپ کند.

نمایش راهنما
از یک حلقه نزولی for با گام i -= 2 استفاده کنید یا در بدنه بررسی کنید i % 2 == 0.
// نکات-کلیدی۵
  • 01متغیر‌های انباشتگر (مثل sum, max, k) را همیشه قبل از حلقه مقداردهی اولیه کنید تا از Undefined Behavior جلوگیری شود.
  • 02در الگوریتم یافتن max، اولین عدد را خارج حلقه بخوانید و به‌عنوان مقدار اولیه max قرار دهید.
  • 03برای تقسیم اعشاری بین دو int، حداقل یک طرف را با float(n) یا (float)n به نوع اعشاری Cast کنید.
  • 04حلقه while برای زمانی است که تعداد تکرار‌ها معلوم نیست؛ اما باید گام تغییر شرط را خودتان مدیریت کنید.
  • 05هر بار که در while چیزی «کاهش یا تغییر» نمی‌کنید، خطر حلقه بی‌نهایت ایجاد می‌کنید.
گام بعدی پیشنهادی

تمرین‌های عملی حلقه while

از چاپ اعداد شرطی تا ماشین حساب تعاملی و میانگین‌گیری از اعداد خاص

۱۶ دقیقهمقدماتی۱۱ بخش

شروع درس

جستجوی سریع در درس‌ها

نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید