درک چرایی وجود حلقهها: چرا برای تکرار دستورات به حلقه نیاز داریم.
یادگیری شکل کامل for: سه بخش (مقدار اولیه، شرط، گام) و نحوه اجرای آنها.
فهم جریان اجرای for با trace table و یک فلوچارت گامبهگام.
آشنایی با نوع bool و مقادیر true/false (معادل ۱/۰).
نوشتن برنامههای ساده با for: چاپ ۱ تا n، چاپ ستاره، دریافت n عدد.
شناسایی و جلوگیری از دو تله شایع: حلقه بینهایت و خطای off-by-one.
چرا حلقه مینویسیم؟
فرض کنید میخواهیم اعداد ۱ تا ۱۰ را روی صفحه چاپ کنیم. بدون حلقه، باید ده خط cout بنویسیم:
main.cppcpp
این کار برای ۱۰ عدد شاید قابل قبول باشد، اما اگر بخواهیم اعداد ۱ تا ۱۰۰۰ یا ۱ تا ۱۰۰۰۰۰۰ را چاپ کنیم، چه میکنیم؟ آیا میخواهیم یک میلیون خط cout بنویسیم؟!
این جایی است که حلقه (Loop) وارد میشود. حلقه به ما اجازه میدهد یک بلاک از کد را با یک شرط مشخص چندینبار اجرا کنیم، بدون این که آن را چندینبار تایپ کنیم.
در C++ سه نوع حلقه اصلی داریم:
for — وقتی تعداد تکرارها را از قبل میدانیم (مثلاً «از ۱ تا n»).
while — وقتی شرط پایان مشخص است اما تعداد تکرارها معلوم نیست (مثلاً «تا وقتی کاربر صفر وارد کند»).
do-while — مثل while ولی بدنه حداقل یکبار اجرا میشود.
در این درس، فقط با for آشنا میشویم. حلقه while در درس بعدی پوشش داده میشود، اما در انتهای همین درس یک مقایسه کوتاه برای آشنایی اولیه ارائه میدهیم.
معرفی حلقه for — شکل کلی
شکل کلی حلقه for در C++ این است:
main.cppcpp
سه بخش داخل پرانتز با نقطهویرگول ; از هم جدا میشوند (نه کاما):
۱. بخش init (مقدار اولیه) — فقط یک بار در ابتدای حلقه اجرا میشود. معمولاً یک متغیر شمارنده تعریف و مقداردهی میکنیم، مثل int i = 1.
۲. بخش condition (شرط) — قبل از هر تکرار بررسی میشود. اگر شرط true (درست) باشد، بدنه اجرا میشود. اگر false (غلط) باشد، حلقه تمام میشود و کنترل از حلقه خارج میشود.
۳. بخش step (گام) — بعد از هر تکرار اجرا میشود. معمولاً شمارنده را زیاد یا کم میکنیم، مثل i++ یا i = i + 1.
به این ترتیب، ترتیب اجرا به این شکل است: init → بررسی condition → بدنه → step → بررسی condition → بدنه → step → ... تا وقتی condition اولین بار false شود.
مثال ۱: چاپ اعداد ۱ تا ۱۰
سادهترین استفاده از for، شمارش از یک عدد به عدد دیگر است. در این مثال، شمارنده i را از ۱ شروع میکنیم، در هر تکرار مقدار i را چاپ میکنیم، و در پایان هر تکرار i را یک واحد زیاد میکنیم. حلقه تا وقتی i <= 10 است ادامه مییابد.
نکته: متغیر i را میتوان داخل خود for تعریف کرد (مثل این مثال). در این حالت، i فقط در محدوده حلقه معتبر است و بعد از حلقه قابل دسترسی نیست.
اولین برنامه واقعی با حلقه forcpp
$خروجی برنامه
1 2 3 4 5 6 7 8 9 10
در حال باز کردن ویرایشگر…
مثال ۲: چاپ اعداد ۱ تا n (با ورودی کاربر)
در نسخه اصلی جزوه، یک مثال بود که n را از کاربر میگرفت و اعداد ۱ تا n را چاپ میکرد. این یکی از کاربردیترین الگوها در برنامهنویسی است: «یک کار را به تعداد دفعاتی که کاربر میگوید تکرار کن».
اگر n را ۰ یا منفی وارد کنیم، شرط i <= n از ابتدا false است، پس بدنه هرگز اجرا نمیشود و هیچ چیزی چاپ نمیشود. این رفتار مطلوب است و نشاندهندهی طراحی خوب حلقه است.
دریافت n از کاربر و چاپ اعداد ۱ تا ncpp
$خروجی برنامه
ورودی: 5
خروجی:
1
2
3
4
5
در حال باز کردن ویرایشگر…
فلوچارت: گردش کار حلقه for
flow.svg
نوع bool — true و false
در صفحه ۱۹ جزوه، در کنار for، نوع دادهای به نام bool معرفی شده بود. در ادامه آن را توضیح میدهیم.
نوع bool (به افتخار جورج بول، ریاضیدان انگلیسی) فقط دو مقدار میتواند بگیرد:
true (درست) — معادل عدد ۱
false (غلط) — معادل عدد ۰
شکل استفاده:
main.cppcpp
نکته جالب: اگر یک bool را با cout چاپ کنید، 1 یا 0 چاپ میشود (نه کلمه «true»):
main.cppcpp
چرا bool مهم است؟ چون شرطهای if و حلقههای for/while در نهایت یک مقدار bool تولید میکنند. مثلاً وقتی مینویسیم i <= n، نتیجه این مقایسه یک bool است (true یا false) و حلقه for بر اساس این مقدار تصمیم میگیرد ادامه دهد یا خیر.
میتوان bool را در یک متغیر ذخیره کرد و بعد استفاده کرد:
main.cppcpp
مثال ۳: چاپ n ستاره
یک الگوی کلاسیک: گرفتن n و چاپ n ستاره پشت سر هم. این مثال نشان میدهد که بدنه حلقه لزوماً نباید از i استفاده کند، میتوانیم فقط یک ثابت را چاپ کنیم و حلقه برای ما تعداد دفعات تکرار را مدیریت کند..
خروجی برای n = 5: *****
برنامهای که n ستاره در یک خط چاپ میکندcpp
$خروجی برنامه
ورودی: 5
خروجی: *****
ورودی: 10
خروجی: **********
در حال باز کردن ویرایشگر…
مثال ۴: دریافت n عدد و چاپ آنها
این یک الگوی بسیار مهم است: حلقه for را برای خواندن چندین ورودی پشت سر هم استفاده میکنیم. در هر تکرار، یک عدد را در cin >> a میخوانیم و آن را پردازش میکنیم.
نکته: متغیر a را بیرون حلقه تعریف میکنیم تا در هر تکرار دوباره ساخته نشود، فقط مقدارش بازنویسی شود.
میتوانیم به جای چاپ، مقدارها را جمع بزنیم، میانگین بگیریم یا max را پیدا کنیم. در درس بعدی، این الگو را با جزئیات بیشتری میبینیم.
برنامهای که n عدد را از کاربر میگیرد و سپس چاپ میکندcpp
یکی از مهارتهای مهم برنامهنویسی، ردیابی دستی اجرای کد است. برنامه for (int i = 1; i <= 3; i++) cout << i; را گامبهگام ردیابی میکنیم:
گام
i (قبل از بدنه)
شرط i <= 3
بدنه (چاپ)
گام i++
۱
۱
true
چاپ ۱
i = ۲
۲
۲
true
چاپ ۲
i = ۳
۳
۳
true
چاپ ۳
i = ۴
۴
۴
false
(بدنه اجرا نمیشود)
(پایان حلقه)
خروجی نهایی: 123
وقتی حلقه تمام میشود، مقدار نهایی i برابر اولین مقداری است که شرط false شده (در مثال بالا، i = 4). این یک نکته آزمایشی است که در مصاحبهها و امتحانها زیاد میپرسند.
اگر i را داخل for تعریف کرده باشیم (مثل این مثال)، بعد از حلقه قابل دسترسی نیست. اگر بیرون for تعریف شده باشد، مقدار نهایی قابل دسترسی است و میتوان از آن استفاده کرد.
عملگرهای افزایشی: i++ و ++i
در اکثر حلقههای for از i++ استفاده میکنیم. این یک عملگر افزایشی postfix است که یعنی «اول مقدار i را برگردان، بعد یک واحد به آن اضافه کن».
نسخه دیگر، prefix است: ++i که یعنی «اول یک واحد اضافه کن، بعد مقدار جدید را برگردان».
تفاوت این دو فقط وقتی ظاهر میشود که در یک عبارت بزرگتر استفاده شوند:
main.cppcpp
اما در بخش step حلقه for فرقی نمیکند که از i++ یا ++i استفاده کنید، هر دو یکی عمل میکنند، چون مقدار برگشتی در آنجا استفاده نمیشود. در کدهای قدیمی، معمولاً i++ رایجتر بود، اما در C++ مدرن، ++i بهخاطر احتمالی کمتر از کپیگیری، توصیه میشود (برای انواع پیچیدهتر مثل iteratorها).
برای اعداد int ساده، هر دو یکسان هستند؛ از هر کدام که راحتترید استفاده کنید.
تله شماره ۱: حلقه بینهایت
اگر بخش step را فراموش کنید یا طوری بنویسید که شرط هیچوقت false نشود، حلقه بینهایت (Infinite Loop) ایجاد میکنید، حلقهای که تا ابد اجرا میشود.
مثال خطا:
main.cppcpp
در این مثال، i هیچوقت افزایش نمییابد، پس شرط i <= 10 همیشه true میماند.
نشانههای حلقه بینهایت: برنامه از اجرا بیرون نمیآید، خروجی به یک حالت ثابت یا تکراری میرسد، و فن کامپیوتر ممکن است با سرعت بیشتری کار کند. در محیطهای IDE، میتوانید با Ctrl+C یا دکمه Stop اجرای برنامه را قطع کنید.
راه جلوگیری: همیشه قبل از اجرا، از خود بپرسید «چه چیزی در هر تکرار تغییر میکند تا شرط روزی false شود؟» اگر جواب «هیچ» بود، کد را دوباره بررسی کنید.
تله شماره ۲: خطای off-by-one
خطای off-by-one یکی از شایعترین خطاهای برنامهنویسی است. این خطا وقتی رخ میدهد که حلقه یک بار بیشتر یا یک بار کمتر از آنچه میخواهید اجرا شود.
مثال: میخواهیم اعداد ۱ تا ۱۰ را چاپ کنیم:
main.cppcpp
تفاوت کلیدی: i <= n شامل n میشود، i < n شامل n نمیشود.
قاعده طلایی: هر بار که حلقه for مینویسید، در ذهن یا روی کاغذ، حداقل دو تکرار اول و آخر را شبیهسازی کنید تا مطمئن شوید مرزها درست هستند.
پیشنمایش: for در برابر while
هر دو حلقه for و while میتوانند یک کار را تکرار کنند — تفاوتشان در شکل نمایش است:
for همه چیز (مقدار اولیه، شرط، گام) را در یک خط دارد — خواندنش برای شمارش ساده راحتتر است.
while فقط شرط را دارد؛ مقدار اولیه و گام را باید در جای دیگری بنویسید — برای زمانی که تعداد تکرارها معلوم نیست مناسبتر است.
هر کاری که با for بتوانید انجام دهید، با while هم میتوانید و برعکس. انتخاب بین این دو بیشتر سلیقهای و وابسته به زمینه است.
نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاحشده و استاندارد
کد صحیحcpp
for فقط برای شمارش ساده نیست
در نسخه اصلی جزوه یک نکته با رنگ قرمز نوشته شده بود: «for فقط برای تکرار نیست»، منظور این است که بدنه حلقه میتواند هر کاری کند، نه فقط چاپ i.
چند کاربرد نشاندهنده این موضوع:
۱. انباشت (Accumulation): جمع، ضرب، یا هر ترکیب تجمعی از اعداد. مثلاً مجموع ۱ تا n، یا حاصلضرب ۱ تا n (فاکتوریل).
۲. شمارش (Counting): شمارش تعداد اعداد زوج، فرد، اول یا هر ویژگی دیگر در یک بازه.
۳. یافتن max/min: با گرفتن n ورودی و ردیابی بزرگترین/کوچکترین.
۴. چاپ الگوها: چاپ اشکال گرافیکی با ستاره، مثلث، مربع، لوزی و...
در تمرینهای این درس، فاکتوریل و شمارش زوج/فرد را خودتان مینویسید تا با این کاربردها آشنا شوید. در درس بعدی، مجموع، max و میانگین را عمیقتر پوشش میدهیم.
برنامهای بنویسید که عدد n را بگیرد و حاصلضرب اعداد ۱ تا n (یعنی فاکتوریل: n!) را چاپ کند. مثلاً برای ۵، خروجی ۱۲۰ است.
نمایش راهنما
یک متغیر prod را با مقدار اولیه ۱ بسازید و در بدنه for بنویسید: prod = prod * i; یا prod *= i;
02
تمرین•حل کامل دارد
برنامهای بنویسید که عدد n را بگیرد و تعداد اعداد زوج و فرد بین ۱ تا n را جداگانه چاپ کند. مثلاً برای n = 6: زوج = ۳ (۲، ۴، ۶)، فرد = ۳ (۱، ۳، ۵).
نمایش راهنما
دو شمارنده even و odd را با مقدار اولیه ۰ بسازید و در بدنه for با i % 2 == 0 بررسی کنید i زوج است یا فرد، و شمارنده مربوطه را یک واحد زیاد کنید.
03
تمرین•حل کامل دارد
برنامهای بنویسید که عدد n را بگیرد و یک مربع n×n از ستاره چاپ کند. مثلاً برای n = 3:
***
***
***
نمایش راهنما
از دو حلقه for تودرتو استفاده کنید: حلقه بیرونی برای سطرها (i از ۱ تا n)، حلقه درونی برای ستونها (j از ۱ تا n) که در هر تکرار یک ستاره چاپ میکند، و بعد از هر سطر یک endl چاپ کنید.
04
تمرین•حل کامل دارد
برنامهای بنویسید که عدد n را بگیرد و حاصلجمع اعداد زوج بین ۱ تا n را چاپ کند. مثلاً برای n = 10: ۲+۴+۶+۸+۱۰ = ۳۰.
نمایش راهنما
یک متغیر sum = 0 بسازید و در بدنه for با if (i % 2 == 0) فقط اعداد زوج را به sum اضافه کنید.
05
تمرین•حل کامل دارد
برنامهای بنویسید که عدد n را بگیرد و مضارب ۳ بین ۱ تا n را چاپ کند. مثلاً برای n = 15: ۳ ۶ ۹ ۱۲ ۱۵.
نمایش راهنما
در بدنه for با if (i % 3 == 0) بررسی کنید i مضرب ۳ است یا نه؛ اگر بله، چاپش کنید. یا بهجای آن، شمارنده را ۳تا۳تا زیاد کنید: for (int i = 3; i <= n; i += 3).
// نکات-کلیدی۶
01حلقهها به ما اجازه میدهند یک بلاک کد را چندین بار بدون تکرار تایپ اجرا کنیم، این برای صدها یا هزاران تکرار حیاتی است.
02حلقه for سه بخش دارد: مقدار اولیه (init)، شرط (condition)، گام (step)؛ که با نقطهویرگول جدا میشوند.
03ترتیب اجرای for: init یکبار → سپس چرخه «بررسی شرط → بدنه → گام» تا وقتی شرط false شود.
04نوع bool فقط دو مقدار true (۱) و false (۰) دارد و در پایهی تمام شرطها و تصمیمات در برنامهنویسی قرار دارد.
05اگر بخش step را فراموش کنید، حلقه بینهایت ایجاد میشود، همیشه قبل از اجرا بپرسید چه چیزی شرط را روزی false میکند.
06تفاوت i <= n و i < n یکی از شایعترین منابع خطای off-by-one است؛ برای مرزها همیشه دو بار بررسی کنید.
./project-basicsپروژهٔ پایانی این دسته
دستیار نمرهٔ کلاس
ورودی/خروجی، شرطها و switch در یک برنامهٔ واقعی
آخرین درس این دسته را تمام کردی — وقت آن است که همهچیز را یکجا به محک بزنی. برنامهای بنویس که نمرهٔ سه درس یک دانشآموز را بخواند، میانگین را با دو رقم اعشار چاپ کند، وضعیت قبولی/مردودی را تعیین کند و با switch حرف نمره را نشان دهد. اگر هر نمره خارج از بازهٔ صفر تا بیست بود، برنامه پیام خطا چاپ کند و با return 1 تمام شود.
⏱ ۴۵ تا ۶۰ دقیقه۶ نیازمندی — هر کدام به یک درس لینک است
نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید
cout <<1<< endl;cout <<2<< endl;cout <<3<< endl;// ... تا ۱۰
for(init; condition; step){// بدنه حلقه}
1#include<iostream>2usingnamespace std;34intmain(){5for(int i =1; i <=10; i++){6 cout << i <<" ";7}8 cout << endl;9return0;10}
1#include<iostream>2usingnamespace std;34intmain(){5int n =0;6 cin >> n;7for(int i =1; i <= n; i++){8 cout << i << endl;9}10return0;11}
flow.svg100%
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
شروع/پایانپردازشتصمیمورودی/خروجی
bool b;b =true;// یا b = 1;b =false;// یا b = 0;
bool b =true;cout << b;// چاپ میکند: 1
bool isEven =(n %2==0);if(isEven) cout <<"even";
1#include<iostream>2usingnamespace std;34intmain(){5int n =0;6 cin >> n;7for(int i =1; i <= n; i++){8 cout <<"*";9}10 cout << endl;11return0;12}
1#include<iostream>2usingnamespace std;34intmain(){5int n =0, a =0;6 cin >> n;7for(int i =1; i <= n; i++){8 cin >> a;9 cout <<"Read: "<< a << endl;10}11return0;12}
int i =5;int a = i++;// a = 5، i = 6 (اول مقدار قبلی برمیگردد)int b =++i;// b = 7، i = 7 (اول اضافه میشود بعد مقدار جدید)
for(int i =1; i <=10;){// step فراموش شده! cout << i;}// خروجی: 1111111... تا ابد
// ✓ درست: ۱ تا ۱۰ چاپ میشود (۱۰ تکرار)for(int i =1; i <=10; i++) cout << i <<" ";// خروجی: 1 2 3 4 5 6 7 8 9 10// ✗ خطا: ۱ تا ۹ چاپ میشود (۹ تکرار)for(int i =1; i <10; i++) cout << i <<" ";// خروجی: 1 2 3 4 5 6 7 8 9// ✗ خطا: ۲ تا ۱۰ چاپ میشود (۹ تکرار)for(int i =2; i <=10; i++) cout << i <<" ";// خروجی: 2 3 4 5 6 7 8 9 10
1// نسخه for — مناسب وقتی تعداد تکرارها معلوم است2#include<iostream>3usingnamespace std;45intmain(){6int n =0;7 cin >> n;8for(int i =1; i <= n; i++){9 cout << i <<" ";10}11return0;12}
1// نسخه while — همان کار را انجام میدهد ولی init و step جدا هستند2#include<iostream>3usingnamespace std;45intmain(){6int n =0;7 cin >> n;8int i =1;// init بیرون حلقه9while(i <= n){// فقط شرط در پرانتز10 cout << i <<" ";11 i++;// step داخل بدنه12}13return0;14}