مجموعه آموزشی پی استور - https://programstore.ir

دستورات حلقه و تکرار در ++C

در این جلسه از سری آموزش های برنامه نویسی ++C [1] در مورد دستورات حلقه و تکرار در ++C صحبت خواهیم کرد. تكرار، اجرای پی در پی یك دستور یا بلوكی از دستورالعمل‌ها در یك برنامه است. با استفاده از تکرار می‌توانیم کنترل برنامه را مجبور کنیم تا به خطوط قبلی برگردد و آن‌ها را دوباره اجرا نماید. C++ دارای سه دستور تكرار است: دستور while، دستور do_while و دستور for. دستور‌های تکرار به علت طبیعت چرخه‌مانندشان‌، حلقه‌ نیز نامیده می‌شوند.

دستور while در ++C

در ابتدای جلسه دستورات حلقه و تکرار در ++C ، نحو یا syntax دستور while بیان می شود:

while (condition) statement;

به جای condition [3]، یك شرط قرار می‌گیرد و به جای statement دستوری که باید تکرار شود قرار می‌گیرد. اگر مقدار شرط، صفر (یعنی نادرست) باشد، statement نادیده گرفته می‌شود و برنامه به اولین دستور بعد از while پرش می‌كند. اگر مقدار شرط ناصفر (یعنی‌ درست) باشد، statement اجرا ‌شده و دوباره مقدار شرط بررسی می‌شود. این تکرار آن قدر ادامه می‌یابد تا این که مقدار شرط صفر شود.

مثال: محاسبۀ حاصل جمع اعداد صحیح متوالی با حلقۀ while : این برنامه مقدار 1 + 2 + 3 + … + n را برای عدد ورودی n محاسبه می‌كند:

#include <iostream>
using namespace std;

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;
 return 0;
}

این دستور با استفاده از حلقه while تا زمانی که شرط توقف برآورده نشده ادامه پیدا می کند. در مثال بالا با اجرای برنامه متوجه خواید شد که با ورودی عدد 10 جمع اعداد 1 تا 10 یعنی 55 را برای ما محاسبه می کند.

خاتمه دادن به یک حلقه در ++C

قبلا‌ دیدیم كه چگونه دستور break برای كنترل دستورالعمل switch استفاده می‌شود (جلسه سوم : دستورات شرطی [4]). از دستور break برای پایان دادن به حلقه‌ها نیز می‌توان استفاده کرد. یكی از‌ مزیت‌های دستور break این است كه فوراً حلقه را خاتمه می‌دهد بدون این که مابقی دستورهای درون حلقه اجرا شوند.

مثال: 

#include <iostream>
using namespace std;

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;
 return 0;
}

مثال اعداد فیبوناچی

در ادامه دستورات حلقه و تکرار در ++C مثال اعداد فیبوناچی را داریم. اعداد فیبوناچی …, 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

برنامۀ زیر، همۀ اعداد فیبوناچی را تا یك محدودۀ مشخص که از ورودی دریافت می‌شود، محاسبه و چاپ می‌كند:

#include <iostream>
using namespace std;

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;
   }
}

مثال استفاده از تابع (exit(0

تابع (exit(0 روش دیگری برای خاتمه دادن به یك حلقه‌ است. هرچند که این تابع بلافاصله اجرای کل برنامه را پایان می‌دهد:

#include <iostream>
using namespace std;

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 برای خاتمه دادن به حلقه‌های نامتناهی استفاده کنند زیرا قابلیت انعطاف بیشتری دارد.

متوقف کردن یك حلقۀ نامتناهی در ++C

با فشردن کلیدهای Ctrl+C سیستم عامل یک برنامه را به اجبار خاتمه می‌دهد. كلید Ctrl را پایین نگه داشته و كلید C روی صفحه‌كلید خود را فشار دهید تا برنامۀ فعلی خاتمه پیدا کند.

دستور do while در ++C

ساختار do..while روش دیگری برای ساختن دستورات حلقه و تکرار در ++C است نحو آن به صورت زیر است:

do statement while (condition);

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

دستور‌ do..while مانند دستور while است. با این فرق كه شرط کنترل حلقه به جای این که در ابتدای حلقه ارزیابی گردد، در انتهای حلقه ارزیابی می‌شود.
یعنی هر متغیر كنترلی به جای این كه قبل از شروع حلقه تنظیم شود، می‌تواند درون آن تنظیم گردد. نتیجۀ دیگر این است كه حلقۀ do..while همیشه بدون توجه به مقدار شرط كنترل، لااقل یك بار اجرا می‌شود اما حلقۀ while می‌تواند اصلا اجرا نشود.

مثال: محاسبۀ حاصل جمع اعداد صحیح ‌متوالی با حلقۀ do..while‌

#include <iostream>
using namespace std;

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;
}

مثال: اعداد فاكتوریل

اعداد فاكتوریل 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

برنامۀ زیر همۀ‌ اعداد فاكتوریل را که از عدد داده شده کوچک‌ترند، چاپ می‌کند:

#include <iostream>
using namespace std;

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 (i < bound);
}

دستور for در ++C

نحو یا syntax دستورالعمل for در دستورات حلقه و تکرار در ++C به صورت زیر است:

for (initialization; condition; update) statement;

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

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

  1. ارزیابی عبارت initialization
  2. بررسی شرط condition . اگر نادرست باشد، حلقه خاتمه می‌یابد.
  3. اجرای statement
  4. ارزیابی عبارت update
  5. تکرار گام‌های 2 تا 4

عبارت‌های initialization و condition و update عبارت‌های اختیاری هستند. یعنی می‌توانیم آن‌ها را در حلقه ذکر نکنیم.

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

#include <iostream>
using namespace std;

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 برای یك متغیر دیگر استفاده نمود.

مثال: یك حلقۀ for نزولی – برنامۀ زیر‌ ده عدد صحیح مثبت را به ترتیب نزولی چاپ می‌كند:

#include <iostream>
using namespace std;

int main()
{  for (int i=10; i > 0; i--)
      cout << " " << i;
}

مثال: بیشتر از یك متغیر كنترل در حلقۀ for – حلقۀ for در برنامۀ زیر دو متغیر كنترل دارد:

#include <iostream>
using namespace std;

int main()
{  
    for (int m=95, n=11; m%n > 0; m -= 3, n++)
      cout << m << "%" << n << " = " << m%n << endl;
}

مثال: حلقه‌های for تودرتو – برنامۀ زیر یك جدول ضرب چاپ می‌كند:

#include <iomanip>    
#include <iostream>

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;
   }
}

دستور break در ++C

دستور break یک دستور آشناست. قبلاً از آن برای خاتمه دادن به دستور switch و همچنین حلقه‌های while و do..while استفاده کرده‌ایم. از این دستور برای خاتمه دادن به حلقۀ for نیز می‌توانیم استفاده کنیم. دستور break در هر جایی درون حلقه می‌تواند جا بگیرد و در همان جا حلقه را خاتمه دهد.
وقتی دستور break درون حلقه‌های تودرتو استفاده شود، فقط روی حلقه‌ای که مستقیماً درون آن قرار گرفته تاثیر می‌گذارد. حلقه‌های بیرونی بدون هیچ تغییری ادامه می‌یابند.

دستور continue در ++C

دستور break بقیۀ دستورهای درون بلوك حلقه را نادیده گرفته و به اولین ‌‌دستور بیرون حلقه پرش می‌كند. دستور continue نیز شبیه همین است اما به جای این که حلقه را خاتمه دهد، اجرا را به تكرار بعدی حلقه منتقل می‌كند. این دستور، ادامۀ چرخۀ فعلی را لغو کرده و اجرای دور بعدی حلقه را آغاز می‌کند.

مثال: استفاده از دستورهای break و continue – این برنامۀ كوچك،‌ دستورهای break و continue را شرح می‌دهد:

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;
}

دستور goto در ++C

دستور goto نوع دیگری از دستورات حلقه و تکرار در ++C است. مقصد این پرش توسط یك برچسب معین می‌شود. برچسب شناسه‌ای است كه جلوی آن علامت كولن ( : ) می‌آید و جلوی یك دستور دیگر قرار می‌گیرد. یک مزیت دستور goto این است که با استفاده از آن می‌توان از همۀ حلقه‌های تودرتو خارج شد و به مکان دلخواهی در برنامه پرش نمود.

مثال: استفاده از دستور goto برای خارج شدن از حلقه‌های تودرتو

#include <iostream>

using namespace std;

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;   
   }
}

تولید اعداد تصادفی در ++C

یكی از كاربردهای بسیار مهم کامپیوترها، «شبیه‌سازی»‌ سیستم‌های دنیای واقعی است. تحقیقات و توسعه‌های بسیار پیشرفته به این راهکار خیلی وابسته است. به وسیلۀ شبیه‌سازی می‌توانیم رفتار سیستم‌های مختلف را مطالعه کنیم بدون این که لازم باشد واقعا آن‌ها را پیاده‌سازی نماییم. در شبیه‌سازی نیاز است «اعداد تصادفی» توسط کامپیوتر‌ها تولید شود تا نادانسته‌های دنیای واقعی مدل‌سازی شود.

کامپیوتر‌ها «ثابت‌کار» هستند یعنی با دادن داده‌های مشابه به کامپیوتر‌های مشابه، همیشه خروجی یکسان تولید می‌شود. با وجود این می توان اعدادی تولید کرد که به ظاهر تصادفی هستند؛ اعدادی که به طور یکنواخت در یک محدودۀ خاص گسترده‌اند و برای هیچ‌کدام الگوی مشخصی وجود ندارد. چنین اعدادی را «اعداد شبه‌تصادفی» می‌نامیم.

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

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

using namespace std;

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 گسترده شده‌اند.‌ AND_MAX در این کامپایلر برابر با 2,147,483,647 است.  هر عدد شبه‌تصادفی از روی عدد قبلی خود ساخته می‌شود. اولین عدد شبه‌تصادفی از روی یك مقدار داخلی که «هسته» گفته می‌شود ایجاد می‌گردد.
هر دفعه که برنامه اجرا شود، هسته با یک مقدار پیش‌فرض بارگذاری می‌شود. برای حذف این اثر نامطلوب که از تصادفی بودن اعداد می‌کاهد، می‌توانیم با استفاده از تابع ()srand خودمان مقدار هسته را انتخاب کنیم.

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

using namespace std;


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;
}

مثال بالا كارگذاری هسته به طور محاوره‌ای است. این برنامه مانند برنامۀ قبلی است بجز این كه می‌توان هستۀ تولیدکنندۀ اعداد تصادفی را به شکل محاوره‌ای وارد نمود.