چاپ اعداد بین a و b که بر ۳ بخشپذیر و بر ۵ غیرقابل بخشپذیرند
ساخت ماشین حساب ساده تعاملی با حلقه while و شرط خروج
تشخیص و اصلاح باگ رایج (a/100)%10 به جای a%10 برای رقم یکان
مدیریت خطای تقسیم بر صفر در محاسبه میانگین
تمرین ترکیب عملگرهای منطقی (&&، ||، !) در شروط while
بهانهای برای تمرین while
حلقه while را زمانی به کار میگیریم که نمیدانیم دقیقاً چند بار قرار است تکرار شود. این درس شامل سه تمرین عملی است که هر کدام باگ خاص خود را در نسخه اصلی جزوه داشت و ما آنها را اصلاح میکنیم:
۱. چاپ اعداد بین a و b که بر ۳ بخشپذیر و بر ۵ بخشپذیر نیستند (با for).
۲. ماشین حساب سادهای که تا وقتی کاربر صفر وارد نکرده، جمع اعداد را نشان میدهد (با while).
۳. میانگین اعداد سهرقمی که رقم یکانشان ۷ است (با اصلاح یک باگ منطقی مهم).
هر سه تمرین مهارت پایهای مهم را آموزش میدهند: ترکیب شروط، مدیریت ورودی تعاملی و پردازش ارقام عدد.
تمرین ۱: چاپ اعداد خاص بین a و b
هدف: با یک حلقه for از a+1 تا b-1 پیمایش میکنیم و برای هر عدد، دو شرط را با عملگر && (And منطقی) ترکیب میکنیم. اگر هر دو شرط برقرار بود، عدد را چاپ میکنیم.
مثال: a = 5, b = 20 → اعداد ۶, ۹, ۱۲, ۱۸ (۱۵ حذف میشود چون بر ۵ بخشپذیر است).
اعدادی که بر ۳ بخشپذیرند اما بر ۵ نیستندcpp
$خروجی برنامه
ورودی: 5 20
خروجی: 6 9 12 18
در حال باز کردن ویرایشگر…
فلوچارت: چاپ اعداد شرطی
flow.svg
مثال اجرا
بررسی دستی خروجی برای a = 5, b = 20:
i
i%3==0
i%5!=0
چاپ؟
6
بله
بله
✓
9
بله
بله
✓
12
بله
بله
✓
15
بله
خیر
✗
18
بله
بله
✓
پس خروجی نهایی: 6 9 12 18.
شرط i < b (نه i <= b) باعث میشود عدد b خودش در نظر گرفته نشود؛ این رفتار به تعریف مسئله بستگی دارد.
تمرین ۲: ماشین حساب ساده تعاملی
این برنامه دو عدد و یک عملگر را میگیرد و تا وقتی دستکم یکی از a، b یا ch غیرصفر است، عملیات را انجام میدهد — چون شرط حلقه با || نوشته شده، خروج فقط وقتی است که هر سه صفر باشند (مثل ورودی 0 0 0). مهمترین نکته: داخل حلقه باید دوباره ورودی بخوانیم؛ در غیر این صورت حلقه یا بینهایت میشود یا فقط یک بار اجرا میشود.
در نسخه اصلی جزوه از getch() استفاده شده بود که در استاندارد C++ وجود ندارد. ما از cin >> ch استفاده میکنیم.
تا وقتی ورودیها صفر نشدهاند، عملیات a و b را با علامت ch انجام بدهcpp
$خروجی برنامه
ورودی کاربر:
3 5 +
result = 8
10 2 /
result = 5
0 0 0
(حلقه تمام میشود؛ برنامه بدون چاپ اضافی خارج میشود)
در حال باز کردن ویرایشگر…
اصلاح: عملگر or به جای ||
در C++ استاندارد، عملگر منطقی «یا» با || نوشته میشود. کلمه or هم یک توکن جایگزین استاندارد است (از C++98) و هر کامپایلرِ منطبق بر استاندارد موظف است آن را بپذیرد — پس or از نظر استاندارد قابل حمل است. خطر واقعی جای دیگری است: کامپایلرهای پیشاستاندارد مثل Turbo C++ (همان محیط جزوه) این کلمات را اصلاً نمیشناسند. برای سازگاری با محیطهای امتحانی و خوانایی، همیشه || و && بنویسید. ضمناً getch() در <conio.h> غیراستاندارد است.
نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاحشده و استاندارد
کد صحیحcpp
getch() یا cin؟
تابع getch() (از <conio.h>) در کامپایلرهای قدیمی مثل Turbo C++ رایج بود تا بدون فشردن Enter یک کاراکتر خوانده شود. اما این هدر استاندارد C++ نیست و در کامپایلرهای مدرن مثل GCC یا Clang موجود نیست.
به جای آن میتوانید:
از cin >> ch; استفاده کنید (نیازمند Enter).
از cin.get(ch); برای خواندن حتی فضای خالی.
در سیستمعاملهای POSIX از توابع termios یا کتابخانه ncurses استفاده کنید.
برای کدهای آموزشی و قابلحمل، همان cin >> ch بهترین گزینه است.
تمرین ۳: میانگین اعداد سهرقمی با یکان ۷
هدف: از بین n عدد ورودی، آنهایی که سه رقم دارند و رقم یکانشان ۷ است را پیدا کنیم، مجموع و تعدادشان را نگه داریم و در نهایت میانگین را چاپ کنیم.
باگ مهم نسخه اصلی جزوه: شرط (a/100)%10 == 7 در واقع رقم صدگان را بررسی میکند، نه یکان! برای رقم یکان باید از a % 10 == 7 استفاده کنیم. این یک اشتباه منطقی است که حتی کامپایل میشود اما خروجی اشتباه میدهد.
تصحیح شده: بررسی رقم یکان با a % 10cpp
$خروجی برنامه
ورودی: 5 107 257 9997 23 117
خروجی: 160.333
(میانگین 107 و 257 و 117)
در حال باز کردن ویرایشگر…
اصلاح باگ منطقی: رقم یکان یا رقم صدگان؟
این یکی از خطرناکترین انواع باگهاست: کد کامپایل میشود، اجرا میشود، اما خروجی اشتباه میدهد. برای استخراج ارقام یک عدد سهرقمی abc (که a رقم صدگان، b رقم دهگان و c رقم یکگان است):
در نسخه اصلی جزوه، باگ دوگانه وجود داشت: هم شرط اشتباه بود و هم متغیر K با حرف بزرگ نوشته شده بود در حالی که با حرف کوچک k تعریف شده بود (Case Sensitivity).
نسخه اشتباه جزوه
کد دارای باگcpp
نسخه اصلاحشده و استاندارد
کد صحیحcpp
خطای تقسیم بر صفر (Division by Zero)
اگر هیچ عددی شرایط را نداشته باشد (یعنی k = 0 بماند)، عبارت Sum / k باعث خطای زمان اجرا (Runtime Error) یا در بهترین حالت، خروجی nan/inf میشود.
راهحل طلایی: همیشه قبل از تقسیم، شمارنده را بررسی کنید:
main.cppcpp
این الگو را برای تمام محاسبههای میانگین به کار ببرید.
چه وقت for و چه وقت while؟
قاعده ساده:
for: وقتی میدانید دقیقاً چند بار باید تکرار شود (۱ تا n، پیمایش آرایه، شمارش از a تا b).
while: وقتی شرط پایان مشخص است اما تعداد تکرارها نامعلوم (تا وقتی کاربر صفر وارد نکرده، تا وقتی فایل تمام نشده، تا وقتی عدد به ۱ نرسیده).
do-while: وقتی بدنه باید حداقل یک بار اجرا شود.
هر سه را میتوان به دیگری تبدیل کرد، اما انتخاب درست باعث خوانایی بیشتر کد میشود.
چاپ اعداد بین a و b که بر ۳ بخشپذیر و بر ۵ غیرقابل بخشپذیرند
ساخت ماشین حساب ساده تعاملی با حلقه while و شرط خروج
تشخیص و اصلاح باگ رایج (a/100)%10 به جای a%10 برای رقم یکان
نکات کلیدی:
برای ترکیب چند شرط در if، از && (And)، || (Or) و ! (Not) استفاده کنید؛ کلمات and/or توکنهای جایگزین استاندارد C++ هستند، اما چون کامپایلرهای قدیمی (مثل Turbo C++) آنها را نمیشناسند، همیشه نمادها را بنویسید.
رقم یکان عدد با n % 10 استخراج میشود، نه با (n / 100) % 10 که رقم صدگان را میدهد.
C++ به بزرگی و کوچکی حروف حساس است؛ `K` و `k` دو متغیر متفاوت هستند.
در حلقه while تعاملی، حتماً داخل بدنه دوباره ورودی بخوانید تا حلقه بینهایت نشود.
برنامهای بنویسید که a و b را بگیرد و اعداد بین آنها که بر ۷ بخشپذیرند اما بر ۲ نیستند (یعنی فرد و مضرب ۷) را چاپ کند.
نمایش راهنما
شرط if را بنویسید: if (i % 7 == 0 && i % 2 != 0)
02
تمرین•حل کامل دارد
برنامهای بنویسید که تعدادی عدد از ورودی بگیرد (تا وقتی صفر وارد شود) و تعداد اعداد مثبت، تعداد اعداد منفی و مجموع کل را چاپ کند.
نمایش راهنما
از while با شرط (a != 0) استفاده کنید. سه شمارنده جداگانه برای مثبت، منفی و sum داشته باشید.
03
تمرین•حل کامل دارد
برنامهای بنویسید که n عدد را بگیرد و میانگین اعداد دو رقمی که رقم دهگانشان بزرگتر از رقم یکانشان است را چاپ کند. اگر چنین عددی نبود، پیام مناسبی چاپ کنید.
نمایش راهنما
برای رقم دهگان بنویسید (a / 10) % 10 و برای یکان a % 10. سپس مقایسه کنید. تقسیم بر صفر را هم مدیریت کنید.
04
تمرین•حل کامل دارد
ماشین حساب پیشرفتهای بنویسید که تا وقتی کاربر علامت q وارد نکرده، عملیات +، -، *، / را روی دو عدد انجام دهد. خطای تقسیم بر صفر را هم مدیریت کنید.
نمایش راهنما
از while (ch != 'q') استفاده کنید و بعد از هر محاسبه، دوباره a, b, ch را بخوانید.
// نکات-کلیدی۵
01برای ترکیب چند شرط در if، از && (And)، || (Or) و ! (Not) استفاده کنید؛ کلمات and/or توکنهای جایگزین استاندارد C++ هستند، اما چون کامپایلرهای قدیمی (مثل Turbo C++) آنها را نمیشناسند، همیشه نمادها را بنویسید.
02رقم یکان عدد با n % 10 استخراج میشود، نه با (n / 100) % 10 که رقم صدگان را میدهد.
03C++ به بزرگی و کوچکی حروف حساس است؛ `K` و `k` دو متغیر متفاوت هستند.
04در حلقه while تعاملی، حتماً داخل بدنه دوباره ورودی بخوانید تا حلقه بینهایت نشود.
05قبل از هر تقسیم روی یک شمارنده (مثل k)، حالت k == 0 را بررسی کنید تا از Division by Zero جلوگیری شود.
نام درس، موضوع یا کلمه کلیدی را بنویسید و با Enter به آن بروید
1#include<iostream>2usingnamespace std;34intmain(){5int a, b;6 cin >> a >> b;7for(int i = a +1; i < b; i++){8if(i %3==0&& i %5!=0){9 cout << i <<" ";10}11}12 cout << 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.
شروع/پایانپردازشتصمیمورودی/خروجی
1#include<iostream>2usingnamespace std;34intmain(){5int a, b;6char ch;7 cin >> a >> b >> ch;8while(a !=0|| b !=0|| ch !='0'){9if(ch =='+'){10 cout <<"result = "<< a + b << endl;11}elseif(ch =='-'){12 cout <<"result = "<< a - b << endl;13}elseif(ch =='*'){14 cout <<"result = "<< a * b << endl;15}elseif(ch =='/'){16if(b !=0) cout <<"result = "<< a / b << endl;17else cout <<"division by zero!"<< endl;18}19// ورودی جدید برای تکرار حلقه20 cin >> a >> b >> ch;21}22return0;23}
1#include<iostream>2// using namespace std; فراموش شده3main()4{5int a,b;6char ch;7 cin>>a>>b;8 ch=getch();// غیراستاندارد در C++ مدرن9while(a!=0or b!=0or ch!=0)// خطا: کلمه or10{11if(ch=='+')12 cout<<a+b;13;// سمیکالن اضافی14}15}
1#include<iostream>2usingnamespace std;34intmain(){5int a, b;6char ch;7 cin >> a >> b >> ch;8while(a !=0|| b !=0|| ch !='0'){// || به جای or9if(ch =='+') cout << a + b << endl;10 cin >> a >> b >> ch;11}12return0;13}
1#include<iostream>2usingnamespace std;34intmain(){5int n, a;6int k =0;// شمارنده (با حرف کوچک)7float sum =0;8 cin >> n;9for(int i =1; i <= n; i++){10 cin >> a;11// شرط: سه رقمی بودن و رقم یکان برابر ۷12if(a >=100&& a <=999&& a %10==7){13 sum += a;14 k++;15}16}17if(k ==0){18 cout <<"no matching number"<< endl;19}else{20 cout << sum / k << endl;21}22return0;23}
1main()2{3int n, k =0, a;4float Sum =0;5 cin >> n;6for(int i =1; i <= n; i++){7 cin >> a;8if((a /100)%10==7){// باگ: این رقم صدگان است نه یکان9 Sum += a;10 K++;// باگ: K تعریف نشده، باید k باشد11}12}13 cout << Sum / k;// تقسیم بر صفر اگر k=0 باشد14}
1#include<iostream>2usingnamespace std;34intmain(){5int n, a, k =0;6float Sum =0;7 cin >> n;8for(int i =1; i <= n; i++){9 cin >> a;10if(a >=100&& a <=999&& a %10==7){// رقم یکان صحیح11 Sum += a;12 k++;// حرف کوچک k13}14}15if(k >0) cout << Sum / k << endl;16return0;17}
if(k >0){ cout << Sum / k << endl;}else{ cout <<"no matching number"<< endl;}