ایران سرفراز- نرم افزار وپروژهای دانشجویی


نرم افزار وپروژهای دانشجویی

فصل چهارم در تکرار ++C

<!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

mohsen_mahyar@yahoo.com

C ++ فصل چهارم در تکرار  101

این مثال یک راه برای خروج از حلقۀ نامتناهی را نشان داد. مثال بعدی روش

برای خاتمه دادن break دیگری را نشان می دهد. اما برنام هنویسان ترجیح می دهند از

به حلقه های نامتناهی استفاده کنند زیرا قابلیت انعطاف بیشتری دارد.

4 متوقف کردن یک حلقۀ نامتناهی ‐ * مثال 6

اگر از راهکارهای خاتمۀ حلقه استفاده نکنید، حلقه برای همیشه ادامه پیدا می کند

و به طبع آن برنامه هم هیچ گاه به پایان نمی رسد. ممکن است شرط کنترلی که برای

نشود و حلقه تا بی نهایت ادامه « نادرست » حلقه می نویسید هنگام اجرای برنامه هیچ گاه

Ctrl+C یابد. در چنین مواردی از سیستم عامل کمک بگیرید. با فشردن کلیدهای

را پایین نگه داشته و Ctrl سیستم عامل یک برنامه را به اجبار خاتمه می دهد. کلید

روی صفحه کلید خود را فشار دهید تا برنامۀ فعلی خاتمه پیدا کند. به کد زیر C کلید

نگاه کنید:

int main()

{ long bound;

cout << "Enter a positive integer: ";

cin >> bound;

cout << "Fibonacci numbers < " << bound << ":\n0, 1";

long f0=0, f1=1;

while (true) // ERROR: INFINITE LOOP! Press <Ctrl>+c.)

{ long f2 = f0 + f1;

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,

159781, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,

317811, 5040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352,

24157817, 63245986, 102334155, 165580141, 267914296, 433494437,

 

102 برنامه سازی پیشرفته

چون هیچ شرط پایان حلق های در این برنامه وجود ندارد، اجرای برنامه تا

را Ctrl+C بی نهایت ادامه خواهد یافت (تا وقتی حافظه سرریز شود). پس کلیدهای

فشار دهید تا برنامه خاتمه یابد.

do..while 4 دستور ‐3

روش دیگری برای ساختن حلقه است. نحو آن به do..while ساختار

صورت زیر است:

do statement while (condition);

دستور یا statement یک شرط قرار می گیرد و به جای condition به جای

را اجرا statement بلوکی قرار می گیرد که قرار است تکرار شود. این دستور ابتدا

را بررسی می کند. اگر شرط درست بود حلقه condition می کند و سپس شرط

دوباره تکرار می شود وگرنه حلقه پایان می یابد.

است. با این فرق که شرط کنترل while مانند دستور do..while دستور

حلقه به جای این که در ابتدای حلقه ارزیابی گردد، در انتهای حلقه ارزیابی م یشود.

یعنی هر متغیر کنترلی به جای این که قبل از شروع حلقه تنظیم شود، می تواند درون آن

همیشه بدون توجه به do..while تنظیم گردد. نتیجۀ دیگر این است که حلقۀ

می تواند اصلا اجرا while مقدار شرط کنترل، لااقل یک بار اجرا می شود اما حلقۀ

نشود.

do..while 4 محاسبۀ حاصل جمع اعداد صحیح متوالی با حلقۀ ‐ * مثال 7

4 را دارد: ‐ این برنامه همان تأثیر مثال 1

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;

 

 

فصل چهارم / تکرار 103

}

4 اعداد فاکتوریال ‐ * مثال 8

اعداد فاکتوریال ! 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);

}

Enter a positive integer: 100000

Factorial numbers < 100000:

1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880

نادرست شود، تکرار (f < bound) تا وقتی که شرط کنترل do..while حلقۀ

می گردد.

 

 

104 برنامه سازی پیشرفته

for 4 دستور

به صورت زیر است: for نحو دستورالعمل

for (initialization; condition; update) statement;

برای initialization سه قسمت داخل پرانتز، حلقه را کنترل می کنند. عبارت

اعلان یا مقداردهی اولیه به متغیر کنترل حلقه استفاده می شود. این عبارت اولین عبارتی

condition است که ارزیابی می شود پیش از این که نوبت به تکرارها برسد. عبارت

برای تعیین این که آیا حلقه باید تکرار شود یا خیر به کار می رود. یعنی این عبارت،

اجرا statement شرط کنترل حلقه است. اگر این شرط درست باشد دستور

برای پیش بردن متغیر کنترل حلقه به کار می رود. این عبارت update می شود. عبارت

ارزیابی می گردد. بنابراین زنجیرۀ وقایعی که تکرار را statement پس از اجرای

ایجاد می کنند عبارتند از:

initialization 1 – ارزیابی عبارت

اگر نادرست باشد، حلقه خاتمه می یابد. . condition 2 – بررسی شرط

statement 3 – اجرای

update 4 – ارزیابی عبارت

5 – تکرار گام های 2 تا 4

عبارت های update و condition و initialization عبارت های

اختیاری هستند. یعنی می توانیم آن ها را در حلقه ذکر نکنیم.

برای محاسبۀ مجموع اعداد صحیح متوالی for 4 استفاده از حلقۀ ‐ * مثال 9

4 را دارد: ‐ این برنامه همان تأثیر مثال 1

int main()

{ int n;

cout << "Enter a positive integer: ";

 

فصل چهارم / تکرار 105

cin >> n;

long sum=0;

for (int i=1; i <= n; i++)

sum += I;

cout << "The sum of the first " << n << " integers is " << sum;

}

i<=n است. شرط کنترل حلقه int i= در حلقۀ برنامۀ فوق، عبارت مقداردهی اولیه 1

است. دقت کنید که این ها همان i++ می باشد و عبارت پیش بری متغیر کنترل هم

4 استفاده شده است. ‐ 4 و 7 ‐ 4 و 3 ‐ عباراتی هستند که در برنامۀ مثال های 1

اعلان می شود for استاندارد وقتی یک متغیر کنترل درون یک حلقۀ C++ در

محدود می گردد. یعنی آن for در مثال بالا) حوزۀ آن متغیر به همان حلقۀ i (مانند

متغیر نمی تواند بیرون از آن حلقه استفاده شود. نتیجۀ دیگر این است که می توان از نام

برای یک متغیر دیگر استفاده نمود. for مشابهی در خارج از حلقۀ

for 4 استفادۀ مجدد از اسامی متغیرهای کنترل حلقۀ ‐ * مثال 10

4 را دارد: ‐ برنامۀ زیر همان اثر برنامۀ مثال 1

int main()

{ int n;

cout << "Enter a positive integer: ";

cin >> n;

long sum=0;

for (int i=1; i < n/2; i++)

// the scope of this i is this loop

sum += i;

for (int i=n/2; i <= n; i++)

// the scope of this i is this loop

sum += i;

cout << "The sum of the first " << n << " integers is " << sum ;

}

4 را انجام ‐ در برنامۀ مثال 9 for در برنامۀ بالا همان محاسبات حلقۀ for دو حلقۀ

محاسبه در حلقۀ اول n/ می دهند. این دو حلقه، کار را به دو قسمت تقسیم می کنند: 2

 

106 برنامه سازی پیشرفته

خودش i انجام می گیرد و مابقی در حلقۀ دوم. هر حلقه به طور مستقل متغیر کنترلی

را دارد.

for استاندارد، حوزۀ متغیر کنترلی حلقۀ C++ اخطار: بیشتر کامپایلرهای قبل از

را تا بعد از پایان حلقه نیز گسترش می دهند.

4 دوباره اعداد فیبوناچی ‐ * مثال 11

4 را دارد: ‐ این برنامه همان تأثیر برنامۀ مثال 8

int main()

{ long bound;

cout << "Enter a positive integer: ";

cin >> bound;

cout << "Factorial numbers < " << bound << ":\n1";

long f=1;

for (int i=2; f <= bound; i++)

{ cout << ", " << f;

f *= i;

}

}

Enter a positive integer: 100000

Factorial numbers < 100000:

1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880

4 مقایسه کنید. هر دو کارهای مشابهی را انجام می دهند. در هر ‐ برنامۀ بالا را با مثال 8

قرار می گیرد. مقدار اولیۀ 2 f دو برنامه، کارهای زیر انجام می شود: مقدار اولیۀ 1 در

،i در f ضرب ،f قرار داده می شود و سپس پنج گام تکرار رخ می دهد: چاپ i در

و پایان دادن به حلقه در صورت نادرست (f <= bound) بررسی شرط ،i افزایش

را دارد. do..while همان تأثیر برنامه با حلقۀ for بودن شرط. این برنامه با حلقۀ

انعطاف پذیری بیشتری به برنامه می دهد. مثال های زیر این مطلب for دستور

را آشکار می کنند.

نزولی for 4 یک حلقۀ ‐ * مثال 12

 

فصل چهارم / تکرار 107

برنامۀ زیر ده عدد صحیح مثبت را به ترتیب نزولی چاپ می کند:

int main()

{ for (int i=10; i > 0; i--)

cout << " " << i;

}

10 9 8 7 6 5 4 3 2 1

با گام های بزرگ تر از یک for 4 استفاده از حلقۀ ‐ * مثال 13

برنامۀ زیر مشخص می کند که آیا یک عدد ورودی اول هست یا خیر:

int main()

{ long n;

cout << "Enter a positive integer: ";

cin >> n;

if (n < 2) cout << n << " is not prime." << endl;

else if (n < 4) cout << n << " is prime." << endl;

else if (n%2 == 0) cout << n << " = 2*" << n/2 << endl;

else

{ for (int d=3; d <= n/2; d+=2)

if (n%d == 0)

{ cout << n << " = " << d << "*" << n/d << endl;

exit(0);

}

cout << n << " is prime." << endl;

};

}

Enter a positive integer: 101

101 is prime.

Enter a positive integer: 975313579

975313579 = 17*57371387

را دو واحد دو واحد d در برنامۀ بالا متغیر کنترلی خود یعنی for توجه کنید که حلقۀ

افزایش می دهد. سعی کنید منطق برنامۀ بالا را توضیح دهید.

for 4 استفاده از نگهبان برای کنترل حلقۀ ‐ * مثال 14

این برنامه مقدار بیشینۀ یک رشته از اعداد ورودی را پیدا می کند:

 

108 برنامه سازی پیشرفته

int main()

{ int n, max;

cout << "Enter positive integers (0 to quit): ";

cin >> n;

for (max = n; n > 0; )

{ if (n > max) max = n;

cin >> n;

}

cout << "max = " << max << endl;

}

Enter positive integers (0 to quit): 44 77 55 22 99 33 11 66 88 0

max = 99

کنترل می شود. این حلقه ادامه n در برنامۀ بالا به وسیلۀ متغیر ورودی for حلقۀ

بشود. متغیر ورودی که به این شیوه برای کنترل حلقه نیز n<= می یابد تا زمانی که 0

استفاده شود، نگهبان نامیده می شود.

است دقت (max = n; n > به بخش کنترلی این حلقه که به صورت (; 0

کنید. بخش پیش بری در آن وجود ندارد و بخش مقداردهی آن نیز متغیر جدیدی را

تعریف نمی کند بلکه از متغیرهایی که قبلا در برنامه تعریف شده استفاده می برد. علت

این است که حلقۀ مذکور نگهبان دارد و نگهبان از طریق ورودی پیش برده می شود و

نیز باید مقدار خود را پس max دیگر نیازی به بخش پیش بری در حلقه نیست. متغیر

درون حلقه اعلان max از اتمام حلقه حفظ کند تا در خروجی چاپ شود. اگر متغیر

می شد، پس از اتمام حلقه از بین می رفت و دیگر قابل استفاده نبود.

for 4 بیشتر از یک متغیر کنترل در حلقۀ ‐ * مثال 15

در برنامۀ زیر دو متغیر کنترل دارد: for حلقۀ

int main()

{ for (int m=95, n=11, m%n > 0; m -= 3, n++)

cout << m << "%" << n << " = " << m%n << endl;

}

95%11 = 7

92%12 = 8

89%13 = 11

 

فصل چهارم / تکرار 109

86%14 = 2

83%15 = 8

به عنوان متغیر کنترل اعلا ن و n و m در بخش کنترل این حلقه، دو متغیر

یک واحد افزایش n سه واحد کاسته شده و m ، مقداردهی شده اند. در هر تکرار حلقه

به شکل ( 95,11 ) و ( 92,12 ) و ( 89,13 ) و (m,n) می یابد. در نتیجه زوج های

86,14 ) و ( 83,15 ) و ( 80,16 ) تولید می شوند. چون 80 بر 16 بخش پذیر )

است، حلقه با زوج ( 80,16 ) پایان می یابد.

تودرتو for 4 حلقه های ‐ * مثال 16

برنامۀ زیر یک جدول ضرب چاپ می کند:

#include <iomanip> // defines setw()

#include <iostream> // defines cout

using namespace std;

int main()

{ for (int x=1; x <= 10; x++)

{ for (int y=1; y <= 10; y++)

cout << setw(4) << x*y;

cout << endl;

}

}

1 2 3 4 5 6 7 8 9 10

2 4 6 8 10 12 14 16 18 20

3 6 9 12 15 18 21 24 27 30

4 8 12 16 20 24 28 32 36 40

5 10 15 20 25 30 35 40 45 50

6 12 18 24 30 36 42 48 54 60

7 14 21 28 35 42 49 56 63 70

8 16 24 32 40 48 56 64 72 80

9 18 27 36 45 54 63 72 81 90

10 20 30 40 50 60 70 80 90 100

است، حلقۀ درونی ده مرتبه تکرار x= در اولین تکرار از حلقۀ بیرونی، وقتی که 1

1 را روی یک ردیف چاپ م یکند. وقتی *y تا 10 مقادیر y= می شود و به ازای 1

مکان نما به سطر بعدی روی cout << endl; حلقۀ درونی پایان یافت، با دستور

آغاز x= صفحه نمایش منتقل می شود. حالا دومین تکرار حلقۀ بیرونی به ازای 2

 

 

110 برنامه سازی پیشرفته

2 روی یک *y می شود. دوباره حلقۀ درونی ده مرتبه تکرار می شود و این دفعه مقادیر

مکان نما به سطر بعدی cout << endl; سطر چاپ می شود. دوباره با دستور

می رود و تکرار سوم حلقۀ بیرونی شروع می شود. این رویه ادامه می یابد تا این که

حلقۀ بیرونی برای بار دهم تکرار شده و آخرین سطر جدول هم چاپ می شود و سپس

برنامه خاتمه می یابد.

به setw( استفاده شده. عبارت ( 4 setw در این برنامه از شکل دهندۀ فرایند

این معنی است که طول ناحیۀ چاپ را برای خروجی بعدی به اندازۀ چهار کاراکتر

تنظیم کن. به این ترتیب اگر خروجی کم تر از چهار کاراکتر باشد، فضای خالی به

خروجی مربوطه پیوند زده می شود تا طول خروجی به اندازۀ چهار کاراکتر شود. نتیجه

این است که خروجی نهایی به شکل یک جدول مرتب روی ده سطر و ده ستون زیر

تعریف شده اند. <iomanip> هم چاپ می شود. شکل دهنده های فرایند در سرفایل

بنابراین برای استفاده از شکل دهنده های فرآیند باید راهنمای پیش پردازندۀ

را به ابتدای برنامه بیافزایید. همچنین برنامه باید دارای #include <iomanip>

نیز باشد. #include<iostream> راهنمای پیش پردازندۀ

break 4 دستور ‐5

یک دستور آشناست. قبلا از آن برای خاتمه دادن به دستور break دستور

استفاده کرد هایم. از این do..while و while و همچنین حلق ههای switch

break نیز می توانیم استفاده کنیم. دستور for دستور برای خاتمه دادن به حلقۀ

یک ، while انعطاف پذیری بیشتری را برای حلقه ها ایجاد می کند. معمولا یک حلقۀ

فقط در شروع یا پایان مجموعۀ کامل for یا یک حلقۀ do..while حلقۀ

در هر جایی break دستورالعمل های موجود در بلوک حلقه، خاتمه می یابد. دستور

درون حلقه می تواند جا بگیرد و در همان جا حلقه را خاتمه دهد.

4 کنترل ورودی با یک نگهبان ‐ * مثال 17

این برنامه یک رشته اعداد صحیح مثبت را تا زمانی که صفر وارد شود، خوانده و

معدل آ نها را محاسبه می کند:

 

 

فصل چهارم / تکرار 111

int main()

{ int n, count=0, sum=0;

cout << "Enter positive integers (0 to quit):" << endl;

for (;;) // "forever"

{ cout << "\t" << count + 1 << ": ";

cin >> n;

if (n <= 0) break;

++count;

sum += n;

}

cout << "The average of those " << count << " positive

numbers is " << float(sum)/count << endl;

}

Enter positive integers (0 to quit):

1: 4

2: 7

3: 1

4: 5

5: 2

6: 0

The average of those 5 positive numbers is 3.8

اجرا شده و حلقه فورا خاتمه break در برنامۀ بالا وقتی که 0 وارد شود، دستور

می یابد و اجرای برنامه به اولین دستور بعد از حلقه پرش می کند. به نحوۀ نوشتن

در این برنامه دقت کنید. هر سه بخش کنترلی در این حلقه، خالی است: for دستور

این break این ترکیب به معنای بی انتهایی است. یعنی بدون دستور .for( ; ; )

حلقه یک حلقۀ نامتناهی می شود.

درون حلقه های تودرتو استفاده شود، فقط روی حلقه ای break وقتی دستور

که مستقیما درون آن قرار گرفته تاثیر می گذارد. حلقه های بیرونی بدون هیچ تغییری

ادامه می یابند.

در حلق ههای تودرتو break 4 استفاده از دستور ‐ * مثال 18

 

112 برنامه سازی پیشرفته

3)، برای ایجاد یک ×4 = 4× چون عمل ضرب جابجایی پذیر است (یعنی 3

جدول ضرب فقط کافی است اعداد قطر پایینی مشخص شوند. این برنامه، مثال 16

4 را برای چاپ یک جدول ضرب مثلثی تغییر می دهد:

int main()

{ for (int x=1; x <= 10; x++)

{ for (int y=1; y <= 10; y++)

if (y > x) break;

else cout << setw(4) << x*y;

cout << endl;

}

}

1

2 4

3 6 9

4 8 12 16

5 10 15 20 25

6 12 18 24 30 36

7 14 21 28 35 42 49

8 16 24 32 40 48 56 64

9 18 27 36 45 54 63 72 81

10 20 30 40 50 60 70 80 90 100

x درونی خاتمه می یابد و تکرار بعدی حلقۀ خارجی y باشد، اجرای حلقۀ y>x وقتی

سه بار تکرار می شود و خروجی های 3 y باشد، حلقۀ x= شروع می شود. مثلا وقتی 3

برابر با درست ارزیابی (y>x) و 6 و 9 چاپ می شوند. در تکرار چهارم، شرط

منتقل cout<<endl; اجرا شده و کنترل فورا به خط break می شود. پس دستور

است). آنگاه حلقۀ بیرونی y می شود (زیرا این خط اولین دستور خارج از حلقۀ درونی

آغاز می کند. x= تکرار چهارم را با 4 x

continue 4 دستور ‐6

بقیۀ دستورهای درون بلوک حلقه را نادیده گرفته و به اولین break دستور

نیز شبیه همین است اما به جای continue دستور بیرون حلقه پرش م یکند. دستور

 

فصل چهارم / تکرار 113

این که حلقه را خاتمه دهد، اجرا را به تکرار بعدی حلقه منتقل م یکند. این دستور،

ادامۀ چرخۀ فعلی را لغو کرده و اجرای دور بعدی حلقه را آغاز می کند.

continue و break 4 استفاده از دستورهای ‐ * مثال 19

را شرح می دهد: continue و break این برنامۀ کوچک ، دستورهای

int main()

{ int n = 1;

char c;

for( ; ;n++ )

{ cout << "\nLoop no: " << n << endl;

cout << "Continue? <y|n> ";

cin >> c;

if (c = = 'y') continue;

break;

}

cout << "\nTotal of loops: " << n;

}

Loop no: 1

Continue? y

Loop no: 2

Continue? y

Loop no: 3

Continue? n

Total of loops: 3

مشخص n برنامۀ بالا تعداد تکرار حلقه را می شمارد. در ابتدای هر حلقه با چاپ

می شود که چندمین دور حلقه در حال اجراست. سپس از کاربر درخواست می شود تا

باشد، شرط 'y' یک کاراکتر را به عنوان انتخاب، وارد کند. اگر کاراکتر وارد شده

اجرا شده و continue برابر با درست ارزیابی می شود و لذا دستور (c=='y')

باشد، 'y' دور جدید حلقه شروع می شود. اگر کاراکتر وارد شده هر چیزی غیر از

این حلقه را خاتمه می دهد و کنترل اجرا به اولین دستور بیرون حلقه break دستور

پرش می کند. سپس مجموع دفعاتی که حلقه تکرار شده چاپ می گردد و برنامه پایان

می گیرد.

 

114 برنامه سازی پیشرفته

goto 4 دستور ‐7

باعث می شوند که اجرای switch و continue و break دستورهای

برنامه به مکان دیگری از جایی که به طور طبیعی باید می رفت، منتقل شود. مقصد

به continue ، به خارج از حلقه می رود break : انتقال را نوع دستور تعیین می کند

case به یکی از ثابت های switch شرط ادامۀ حلقه(دور بعدی حلقه) می رود و

می رود. هر سۀ این دستورها دستور پرش 1 هستند زیرا باعث می شوند اجرای برنامه از

روی دستورهای دیگر پرش کند.

نوع دیگری از دستورهای پرش است. مقصد این پرش توسط یک goto دستور

برچسب معین می شود. برچسب 2 شناسه ای است که جلوی آن علامت کولن( : )

ها در دستور case می آید و جلوی یک دستور دیگر قرار می گیرد. برچسب ها شبیه

این goto هستند، یعنی مقصد پرش را مشخص می کنند. یک مزیت دستور switch

است که با استفاده از آن می توان از همۀ حلقه های تودرتو خارج شد و به مکان

دلخواهی در برنامه پرش نمود.

فقط درونی ترین حلقه را خاتمه break مثال زیر نشان می دهد که دستور

می توان چند حلقه یا همۀ حلقه ها را یک جا خاتمه داد. goto می دهد ولی با دستور

برای خارج شدن از حلقه های تودرتو goto 4 استفاده از دستور ‐ * مثال 20

int main()

{ const int N=5;

for (int i=0; i<N; i++)

{ for (int j=0; j<N; j++)

{ for (int k=0; k<N; k++)

if (i+j+k>N) goto esc;

else cout << i+j+k << " ";

cout << "* ";

}

esc: cout << "." << endl; // inside the i loop, outside the j loop

}

}

0 1 2 3 4 * 1 2 3 4 5 * 2 3 4 5 .

 

فصل چهارم / تکرار 115

1 2 3 4 5 * 2 3 4 5 .

2 3 4 5 .

3 4 5 .

4 5 .

می رسیم. goto در درونی ترین حلقه درست شود، به دستور (i+j+k>N) اگر شرط

دارد منتقل esc وقتی این دستور اجرا شود، اجرای برنامه به سطری که برچسب

است. پس با این پرش هر دوی این k و j می شود. این خط بیرون از حلقه های

پنج بار تکرار می گردد و k صفر هستند، حلقۀ j و i حلقه ها پایان می گیرند. وقتی

به 1 افزایش می یابد و حلقۀ j 0 به همراه ستاره * چاپ می شود. آنگاه 1 2 3 4

1 همراه یک ستاره * چاپ می شود. 2 3 4 پنج بار دیگر تکرار شده و این بار 5 k

2 3 4 چهار بار دیگر تکرار م یشود و 5 k به 2 افزایش می یابد و حلقۀ j سپس

درست می شود زیرا (i+j+k> شرط ( 0 k چاپ می شود. اما در تکرار بعدی حلقۀ

برای اولین بار اجرا شده و کنترل برنامه goto است. پس دستور i+j+k = حالا 6

به سطر برچس بدار که یک دستور خروجی است پرش می کند، یک نقط ه چاپ شده و

بدون این که k و j مکان نما به سطر بعد منتقل می شود. توجه کنید که حلقه های

تکرارهایشان را کامل کنند، ناتمام رها می شوند. دستور برچسب خورده، خود جزو

آغاز i است. لذا پس از پایان گرفتن اجرای این سطر، تکرار بعدی حلقۀ i بدنۀ حلقۀ

شروع می شود و این خود باعث j= دوباره با 0 j است و حلقۀ i= می شود. حالا 1

دوباره شروع شود. برنامه به همین ترتیب ادامه می یابد و k= نیز با 0 k می گردد حلقۀ

خروجی نهایی حاصل می شود.

می توان از هر قسمت برنامه به هر قسمت دیگری goto با استفاده از دستور

پرش کرد. گرچه این دستور باعث می شود راحت تر بتوانیم از تکرار حلق هها خلاص

شویم یا آسان تر به سطر دلخواه انشعاب کنیم اما تجربه نشان داده که استفادۀ بی مهابا از

سبب افزایش خطاهای زمان اجرا و کاهش پایداری برنامه می شود. goto دستور

goto 4 خارج شدن از چند حلقۀ تودرتو بدون استفاده از ‐ * مثال 21

1 – Jump 2 – Label

 

 

 

116 برنامه سازی پیشرفته

4 را دارد: ‐ این برنامه همان اثر برنامۀ مثال 20

int main()

{ const int N=5;

bool done=false;

for (int i=0; i<N; i++)

{ for (int j=0; j<N && !done; j++)

{ for (int k=0; k<N && !done; k++)

if (i+j+k>N) done = true;

else cout << i+j+k << " ";

cout << "* ";

}

cout << "." << endl; // inside the i loop, outside the j loop

done = false;

}

}

true برابر با done استفاده شده. وقتی done در برنامۀ بالا از یک پرچم به نام

تکرارش را با چاپ i خاتمه می یابد و حلقۀ خارجی j و k شود، هر دو حلقۀ درونی

می کند و دور جدید را آغاز false یک نقطه ادامه می دهد و پرچم را دوباره

می نماید. گرچه منطق این برنامه کمی پیچیده تر است اما قابلیت اطمینان بیشتری نسبت

4 دارد زیرا هیچ حلق های نیمه کاره نمی ماند و هیچ متغیری ‐ به برنامۀ مثال 20

بلاتکلیف رها نمی شود.

4 تولید اعداد شبه تصادفی 1 ‐8

سیستم های دنیای واقعی « شبیه سازی 2 » ، یکی از کاربردهای بسیار مهم رایانه ها

است. تحقیقات و توسعه های بسیار پیشرفته به این راهکار خیلی وابسته است. به

وسیلۀ شبیه سازی می توانیم رفتار سیستم های مختلف را مطالعه کنیم بدون این که لازم

توسط « اعداد تصادفی » باشد واقعا آن ها را پیاده سازی نماییم. در شبیه سازی نیاز است

« ثابت کار » رایانه ها تولید شود تا نادانسته های دنیای واقعی مدل سازی شود. البته رایانه ها

هستند یعنی با دادن داده های مشابه به رایانه های مشابه، همیشه خروجی یکسان تولید

می شود. با وجود این می توان اعدادی تولید کرد که به ظاهر تصادفی هستند؛ اعدادی که

 

فصل چهارم / تکرار 117

به طور یکنواخت در یک محدودۀ خاص گسترده اند و برای هیچ کدام الگوی مشخصی

می نامیم. « اعداد شبه تصادفی » وجود ندارد. چنین اعدادی را

است که rand() استاندارد دارای تابعی به نام c در <cstdlib> سرفایل

تولید می نماید. RAND_MAX این تابع اعداد صحیح شبه تصادفی در محدودۀ صفر تا

تعریف شده. هر بار که <cstdlib> ثابتی است که آن هم در سرفایل RAND_MAX

تولید unsigned فراخوانی شود، یک عدد صحیح متفاوت از نوع rand() تابع

می کند که این عدد در محدودۀ ذکر شده قرار دارد.

4 تولید اعداد شبه تصادفی ‐ * مثال 22

برای تولید اعداد شبه تصادفی استفاده می کند: rand() این برنامه از تابع

#include <cstdlib> // defines the rand() and RAND_MAX

#include <iostream>

int main()

{ // prints pseudo-random numbers:

for (int i = 0; i < 8; i++)

cout << rand() << endl;

cout << "RAND_MAX = " << RAND_MAX << endl;

}

1103527590

377401575

662824084

1147902781

2035015474

368800899

1508029952

486256185

RAND_MAX = 2147483647

تولید می کند که unsigned هر بار که برنامۀ بالا اجرا شود، رایانه هشت عدد صحیح

در این RAND_MAX . گسترده شده اند RAND_MAX به طور یکنواخت در فاصلۀ 0 تا

1 – Pseudo Random 2 – Simulation

 

 

118 برنامه سازی پیشرفته

رایانه برابر با 2,147,483,647 است. خروجی زیر، اجرای دیگری از برنامۀ بالا را

نشان می دهد:

1103527590

377401575

662824084

1147902781

2035015474

368800899

1508029952

486256185

RAND_MAX = 2147483647

متاسفانه هر بار که برنامه اجرا می شود، همان اعداد قبلی تولید می شوند زیرا این اعداد

از یک هستۀ مشترک ساخته می شوند.

هر عدد شبه تصادفی از روی عدد قبلی خود ساخته می شود. اولین عدد

گفته می شود ایجاد می گردد. هر « هسته 1 » شبه تصادفی از روی یک مقدار داخلی که

دفعه که برنامه اجرا شود، هسته با یک مقدار پیش فرض بارگذاری می شود. برای حذف

این اثر نامطلوب که از تصادفی بودن اعداد می کاهد، می توانیم با استفاده از تابع

خودمان مقدار هسته را انتخاب کنیم. srand()

4 کارگذاری هسته به طور محاوره ای ‐ * مثال 23

4 است بجز این که می توان هستۀ تولیدکنندۀ ‐ این برنامه مانند برنامۀ مثال 22

اعداد تصادفی را به شکل محاوره ای وارد نمود:

#include <cstdlib> // defines the rand() and srand()

#include <iostream>

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;

}

 

فصل چهارم / تکرار 119

سه اجرای متفاوت از برنامۀ بالا نشان داده شده است:

Enter seed: 0

12345

1406932606

654583775

1449466924

229283573

1109335178

1051550459

1293799192

Enter seed: 1

1103527590

377401575

662824084

1147902781

2035015474

368800899

1508029952

486256185

Enter seed: 12345

1406932606

654583775

1449466924

229283573

1109335178

1051550459

1293799192

794471793

را به هستۀ داخلی تخصیص می دهد. seed مقدار متغیر srand(seed); خط

برای تولید اعداد شبه تصادفی استفاده می شود. rand() این مقدار توسط تابع

هسته های متفاوت، نتایج متفاوتی را تولید می کنند.

که در سومین اجرای برنامه استفاده شده seed توجه کنید که مقدار متغیر

در اجرای اول تولید شده بود. rand() 12345 ) اولین عددی است که توسط تابع )

در نتیجه اعداد اول تا هشتم که در اجرای سوم تولید شده با اعداد دوم تا نهم که در

اجرای اول تولید شده بود برابر است. همچنین دقت کنید که رشته اعداد تولید شده در

1 – Seed

 

 

120 برنامه سازی پیشرفته

4 است. این موضوع القا می کند ‐ اجرای دوم مانند رشته اعداد تولید شده در مثال 22

که مقدار پیش فرض هسته در این رایانه، عدد یک است.

این که مقدار هسته باید به طور محاوره ای وارد شود مشکلی است که با استفاده

زمان فعلی را بر حسب ثانیه نگه « ساعت سیستم 1 » . از ساعت سیستم حل می شود

تعریف شده زمان فعلی را به <ctime> که در سرفایل time() می دارد. تابع

برمی گرداند. این مقدار می تواند به عنوان هسته unsigned صورت یک عدد صحیح

استفاده شود. rand() برای تابع

4 کارگذاری هسته از ساعت سیستم ‐ * مثال 24

4 است با این فرق که هستۀ تولیدکنندۀ ‐ برنامۀ زیر، همان برنامۀ مثال 23

اعداد شبه تصادفی را با استفاده از ساعت سیستم تنظیم می کند.

را تشخیص نمی دهد، به جای آن <ctime> توجه : اگر کامپایلر شما سرفایل

استفاده کنید. <time.h> از سرفایل

#include <cstdlib>

#include <ctime> // defines the time() function

#include <iostream>

//#include <time.h> // use this if <ctime> is not recognized

int main()

{ // prints pseudo-random numbers:

unsigned seed = time(NULL); // uses the system clock

cout << "seed = " << seed << endl;

srand(seed); // initializes the seed

for (int i = 0; i < 8; i++)

cout << rand() << endl;

}

seed = 808148157

1877361330

352899587

1443923328

1857423289

1 – System timer

 

فصل چهارم / تکرار 121

200398846

1379699551

1622702508

715548277

seed = 808148160

892939769

1559273790

1468644255

952730860

1322627253

844657339

440402904

عدد صحیح 808,148,157 را برمی گرداند که به time() در اولین اجرا، تابع

عنوان هستۀ تولید کنندۀ اعداد تصادفی استفاده شده است. دومین اجرا 3 ثانیه بعد

عدد صحیح 808,148,160 را برمی گرداند که time() انجام شده، بنابراین تابع

این مقدار، رشته اعداد کاملا متفاوتی را تولید می کند.

انجام شده است: intel با پردازندۀ pc دو اجرای زیر روی یک

seed = 943364015

2948

15841

72

25506

30808

29709

13155

2527

seed = 943364119

17427

20464

13149

5702

12766

1424

16612

31746

در بیشتر برنامه های کاربردی، نیاز است که اعداد تصادفی در محدودۀ

مشخصی پخش شده باشند. مثال بعدی طریقۀ انجام این کار را نشان می دهد.

 

122 برنامه سازی پیشرفته

4 تولید اعداد تصادفی در یک محدودۀ مشخص ‐ * مثال 25

4 است به جز این که اعدادی که برنامۀ زیر تولید ‐ برنامۀ زیر مانند مثال 24

می کند در یک ناحیۀ مشخص محدود شده:

#include <cstdlib>

#include <ctime> // defines the time() function

#include <iostream>

//#include <time.h> // use this if <ctime> is not recognized

int main()

{ // prints pseudo-random numbers:

unsigned seed = time(NULL); // uses the system clock

cout << "seed = " << seed << endl;

srand(seed); // initializes the seed

int min, max;

cout << "Enter minimum and maximum: ";

cin >> min >> max; // lowest and highest numbers

int range = max - min + 1; // number of numbers in rsnge

for (int i = 0; i < 20; i++)

{ int r = rand()/100%range + min;

cout << r << " ";

}

cout << endl;

}

seed = 808237677

Enter minimum and maximum: 1 100

85 57 1 10 5 73 81 43 46 42 17 44 48 9 3 74 41 4 30 68

seed = 808238101

Enter minimum and maximum: 22 66

63 29 56 22 53 57 39 56 43 36 62 30 41 57 26 61 59 26 28

اولین اجرا 20 عدد صحیح تصادفی بین 1 و 100 تولید می کند. دومین اجرا 20

عدد صحیح که بین 22 و 66 گسترش یافته را تولید می نماید.

بر 100 تقسیم می شود تا دو رقم سمت rand() ابتدا مقدار for در حلقۀ

راست عدد تصادفی حذف شود زیرا این مولد به طور متناوب اعداد زوج و فرد تولید

 

 

 

 

فصل چهارم / تکرار 123

می کند. با حذف دو رقم سمت راست عدد تولید شده، این مشکل برطرف می شود.

range- اعداد تصادفی در محدودۀ 0 تا 1 rand()/100%range سپس عبارت

اعدادی تصادفی در rand()/100%range + min تولید نموده و عبارت

تولید می نماید. max تا min محدودۀ

124 برنامه سازی پیشرفته

پرسش های گزینه ای

1 – کدام یک از دستورات زیر، یک حلقه نیست؟

switch – ب while – الف

do..while – د for – ج

کدام گزینه صحیح است؟ while (false) i++; 2 – در مورد کد

بی نهایت می شود. i الف – حلقۀ فوق تا بی نهایت ادامه می یابد و مقدار

سرریز شود. i ب – حلقۀ فوق آن قدر ادامه می یابد تا این که

فقط یک واحد اضافه می شود. i ج – حلقۀ فوق فقط یک بار اجرا می شود و

د – حلقۀ فوق اصلا اجرا نمی شود.

برابر i از نوع صحیح و مقدار آن 5 باشد، پس از خاتمۀ حلقۀ زیر مقدار i 3 – اگر

While (i<10) i+= با کدام گزینه است؟ ; 2

الف – 10 ب – 11 ج – 9 د – 12

برابر n از نوع صحیح و مقدار آن 0 باشد، پس از خاتمۀ حلقۀ زیر مقدار n 4 – اگر

While (n< با کدام گزینه است؟ ( 5

{ if (n>3) break; n++; }

الف – 4 ب – 5 ج – 6 د – 3

برابر k از نوع صحیح و مقدار آن 5 باشد، پس از خاتمۀ حلقۀ زیر مقدار k 5 – اگر

do ؟ با کدام گزینه است

k++ while (k<5);

پاریز می شود. k – سرریز می شود د k – الف – 5 ب – 6 ج

6 – کدام گزینه صحیح نیست؟

حلقه را خاتمه می دهد. break الف‐ دستور

حلقه را خاتمه می دهد. exit( ب – دستور ( 0

حلقه را خاتمه می دهد. continue ج – دستور

د – غلط بودن شرط کنترل، حلقه را خاتمه می دهد.

for (j=0; true; j++) {…} ؟ 7 – حلقۀ مقابل چند بار تکرار می شود

 

 

فصل چهارم / تکرار 125

الف – اصلا تکرار نمی شود

ب – تا بی نهایت ادامه می یابد

ج – فقط یک بار تکرار می شود

د – اگر در بدنۀ حلقه، دستور خاتمۀ حلقه وجود نداشته باشد تا بی نهایت ادامه

می یابد.

چقدر است؟ k 8 – در پایان حلقه های مقابل مقدار

k = 0;

for (i=0; i<5; i++)

for (j=0; j<5; j++)

k++;

الف – 5 ب – 10 ج – 25 د – 50

9 – کدام گزینه صحیح است؟

دست کم یک بار اجرا می شود. do..while الف – حلقۀ

دست کم یک بار اجرا می شود. while ب – حلقۀ

دست کم یک بار اجرا می شود for ج – حلقۀ

دست کم یک بار اجرا می شوند. for و حلقۀ while د – حلقۀ

10 – در کدام حلقه، شرط کنترل حلقه در انتهای هر تکرار بررسی می شود؟

د – هیچ کدام for ج – حلقۀ do..while ب ‐ حلقۀ while الف – حلقۀ

11 – کدام حلقه نمی تواند تا بی نهایت ادامه یابد؟

د – هیچ کدام for ج – حلقۀ do..while ب – حلقۀ while الف – حلقۀ

12 – در مورد حلقه های تودرتو کدام عبارت صحیح است؟

فقط درونی ترین حلقه را خاتمه می دهد break الف – دستور

فقط بیرونی ترین حلقه را خاتمه می دهد break ب – دستور

فقط حلقه ای که این دستور در بدنۀ آن قرار دارد را خاتمه می دهد break ج – دستور

حلقه های درونی و بیرونی را یک جا خاتمه می دهد. break د – دستور

13 – کدام عبارت صحیح است؟

تبدیل کرد. do..while یا حلقۀ while را می توان به حلقۀ for الف – حلقۀ

تبدیل کرد. do..while یا حلقۀ while را نمی توان به حلقۀ for ب – حلقۀ

تبدیل کرد. while را فقط می توان به حلقۀ for ج – حلقۀ

 

 

126 برنامه سازی پیشرفته

تبدیل کرد. do..while را فقط می توان به حلقۀ for د – حلقۀ

قرار دهیم آنگاه: true 14 – اگر به جای شرط کنترل اجرای یک حلقه، عبارت

الف – حلقه اصلا اجرا نمی شود

ب – حلقه حتما تا بی نهایت ادامه می یابد

ج – تعداد تکرارها بستگی به دستورات بدنه دارد

د – کامپایلر خطا می گیرد

باشد آنگاه حلقۀ مقابل چند بار false با مقدار bool متغیری از نوع i 15 – اگر

while (!i) i=true; ؟ تکرار می شود

الف – اصلا اجرا نمی شود ب – یک بار اجرا می شود

ج – تا بی نهایت ادامه می یابد د – تا وقتی حافظه سرریز شود ادامه می یابد

در حلق هها چه کاری انجام می دهد؟ continue 16 – دستور

الف – حلقه را در همان محل خاتمه می دهد

ب – مابقی دستورات بدنۀ حلقه را نادیده گرفته و تکرار بعدی حلقه را آغاز می کند

ج – مابقی دستورات بدنۀ حلقه را نادیده گرفته و حلقه را خاتمه می دهد

د – تمام دستورات تکرار فعلی را اجرا نموده و سپس حلقه را خاتمه می دهد

کدام for یا مقداردهی اولیه در حلقۀ initializing 17 – در رابطه با بخش

عبارت صحیح نیست؟

الف – این بخش فقط یک بار ارزیابی می شود

ب – این بخش قبل از این که تکرارها آغاز شوند ارزیابی می شود

قید نشود for ج – این بخش می تواند در حلقۀ

تودرتو این بخش حذف می شود for د – در حلق ههای

 

فصل چهارم / تکرار 127

پرسش های تشریحی

یعنی صفر) ) false اگر شرط کنترل در ابتدا با مقدار while 1‐ در یک حلقۀ

مقداردهی شود، چه اتفاقی می افتد؟

قبل از حلقه اعلان گردد (به جای این که for 2‐ چه وقت باید متغیر کنترل در حلقۀ

داخل بخش کنترلی آن اعلان گردد)؟

چگونه باعث کنترل بهتر روی حلق هها می شود؟ break 3‐ دستور

4‐ حداقل تکرار در:

چقدر است؟ while الف ‐ یک حلقۀ

چقدر است؟ do..while ب ‐ یک حلقۀ

5‐ چه اشتباهی در حلقۀ زیر است؟

while (n <= 100)

sum += n*n;

6‐ چه خطایی در برنامۀ زیر است؟

int main()

{ const double PI;

int n;

PI = 3.14159265358979

n = 22;

}

چیست و چه فایده ای دارد؟ « حلقۀ بی پایان » ‐7

8‐ چطور می توان حلق های ساخت که با یک دستور در وسط بلوکش پایان یابد؟

9‐ چرا از به کارگیری متغیرهای ممیز شناور در مقایسه های برابری باید اجتناب شود؟

 

128 برنامه سازی پیشرفته

تمرین های برنامه نویسی

1‐ قطعه برنامۀ زیر را دنبال نمایید و مقدار هر متغیر را در هر گام مشخص کنید:

float x = 4.15;

for (int i=0; i < 3; i++)

x *= 2;

تبدیل کنید: while زیر را به حلقۀ for 2‐ حلقۀ

for (int i=1; i <= n; i++)

cout << i*i << " ";

3‐ خروجی این برنامه را توضیح دهید:

int main()

{ for (int i = 0; i < 8; i++)

if ( i%2 == 0) cout << i + 1 << "\t";

else if (i%3 == 0) cout << i*i << "\t";

else if (i%5 == 0) cout << 2*i - 1 << "\t";

else cout << i << "\t";

}

4‐ خروجی برنامۀ زیر را توضیح دهید:

int main()

{ for (int i=0; i < 8; i++)

{ if (i%2 == 0) cout << i + 1 << endl;

else if (i%3 == 0) continue;

else if (i%5 == 0) break;

cout << "End of program.\n";

}

cout << "End of program.\n";

}

5‐ برنامه ای نوشته و اجرا کنید که عددی را از ورودی گرفته و با استفاده از یک حلقۀ

مجموع مربعات اعداد متوالی تا آن عدد را پیدا کند. برای مثال اگر 5 وارد while

52 است. +42+32+22+ شود، برنامه مذکور عدد 55 را چاپ کند که معادل 12

نوشته و اجرا کنید. for 6‐ پاسخ سوال 5 را با یک حلقۀ

 

فصل چهارم / تکرار 129

نوشته و اجرا کنید. do..while 7‐ پاسخ سوال 5 را با یک حلقۀ

8‐ برنامه ای را نوشته و اجرا کنید که اعمال تقسیم و باقیمانده را بدون استفاده از

عملگرهای / و % برای تقسیم اعداد صحیح مثبت پیاده سازی می کند.

9‐ برنامه ای را نوشته و اجرا کنید که ارقام یک عدد مثبت داده شده را معکوس

می کند. (به تمرین 13 فصل سوم نگاه کنید)

10 ‐ برنامه ای بنویسید که ریشۀ صحیح یک عدد داده شده را پیدا کند. ریشۀ صحیح،

بزرگ ترین عدد صحیحی است که مربع آن کوچ کتر یا مساوی عدد داده شده باشد.

11 – با استفاده از الگوریتم اقلیدس، بزرگ ترین مقسوم علیه مشترک دو عدد صحیح

را به زوج (m,n) داده شده را بیابید. این الگوریتم به وسیلۀ تقسیم های متوالی، زوج

تبدیل می کند. به این صورت که عدد صحیح بزرگ تر را بر عدد کوچک تر (n,0)

تقسیم کرده و سپس به جای عدد بزرگ تر، عدد کوچ کتر را قرار می دهد و به جای

عدد کوچک تر، باقیمانده تقسیم را قرار م یدهد و دوباره تقسیم را روی این زوج جدید

تکرار می کند. وقتی باقیمانده برابر با صفر شود، عدد دیگر از آن زوج، بزرگ ترین

مقسوم علیه مشترک دو عدد صحیح اولیه است (و همچنین بزرگ ترین مقسو معلیه

برابر با 112 باشد، n برابر با 532 و m مشترک تمام زوج های میانی). برای مثال اگر

الگوریتم اقلیدس زوج ( 532,112 ) را به ترتیب زیر به زوج ( 28,0 ) تبدیل

می کند:

(532,112) 􀃖 (112,84) 􀃖 (84,28) 􀃖 (28,0).

برنامه ای بنویسید که با استفاده از الگوریتم اقلیدس، بزر گترین مقسوم علیه مشترک دو

عدد صحیح داده شده را بیابد.

 

   + MOHSEN GHASEMI - ۱۱:۳٦ ‎ب.ظ ; ۱۳۸٩/٥/۱۸