برنامه نویسی ++C جلسه چهارم
جلسه چهارم
«تكرار»
مقدمه
تكرار، اجراي پي در پي يك دستور يا بلوكي از دستورالعملها در يك برنامه
است. با استفاده از تکرار ميتوانيم کنترل برنامه را مجبور کنيم تا به خطوط قبلي
برگردد و آنها را دوباره اجرا نمايد.
C++ داراي سه دستور تكرار است:
دستور while، دستور do_while و دستور for. دستورهاي تکرار به علت طبيعت چرخهمانندشان، حلقه نيز ناميده ميشوند.
1- دستور while
نحو دستور
while به شکل زير است:
while
(condition) statement;
به جاي condition، يك شرط قرار ميگيرد و به جاي statement دستوري که بايد تکرار شود قرار ميگيرد. اگر مقدار شرط، صفر(يعني
نادرست) باشد، statement ناديده گرفته ميشود
و برنامه به اولين دستور بعد از while پرش ميكند. اگر مقدار شرط ناصفر(يعني درست) باشد،
statement اجرا شده و دوباره مقدار شرط بررسي ميشود.
اين تکرار آن قدر ادامه مييابد تا اين که مقدار شرط صفر شود.
مثال 1-4 محاسبۀ حاصل جمع اعداد
صحيح متوالي با حلقۀ while
اين برنامه مقدار 1
+ 2 + 3 + … + n
را براي عدد ورودي n محاسبه ميكند:
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (i <= n)
sum += i++;
cout << "The sum of the first " << n <<
" integers is "
<< sum;
}
2-
خاتمه دادن به يك حلقه
قبلا ديديم كه چگونه دستور break براي كنترل دستورالعمل switch استفاده ميشود (به مثال 17-4 نگاه كنيد). از
دستور break براي پايان دادن به حلقهها
نيز ميتوان استفاده کرد.
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (true)
{ if (i > n) break;
sum += i++;
}
cout << "The sum of the first " << n <<
" integers is " << sum;
}
يكي از مزيتهاي دستور break اين است كه فورا حلقه را خاتمه ميدهد بدون اين
که مابقي دستورهاي درون حلقه اجرا شوند.
* مثال 4-4 اعداد فيبوناچي
اعداد فيبوناچي F0, F1, F2,
F3, …
به شکل بازگشتي توسط معادلههاي زير تعريف ميشوند:
F0 = 0 , F1 = 1 , Fn = Fn-1 + Fn-2
مثلا براي n=2 داريم:
F2 =
F2-1 + F2-2 = F1 + F0 = 0 + 1 = 1
يا براي n=3 داريم:
F3 =
F3-1 + F3-2 = F2 + F1 = 1 + 1 = 2
و براي n=4 داريم:
F4 =
F4-1 + F4-2 = F3 + F2 = 2 + 1 = 3
برنامۀ زير، همۀ اعداد فيبوناچي
را تا يك محدودۀ مشخص که از ورودي دريافت ميشود، محاسبه و چاپ ميكند:
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Fibonacci numbers < " << bound
<< ":\n0, 1";
long f0=0, f1=1;
while (true)
{ long f2 = f0 + f1;
if (f2 > bound) break;
cout << ", " << f2;
f0 = f1;
f1 = f2;}
}
Enter a positive integer: 1000
Fibonacci numbers < 1000:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,
144, 233, 377, 610, 987
مثال5-4 استفاده از تابع
exit(0)
تابع exit(0) روش ديگري براي خاتمه دادن به يك حلقه است. هرچند که اين تابع
بلافاصله اجراي کل برنامه را پايان ميدهد:
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Fibonacci numbers < " << bound
<< ":\n0, 1";
long f0=0, f1=1;
while (true)
{ long f2 = f0 + f1;
if (f2 > bound) exit(0);
cout << ", " << f2;
f0 = f1;
f1 = f2; }
}
برنامهنويسان ترجيح ميدهند از break براي خاتمه دادن به حلقههاي نامتناهي استفاده
کنند زيرا قابليت انعطاف بيشتري دارد.
متوقف کردن يك حلقۀ نامتناهي :
با فشردن کليدهاي Ctrl+C سيستم عامل يک برنامه را به اجبار خاتمه ميدهد.
كليد Ctrl را پايين نگه داشته و كليد
C روي صفحهكليد خود را فشار دهيد تا برنامۀ فعلي
خاتمه پيدا کند.
3-
دستور do..while
ساختار do..while
روش ديگري براي ساختن حلقه است. نحو آن به صورت زير است:
do statement while (condition);
به جاي condition يك شرط قرار ميگيرد و به جاي statement دستور يا بلوکي قرار ميگيرد
که قرار است تکرار شود.
اين دستور ابتدا statement
را اجرا ميكند و سپس شرط condition را بررسي ميكند. اگر شرط
درست بود حلقه دوباره تکرار ميشود وگرنه حلقه پايان مييابد.
دستور do..while
مانند دستور while است. با اين فرق كه شرط کنترل حلقه به جاي اين
که در ابتداي حلقه ارزيابي گردد، در انتهاي حلقه ارزيابي ميشود.
يعني هر متغير كنترلي به جاي اين
كه قبل از شروع حلقه تنظيم شود، ميتواند درون آن تنظيم گردد.
نتيجۀ ديگر اين است كه حلقۀ do..while
هميشه بدون توجه به مقدار شرط كنترل، لااقل يك بار اجرا ميشود اما حلقۀ while
ميتواند اصلا اجرا نشود.
مثال 7-4 محاسبۀ حاصل جمع
اعداد صحيح متوالي با حلقۀ do..while
اين برنامه همان تأثير مثال 1-5 را دارد:
int main()
{ int n, i=0;
cout << "Enter a
positive integer: ";
cin >> n;
long sum=0;
do
sum += i++;
while (i <= n);
cout << "The sum of
the first " << n << " integers is " << sum;
}
* مثال 8-4 اعداد فاكتوريال
اعداد فاكتوريال 0! و 1! و 2!
و 3! و … با استفاده از رابطههاي بازگشتي زير تعريف ميشوند:
0! = 1 , n! = n(n-1)!
براي مثال، به ازاي n = 1 در معادلۀ دوم داريم:
1! = 1((1-1)!) = 1(0!) = 1(1) = 1
همچنين براي n = 2 داريم:
2! = 2((2-1)!) = 2(1!) = 2(1) = 2
و به ازاي n = 3 داريم:
3! = 3((3-1)!) = 3(2!) = 3(2) = 6
برنامۀ زير همۀ اعداد فاكتوريال
را که از عدد داده شده کوچکترند، چاپ ميکند:
int main()
{ long bound;
cout << "Enter a
positive integer: ";
cin >> bound;
cout << "Factorial
numbers < " << bound << ":\n1";
long f=1, i=1;
do
{ cout << ", " << f;
f *= ++i;
}
while (f < bound);
}
4 - دستور for
نحو دستورالعمل for
به صورت زير است:
for (initialization; condition; update) statement;
سه قسمت داخل پرانتز، حلقه را
کنترل ميکنند.
عبارت initialization براي اعلان يا مقداردهي اوليه به متغير کنترل حلقه استفاده ميشود.اين
عبارت اولين عبارتي است که ارزيابي ميشود پيش از اين که نوبت به تکرارها
برسد.
عبارت condition براي تعيين اين که آيا حلقه بايد تکرار شود يا خير به کار ميرود.
يعني اين عبارت، شرط کنترل حلقه است. اگر اين شرط درست باشد دستور statement
اجرا ميشود.
عبارت updateبراي پيشبردن متغير کنترل حلقه به کار ميرود. اين عبارت پس از اجراي statement
ارزيابي ميگردد.
بنابراين زنجيرۀ وقايعي که تکرار
را ايجاد ميکنند عبارتند از:
1 – ارزيابي عبارت initialization
2 – بررسي شرط condition . اگر نادرست باشد، حلقه خاتمه مييابد.
3 – اجراي statement
4 – ارزيابي عبارت update
5 – تکرار گامهاي 2 تا 4
عبارتهاي initialization و condition و updateعبارتهاي اختياري هستند. يعني ميتوانيم
آنها را در حلقه ذکر نکنيم.
مثال 9-4 استفاده از حلقۀ for
براي محاسبۀ مجموع اعداد صحيح متوالي
اين برنامه همان تأثير مثال 1-5 را دارد:
int main()
{ int n;
cout << "Enter a
positive integer: ";
cin >> n;
long sum=0;
for (int i=1; i <= n; i++)
sum += I;
cout << "The sum of the first " << n <<
" integers is " << sum;
}
در C++ استاندارد وقتي يك متغير
كنترل درون يك حلقۀ for اعلان ميشود (مانند i در
مثال بالا) حوزۀ آن متغير به همان حلقۀ for محدود ميگردد. يعني آن متغير نميتواند بيرون از آن حلقه
استفاده شود.
نتيجۀ ديگر اين است که ميتوان
از نام مشابهي در خارج از حلقۀ for براي يك متغير ديگر
استفاده نمود.
مثال 12-4 يك حلقۀ for
نزولي
برنامۀ زير ده عدد صحيح مثبت را
به ترتيب نزولي چاپ ميكند:
int main()
{ for (int
i=10; i > 0; i--)
cout << " "
<< i;
}
مثال 15-4 بيشتر از يك متغير
كنترل در حلقۀ for
حلقۀ for
در برنامۀ زير دو متغير كنترل دارد:
int main()
{ for (int m=95, n=11, m%n >
0; m -= 3, n++)
cout << m <<
"%" << n << " = " << m%n << endl;
}
مثال 16-4 حلقههاي for
تودرتو
برنامۀ زير يك جدول ضرب چاپ ميكند:
#include
#include
int main()
{ for (int x=1; x <= 10; x++)
{ for (int y=1; y <= 10; y++)
cout << setw(4) << x*y;
cout <<
endl;
}
}
5- دستور break
دستور break يک دستور آشناست. قبلا از آن براي خاتمه دادن به
دستور switch و همچنين حلقههاي while و do..while استفاده کردهايم. از اين دستور براي خاتمه دادن
به حلقۀ for نيز ميتوانيم استفاده
کنيم.
وقتي دستور break درون حلقههاي تودرتو استفاده شود، فقط روي حلقهاي
که مستقيما درون آن قرار گرفته تاثير ميگذارد.
حلقههاي بيروني بدون هيچ تغييري
ادامه مييابند.
دستور break در هر جايي درون حلقه ميتواند جا بگيرد و در
همان جا حلقه را خاتمه دهد.
6-
دستور continue
دستور break بقيۀ دستورهاي درون بلوك حلقه را ناديده گرفته و
به اولين دستور بيرون حلقه پرش ميكند. دستور continue نيز شبيه همين است اما به جاي اين که حلقه را
خاتمه دهد، اجرا را به تكرار بعدي حلقه منتقل ميكند.
اين دستور، ادامۀ چرخۀ فعلي را
لغو کرده و اجراي دور بعدي حلقه را آغاز ميکند.
مثال 19-4 استفاده از
دستورهاي break و continue
اين برنامۀ كوچك، دستورهاي break و continue را شرح ميدهد:
int main()
{ int n = 1;
char c;
for( ; ;n++ )
{ cout << "\nLoop no:
" << n << endl;
cout << "Continue?
cin >> c;
if (c = = 'y') continue;
break;
}
cout << "\nTotal of loops: " << n;
}
7- دستور goto
دستورgoto نوع ديگري از دستورهاي پرش است. مقصد اين پرش
توسط يك برچسب معين ميشود.
برچسب شناسهاي است كه جلوي آن علامت كولن( : ) ميآيد و جلوي يك دستور ديگر
قرار ميگيرد.
يک مزيت دستور goto اين است که با استفاده از آن ميتوان از همۀ
حلقههاي تودرتو خارج شد و به مکان دلخواهي در برنامه پرش نمود.
مثال
20-4 استفاده از دستور goto براي خارج شدن از حلقههاي
تودرتو
int main()
{ const
int N=5;
for (int i=0; i
{ for (int j=0; j
{ for (int k=0; k
if (i+j+k>N) goto esc;
else cout << i+j+k << " ";
cout << "* ";
}
esc:
cout << "." << endl;
}
}
8- توليد اعداد شبه تصادفي
يكي از كاربردهاي بسيار مهم
رايانهها، «شبيهسازي» سيستمهاي دنياي واقعي است. تحقيقات و توسعههاي بسيار
پيشرفته به اين راهکار خيلي وابسته است. به وسيلۀ شبيهسازي ميتوانيم رفتار سيستمهاي
مختلف را مطالعه کنيم بدون اين که لازم باشد واقعا آنها را پيادهسازي نماييم. در
شبيهسازي نياز است «اعداد تصادفي» توسط رايانهها توليد شود تا نادانستههاي
دنياي واقعي مدلسازي شود.
رايانهها «ثابتکار» هستند يعني
با دادن دادههاي مشابه به رايانههاي مشابه، هميشه خروجي يکسان توليد ميشود. با
وجود اين ميتوان اعدادي توليد کرد که به ظاهر تصادفي هستند؛ اعدادي که به طور
يکنواخت در يک محدودۀ خاص گستردهاند و براي هيچکدام الگوي مشخصي وجود ندارد.
چنين اعدادي را «اعداد شبهتصادفي» ميناميم.
مثال 22-4 توليد اعداد شبه تصادفي
اين برنامه از تابع rand()
براي توليد اعداد شبهتصادفي استفاده ميكند:
#include
#include
int main()
{ // prints pseudo-random
numbers:
for (int i = 0; i < 8; i++)
cout << rand()
<< endl;
cout << "RAND_MAX =
" << RAND_MAX << endl;
}
هر بار که برنامۀ بالا اجرا شود،
رايانه هشت عدد صحيح unsigned توليد ميکند که به طور يکنواخت در فاصلۀ 0 تا RAND_MAX
گسترده شدهاند. RAND_MAX در اين رايانه برابر با 2,147,483,647 است.
هر عدد شبهتصادفي از روي عدد
قبلي خود ساخته ميشود.
اولين عدد شبهتصادفي از روي
يك مقدار داخلي که «هسته» گفته ميشود ايجاد ميگردد.
هر دفعه که برنامه اجرا شود، هسته با يک مقدار
پيشفرض بارگذاري ميشود.
براي حذف اين اثر نامطلوب که از تصادفي بودن
اعداد ميکاهد، ميتوانيم با استفاده از تابع ()srand خودمان مقدار هسته را
انتخاب کنيم.
مثال 23-4 كارگذاري هسته به
طور محاورهاي
اين برنامه مانند برنامۀ مثال 22-4 است بجز اين كه
ميتوان هستۀ توليدکنندۀ اعداد تصادفي را به شکل محاورهاي وارد نمود:
#include
#include
int main()
{ // prints pseudo-random
numbers:
unsigned seed;
cout << "Enter
seed: ";
cin >> seed;
srand(seed); // initializes the seed
for (int i = 0; i < 8; i++)
cout << rand()
<< endl;
}