مقدمه:
آموزش حلقه ها در C++ چه فایده ای دارد؟
حلقه ها در C++ در موقعی استفاده میگردد که: نیاز داریم یک دستور بخصوص یا مجموعه ی از دستورات بیش از یک بار تکرار شود.
به عنوان مثال میخواهیم جملهی Hello world را 4 بار چاپ کنیم. شاید راه حل ابتدایی به ذهنمان برسد عمل کردن به شکل زیر باشد:
int main(){
std::cout<<”Hello world”<<std::endl;
std::cout<<”Hello world”<<std::endl;
std::cout<<”Hello world”<<std::endl;
std::cout<<”Hello world”<<std::endl;}
این روش اگرچه کمی خسته کننده و زمانبر به نظر میرسد، اما امکانپذیر است.اما چه اتفاقی می افتد اگر بخواهیم این دستور را 100 بار یا به تعداد نامشخص n بار تکرار کنیم؟ قطعا نوشتن یک قطعه کد به تعداد دفعات 100 یا n بار راه حل مناسبی نیست.
در برنامهنویسی با زبان C++, استفاده از حلقهها امکان اجرای تکراری دستورات را فراهم میآورد، که این امر برای مواردی چون پردازش دادهها، ایجاد رابط کاربری داینامیک و بسیاری از کاربردهای دیگر ضروری است.
در این مقاله، به آموزش حلقه ها در C++ میپردازیم و نحوه استفاده از آنها را بررسی میکنیم.
ساختار تشکیل دهنده حلقه ها در C++ :
اصولا هر حلقه شامل دو بخش اصلی است:
- شرط خروج از حلقه: که به وسیله آن تعیین میکنیم که دستورات درون بدنهی حلقه چندبار باید تکرار شود یا به بیان بهتر، تکرار اجرای دستورات درون حلقه تا چه مدت باید ادامه داشته باشد.
- بدنه ی حلقه: شامل دستورات مورد نظر که قرار است به تعدادی که برنامه نویس میخواهد تکرار شوند.
حلقه ها در دوره ۰ تا ۹۹ مبانی کامپیوتر و برنامه نویسی به طور کامل برای شما آموزش داده شده است. برای مشاهده این دوره کلیک کنید.
انواع حلقه ها در C++ :
به طور کلی دو نوع آموزش حلقه ها در C++ وجود دارد:
1) حلقه هایی که در آن ها قبل از ورود به حلقه شرط ورود به حلقه چک میشود و اگر شرط درست باشد، وارد حلقه شده و دستورات داخل آن اجرا میشود. در این نوع حلقه ها ورود به حلقه و اجرای دستورات آن فقط در صورتی که انجام میشود که شرط در ابتدای کار درست باشد در غیر اینصورت هرگز ورود به حلقه در برنامه اتفاق نمی افتد؛ و در نتیجه دستورات آن اجرا نمیشوند. در c++ حلقه ی for و while از این نوع میباشند.
2) حلقه هایی که در آنها شرط حلقه در انتهای حلقه بررسی میشود. با این تفسیر دستورات داخل حلقه حتی اگر شرط آن برقرار نباشد حداقل یکبار اجرا میشوند.
در c++ حلقه ی do-while از این نوع میباشد.
در زبان c++ چند حلقه ی مختلف وجود دارد که کاربرد هرکدام را به تفکیک بررسی میکنیم.
حلقه ی for
اولین حلقه ها در C++ حلقه for است. برای زمانی که دقیقا میدانیم یک دستور چند بار قرار است تکرار شود.اگرچه که میتوان از while و یا do-while نیز استفاده کرد. اما در این شرایط حلقه ی for همیشه به آنها ترجیح داده میشود.
for (شمارنده ;بررسی شرط ;تغییر مقدار شمارنده )
{
// بدنه حلقه
}
تعریف و مقداردهی به شمارنده: در این بخش شمارنده ی مربوط به حلقه را تعریف و مقداردهی میکنیم.دقت کنید که نوع داده ی شمارنده همیشه از جنس یک عدد صحیح (int) است.
بررسی شرط: در این قسمت شرط برای ورود به حلقه و یا ادامه تکرار دستورات حلقه بررسی می شود. اگر از ابتدا شرط برقرار نباشد، هرگز وارد حلقه نمیشویم و یا اگر حلقه در حال اجرا باشد و ناگهان دیگر شرط برقرار نباشد(مثلا رسیدن مقدار شمارنده به حد نساب)، اجرای حلقه خاتمه میابد و روند اجرای کد به اولین دستور پس از حلقه منتقل میشود.
تغییر مقدار شمارنده: پس از هربار اجرای حلقه مقدار شمارنده باید بروزرسانی شود. شمارنده ی حلقه میتواند افزایشی یا کاهشی باشد.
بدنه ی حلقه: در این بخش دستوراتی قرار میگیرند که باید تکرار شوند.
نکات مهم:
*بخش های مختلف داخل حلقه ی for باید توسط “سیمیکالم ;” از یکدیگر جدا شوند.
*درصورتی که دستور متعلق به بدنه ی حلقه یکی باشد، دیگر نیازی به {} نداریم،به عبارتی بیش از یک دستور را مجبوریم داخل {} تعریف کنیم.
*شمارنده ی داخل حلقه را میتوان در بیرون از حلقه تعریف اولیه کرد. و در داخل حلقه فقط به آن مقداردهی صورت بگیرد. اما تفاوت آن در این است که وقتی شمارنده را داخل حلقه تعریف میکنیم. درواقع در حال ایجاد یک متغیر محلی هستیم، به این معنا که وقتی کامپایلر وارد حلقه میشود متغیر شمارنده در حافظه ایجاد شده و وقتی از حلقه خارج میشود،ازبین میرود. به این ترتیب در مصرف حافظه صرفه جویی میشود.
ضمن اینکه وقتی شمارنده را به صورت محلی تعریف میکنیم،مجاز به تعریف متغیر دیگر با همان نام در جای دیگر از کد هستیم.
برای مثال:
for(int i = 0; i < 4; i++)
{
std::cout << “Hello World\n”;
}
تعریف همزمان چندین شمارنده برای حلقه ی for :
حلقه ی for میتواند به طور همزمان چندین شمارنده و یا بیش از یک شرط برای ادامه ی حلقه داشته باشد . دراین صورت شمارنده ها و شروط مختلف را توسط( , ) از یکدیگر جدا میکنیم
for(int i=0,j=2,k=3;i<10,j<20,k<15;i++,j+=2,k+=3){
// code to be executed
}
همچنین شرط داخل حلقه میتواند یک عبارت (expression ) باشد،در این صورت به هنگام بررسی شرط حلقه عبارت مورد نظر محاسبه شده و سپس شرط بررسی میشود:
for(int i=0,j=2;i+j%2==0;i++,j+=2){
// code to be executed
}
حذف بخش های مختلف حلقه ی for:
در داخل حلقه ی for در C++ میتوانیم بسته به شرایط هر یک از سه بخش ذکر شده را حذف کنیم.
حذف شمارنده:
به طور مثال زمانی که شمارنده در بیرون از حلقه تعریف و مقداردهی میشود.
int i=10;
for(;i<50;i+=2){
// code to be executed
}
حذف شرط خروج از حلقه:
به طور مثال زمانی که شرط خروج از حلقه در داخل بدنه ی حلقه بررسی میشود(عموما به کمک if ).
نکته: در این صورت باید توجه داشته باشید که به هنگام بررسی شرط حتما از دستور break برای خروج از حلقه استفاده کنید،در غیر اینصورت وارد یک حلقه ی بینهایت (infinite loop) میشویم.
for(int i=0;;i++){
if(i+2>100)
break;
else{
//code to be executed
}
}
حذف بخش مربوط به تغییر مقدار شمارنده:
به طور مثال زمانی که تغییر مقدار شمارنده در بدنه حلقه اتفاق می افتد.
for(int i=0;i<10;)
{
//code to be executed
i+=3;
}
لازم به ذکر است که در حذف هرکدام از بخش های حلقه حق نداریم ; را درون حلقه حذف کنیم،یعنی در هرصورت ; در داخل هر حلقه ی for به تعداد 3 بار تکرار میشود حتی اگر یک یا چند بخش از حلقه را حذف کرده باشیم.
کاربرد های حلقه ی for :
همانطور که پیش تر اشاره شد از حلقه ی for عمدتا زمانی استفاده میکنیم که دقیقا میدانیم دستورات بدنه ی حلقه چندبار قرار است تکرار شوند. به عنوان مثال برای حرکت کردن و انجام عملیات بخصوص روی عناصر یک بلاک داده که تعداد آن مشخص است. مثل آرایه یا وکتور. برای دسترسی به عناصر یک آرایه یا وکتور از طریق حلقه ی for دو روش کلی وجود دارد:
- روش معمول :
for(int i=0;i<100;i++){
//code to be executed
}
- استفاده از حلقه ی foreach: این نوع حلقه ی for که در نسخه ی c++11 معرفی شد. به منظور حرکت دادن حلقه بر روی یک محدوده ی بخصوص استفاده میشود.
for( نوع دادهelement: نام بلاک داده ){
//code to be executed
}
نوع داده: در این بخش باید نوع داده ای را قرار دهیم که در بلاک داده ذخیره شده است. به طور مثال اگر یک آرایه از اعداد صحیح داشته باشیم باید نوع داده ی int و اگر از جنس عدد اعشاری باشد از نوع داده ی float استفاده میکنیم.
نام بلاک داده: در این قسمت باید نام بلاک داده ای را بنویسیم که در بدنه ی حلقه در حال خواندن داده ها از آن هستیم.
element :این بخش که در واقع یک نام برای متغیر است. و میتوان به دلخواه هر نامی برای آن در نظر گرفت. نماینده ای برای تک تک عناصر داخل بلاک داده است.
به زبان خیلی ساده قبل از نماد (:) نوع داده ای که قرار است خوانده شود را ذکر میکنیم و در ادامه مشخص میکنیم که این اطلاعات از کجا قرار است خوانده شوند.
int arr[10]={1,2,3,4,5,6,7,8,9,1};
for(int element:arr){
std::cout<<element<<”\t”;
}
مثال) فرض کنید میخواهید در یک آرایه یک بعدی مقادیر خانه هایی که در آرایه اندیس فرد دارند را دوبرابر کنید:
int arr[10];
for(int i=1;i<10;i+=2){
arr[i]=arr[i]*2;
}
۲- حلقه while:
شاید پر کاربرترین حلقه ها در C++ حلقه while باشد. در استفاده از حلقه ی for دیدیم که تعداد دفعات تکرار دستورات را میدانیم. اما گاهی پیش می آید که به طور دقیق نمیدانیم دستورات حلقه چندبار قرار است تکرار شوند، در اینجا از حلقه ی while استفاده میکنیم.
اگر میخواهید حلقه while و نحوه کار با این حلقه را یاد بگیرید به دوره مبانی کامپیوتر و برنامه نویسی مراجعه کنید.
while(condition){
//code to be executed (بدنه ی حلقه)
}
condition : در این قسمت شرطی را تعریف میکنیم که اجرای دستورات حلقه تا زمانی ادامه دار خواهد بود که این شرط همچنان برقرار (true) باشد.
بدنه ی حلقه: در این بخش دستوراتی قرار میگیرند که باید تکرار شوند.
این حلقه برای زمانی کاربرد دارد که دیگر تعداد دفعات تکرار دستورات برای ما اهمیتی ندارد. به عبارتی تکرار دستورات باید تا زمانی ادامه یابد تا یک شرط بخصوص (شرطی که برای خروج از حلقه تعریف کرده ایم) برقرار شود.
۳- حلقه do-while:
عملکرد و کاربرد آن دقیقا مشابه حلقه ی while است.
do{
// code to be exected (بدنه ی حلقه)
}while(condition);
تنها تفاوت آن با حلقه ی while در این است که در حلقه ی while ابتدا شرط حلقه چک شده و سپس دستورات بدنه اجرا میشوند. اما در حلقه ی do-while ابتدا دستورات بدنه اجرا شده و سپس شرط خروج از حلقه بررسی میشود. بنابراین دستورات حلقه ی do-whie حداقل یکبار اجرا میشوند. حتی اگر شرط حلقه برقرار نباشد.
حلقه ی بینهایت(infinite loop )
زمانی اتفاق می افتد که شرط حلقه برای همیشه برقرار (true ) باشد.در این صورت دستورات حلقه به شکل بینهایت بار تکرار میشوند. به بیان عامیانه کامپایلر درون حلقه گیر میکند و راهی برای خروج از آن ندارد.
مثال هایی از حلقه های بینهایت:
for(;;){} / for(;true;){} / for(;1==1;){}
while(1) / while(true)
do{} while(1) / do {} while(true)
برای جلوگیری از ایجاد چنین مشکلی (که عموما برنامه نویسان تازه کار با آن روبرو میشوند)بایستی به هنگام تعریف حلقه به شرط خروج از حلقه و تغییر مقدار شمارنده(کاهشی یا افزایشی) توجه کنیم.
نکته:اجرای حلقه ی بینهایت تا زمانی اتفاق می افتد که سیستم عامل برنامه را با یک ارور متوقف کند. اما برای متوقف کردن آن به صورت دستی در محیط ترمینال میتوانید از دستور ctrl+c استفاده کنید.
۴- حلقه های تودرتو(nested loops )
منظور از حلقه های تودرتو وجود حلقه هایی است که داخل حلقه های دیگر وجود دارند.
int j=5;
for(int i=0;i<100;i++){
while(j<50){
// body of the loop
}
}
چه زمانی نیاز به استفاده از حلقه های تودرتو داریم؟
اصولا این نوع حلقه ها برای زمانی کاربرد دارند که بخواهیم به ازای هر یک بار که حلقه ی بیرونی اجرا میشود. دستوراتی بیش از یکبار در داخل حلقه تکرار شود. مثلا برای دسترسی به عناصر یک آرایه یا وکتور دوبعدی یا چندبعدی که به ازای هر بعد آنها نیاز به یک حلقه داریم(برای دوبعد به دو حلقه و برای سه بعد به سه حلقه نیاز داریم).قطعه کد زیر خواندن اطلاعات از صفحه کلید برای یک آرایه دوبعدی به وسیله ی دو حلقه ی تودرتو را نشان میدهد.
int arr[10][5];
for(int i=0;i<10;i++){
for(int j=0;j<5;j++){
std::cin<<arr[i][j];
}
}
گردآوری کننده : هانیه اکرمی
برای اطلاع از تخفیف های جزوه جو میتوانید اینستاگرام ما را دنبال کنید.