محاسبه مجموع اعداد ۱ تا 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.
سه راه برای رفع این مشکل:
Cast صریح: float(n) یا (float)n یا static_cast<float>(n)
ضرب در 1.0: sum * 1.0 / n
تعریف اعشاری: اگر از ابتدا 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 است: در این حالت بدنه هرگز اجرا نمیشود؛ که میتواند مطلوب یا یک باگ باشد.
قبل از اجرای برنامه، همیشه خروجی را ذهنی پیشبینی کنید، این عادت از سرعت یافتن باگها را بالا میبرد.
نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید
1#include<iostream>2usingnamespace std;34intmain(){5int n;6int sum =0;// مقداردهی اولیه الزامی است7 cin >> n;8for(int i =1; i <= n; i++){9 sum = sum + i;// یا بهصورت خلاصه: sum += i;10}11 cout << sum;12return0;13}
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.
شروع/پایانپردازشتصمیمورودی/خروجی
1#include<iostream>2usingnamespace std;34intmain(){5int n, a, max;6 cin >> n;7 cin >> a;8 max = a;// اولین عدد بهعنوان مقدار اولیه9for(int i =2; i <= n; i++){10 cin >> a;11if(a > max){12 max = a;13}14}15 cout << max;16return0;17}
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.
شروع/پایانپردازشتصمیمورودی/خروجی
1int S =0;2for(i =3; i <10; i++)// خطا: متغیر i تعریف نشده3 S += i;4cout << i;// حتی اگر تعریف شود، مقدار نهایی i چاپ میشود
1#include<iostream>2usingnamespace std;34intmain(){5int S =0;6int i;// تعریف i قبل از for7for(i =3; i <10; i++){8 S += i;9}10 cout <<"S = "<< S <<", i = "<< i << endl;// i = 10 بعد از حلقه11return0;12}
1#include<iostream>2usingnamespace std;34intmain(){5for(int i =10; i >=1; i--){6 cout << i <<" ";7}8 cout << endl;9return0;10}
1#include<iostream>2usingnamespace std;34intmain(){5int n, a, sum =0;6 cin >> n;7for(int i =1; i <= n; i++){8 cin >> a;9 sum += a;10}11 cout << sum /float(n)<< endl;// یا (float)n یا double(n)12return0;13}
while(شرط){// بدنه حلقه}
1#include<iostream>2usingnamespace std;34intmain(){5int a;6 cin >> a;7int k =0;// شمارنده ارقام8while(a >0){9 a = a /10;// حذف رقم آخر10 k++;// شمارش یک رقم11}12 cout << k << endl;13return0;14}
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.