Циклуси (while, do-while, for)

Циклусите овозможуваат повторување на група од наредби одреден број пати (на пример, додека n<10). Во C++, постојат три типа на циклуси: while, do-while и for.

Исказ while

while исказот е наједноставниот тип на циклус кој го нуди програмскиот јазик C++. Во продолжение е дадена синтаксата на овој исказ:

while (uslov)
     naredba;

Слично како и исказот if, while очекува програмерот да дефинира услов кој треба да биде задоволен (uslov) и наредба naredba (или блок од наредби '{ ... }') кои треба да бидат извршени кога ќе биде задоволен тој услов. Но, за разлика од if, while ќе ги извршува наредбите континуирано: сé додека условот има вредност true. Да разгледаме еден пример:

Програма 11.1

#include <iostream>
using namespace std;

int main()
{
      int i = 1;
      int s = 0;
      
      while (i <= 5)
      {
            cout << "Dodavam " << i << "." << endl;
            s = s + i;
            
            i++;                                        //zgolemi go i
      }
      
      //1+2+3+4+5 = 15
      cout << "Zbir: " << s << endl;                    //pechati 'Zbir: 15'
      
      return 0;
}

На почеток, променливите i и s ги добиваат вредностите 1 и 0, соодветно. Потоа, бидејќи условот (1<=5) е задоволен, ќе се извршат неколкуте наредби дадени во блокот на while циклусот (ќе се отпечати "Dodavam 1.", вредноста на s ќе се зголеми за вредноста i=1 и, потоа, ќе се зголеми вредноста на i). Сега, наместо да заврши извршувањето на овие наредби и програмата да продолжи понатаму, повторно се врши проверка на while условот. Бидејќи тој (2<=5) е задоволен, програмата повторно ги извршува наредбите од while блокот (печати "Dodavam 2.", го зголемува s за вредноста i=2 и ја зголемува вредноста на i). Блокот од наредби ќе се изврши уште три пати (за i=3, i=4 и i=5), по што условот (6<=5) нема да биде задоволен (6<=5 има вредност false) и циклусот ќе заврши. На крај, програмата ја печати вредноста на променливата s - која претставува збир на првите 5 природни броеви 1+2+3+4+5=15.

Доколку уште при првата проверка условот uslov има вредност false, наредбите нема да бидат извршени ниту еднаш. На пример, во програмата дадена погоре, доколку на почетокот променливата i добиеше вредност 10, со што условот (10<=5) во while циклусот не би бил задоволен ниту еднаш, програмата немаше да ги изврши наредбите од while блокот и ќе отпечатеше "Zbir: 0".

Никогаш не заборавајте, во while блокот, да ја ажурирате променливата/променливите која е дел од while условот. Во спротивно, програмата постојано ќе извршува едни исти наредби и никогаш нема да заврши. Ваша обврска е да предизвикате, во одреден момент, неисполнување на while условот. Во програмата дадена погоре, тоа се прави преку зголемување на вредноста на променливата i. Бидејќи i е вклучена во условот uslov (i<=5), во одреден момент (кога i ќе добие вредност поголема од 5), циклусот ќе заврши со извршување.

Следнава програма демонстрира некои од работите кои ги дискутиравме погоре:

Програма 11.2

#include <iostream>
using namespace std;

int main()
{
      int z = 10;
      while (z < 5)
      {
            cout << "Ova nema nikogash da se izvrshi." << endl;
      }
      
      z = 6;
      while (z >= 1)
      {
            cout << z << ", ";
            z--;
      }
      
      cout << "KRAJ NA NATPREVAROT." << endl;
      //izlez: 6, 5, 4, 3, 2, 1, KRAJ NA NATPREVAROT.
      
      z = 100;
      while (z < 1000)
      {
            //bidejki 'z' ne go azurirame nikade, uslovot
            //(z < 1000) kje bide sekogash zadovolen
            
            //naredbite kje se izvrshuvaat se dodeka ne ja ubieme
            //programata - na primer, so pomosh na
            //alatkite koi gi nudi Operativniot Sistem
            cout << z << endl;
      }
      
      return 0;
}

Исказ do-while

Понекогаш сакаме, различно од она што го нуди while циклусот, да гарантираме извршување на одредена наредба (или блок од наредби) најмалку еднаш (на пример, да печатиме мени). Во C++, ова е овозможено со исказот do-while:

do
     naredba;
while (uslov);

Притоа, наредбата naredba (или блокот од наредби кои евентуално би се наоѓал на нејзино место) ќе биде извршена најмалку еднаш. По извршувањето на naredba, програмата го проверува условот uslov и зависно од неговата вредност (true/false), се завршува циклусот (доколку условот не е исполнет) или се продолжува со извршување на наредби.

Следнава програма го илустрира кажаното:

Програма 11.3

#include <iostream>
using namespace std;

int main()
{
      int n;
      
      do
      {
            cout << "Vnesi pozitiven broj: ";
            cin >> n;
      }
      while (n <= 0);
      
      return 0;
}

Програмата очекува корисникот да внесе еден позитивен цел број (чија вредност се запишува во променливата n). Сé додека корисникот не внесе позитивен број (т.е. додека n<=0), програмата ќе печати "Vnesi pozitiven broj: " и ќе го чита целиот број кој го внесол корисникот.

Исказот do-while, најчесто, се употребува кога условот од кој зависи повторното извршување на циклусот зависи од податоци кои се читаат/пресметуваат во самиот блок од наредби; и проверката на вредноста на условот нема смисла без тие податоци.

Исказ for

Доколку знаете точно колку пати треба да се изврши одредена наредба или група од наредби, тогаш исказот for е најдоброто решение за креирање на циклус. Ова е убедливо најкористениот исказ за овозможување повеќекратно извршување на наредби (се користи многу почесто од while и do-while). Во продолжение следува основната синтакса на for исказот, како и објаснување на чекорите кои се извршуваат од страна на програмата:

for(inicijalizacija; uslov; promeni)
       naredba;

Чекорите кои се извршуваат од страна на програмата се:

  1. Се извршува наредбата/наредбите inicijalizacija (тука најчесто се декларираат и иницијализираат променливите кои се користат во uslov - на пример, int i=0 или int i=0, j=5)
  2. Се проверува точноста на uslov. Доколку uslov има вредност false, циклусот завршува и програмата продолжува со извршување на наредбите кои следат по циклусот. Доколку uslov има вредност true, тогаш програмата ја извршува наредбата naredba (или блокот од наредби кој се наоѓа на нејзино место).
  3. Се извршува наредбата/наредбите promeni (тука најчесто се ажурираат променливите кои се декларирани во inicijalizacija - на пример, i++ или i++, j--). Потоа, се оди назад на чекор 2.

Следната програма ги демонстрира можностите на исказот for:

Програма 11.4

#include <iostream>
using namespace std;

int main()
{
      //ispechati gi broevite od 1 do 10
      for (int i=1; i<=10; i++)
            cout << i << endl;
      
      //presmetaj zbir na broevite od 1 do 1000
      //koi se delivi so 2 ili 5
      int s = 0;
      for (int i=1; i<=1000; i++)
      {
            if ((i%2 == 0) || (i%5 == 0))
                  s += i;
      }
      
      cout << "Zbirot e: " << s << endl;
      
      //sledniot del kje otpechati ('0 10', '2 7', '4 4')
      for (int i=0, j=10; i<=j; i+=2, j-=3)
      {
            cout << i << " " << j << endl;
      }
      
      //site 3 parametri (inicijalizacija, uslov i promeni)
      //se nezadolzitelni
      int ii=0, kk=10;
      for ( ;ii<kk; )
      {
            cout << ii << endl;

            //mora da go azurirame 'ii'
            ii++;
      }
      
      return 0;
}

Од примерот даден погоре се гледа дека сите три параметри (inicijalizacija, uslov и promeni) се незадолжителни (може да останат празни). Во секој случај, знакот ';' мора да се запише помеѓу нив. На пример, доколку одлучиме да не го зададеме параметарот promeni, мора да напишеме for(inicijalizacija;uslov; ), доколку не го зададеме параметарот inicijalizacija, мора да напимеше for (; uslov; promeni), итн.

Многу често, потребно е да извршиме повеќе од една наредба во делот promeni. Ова можеме да го направиме така што наредбите ќе ги одделиме со знакот ',' (за кој веќе зборувавме во делот за оператори).

Наредби break и continue

Понекогаш сакаме, во зависност од тоа дали е задоволен одреден услов, да завршиме со извршување на циклус наредби или да прескокнеме дел наредби од циклусот.

Наредбата break ни овозможува да излеземе од определен циклус иако не е задоволен условот uslov (или, евентуално, не е ни дефиниран таков услов):

Програма 11.5

#include <iostream>
using namespace std;

int main()
{
      int s = 0;
      
      for (int i=0; i<10; i++)
      {
            if (i == 6)
                  break;
            
            s = s + i;
      }
      
      //0+1+2+3+4+5 = 15
      cout << s << endl;              //pechati '15'
      
      return 0;
}

Програмата дадена погоре печати 15 бидејќи тоа е збирот на броевите од 0 до 5. Иако во условот на for циклусот e дефинирано дека тој треба да се изврши за сите броеви од 0 до 9 (9 < 10), програмата ќе ги собере (во променливата s) само броевите од 0 до 5. Циклусот ќе заврши со извршување кога променливата i ќе добие вредност 6: во тој момент, наредбата break ќе предизвика предвремено завршување на циклусот.

Оваа наредба ни овозможува да користиме и т.н. бесконечни циклуси - циклуси кои немаат дефиниран услов, или условот е така дефиниран да е секогаш исполнет:

Програма 11.6

#include <iostream>
using namespace std;

int main()
{
      int n, s=0;
      
      while (true)
      {
            cout << "Vnesi broj (0 za kraj): ";
            cin >> n;
            
            if (n == 0)
            {
                  cout << "Izleguvam od ciklusot." << endl;
                  break;
            }
            
            //sobiraj gi broevite koi kje gi vnese korisnikot
            s += n;
      }
      
      cout << "Zbirot na broevite koi gi vnese e: " << s << endl;
      return 0;
}

Истата наредба (break) ја споменавме и кај исказот switch. Таму, наредбата имаше слична намена - да предизвика предвремен крај на извршувањето на група наредби.

Наредбата continue, од друга страна, овозможува предвремен крај на тековната итерација од извршувањето - кај for циклусите, тоа значи извршување на наредбата promeni и скокање до делот за проверка на условите, додека кај while и do-while веднаш се скокнува до делот за проверка на условите.

Следната програма го илустрира ефектот од користењето на наредбата continue:

Програма 11.7

#include <iostream>
using namespace std;

int main()
{
      //zbir na parnite broevi od 1 do 100 (so for)
      int sp=0;
      for (int i=1; i<=100; i++)
      {
            if (i%2 != 0)
            {
                  //ne e paren broj

                  //skokni ja ovaa iteracija
                  continue;
            }
            
            //paren broj
            sp += i;
      }
      
      cout << "Zbirot na parni broevi e: " << sp << endl;
      
      //zbir na neparnite broevi od 1 do 100 (so while)
      int sn=0, ii=0;
      while (ii <= 100)
      {
            if (ii%2 == 0)
            {
                  //ne e neparen broj
                  
                  //mora da go azurirame ii
                  //inaku kje ostane istata vrednost
                  ii++;
                  
                  //skokni ja ovaa interacija
                  continue;
            }
            
            //neparen broj
            sn += ii;
            ii++;
      }
      
      cout << "Zbirot na neparni broevi e: " << sn << endl;
      return 0;
}

Дозвола за користење: CC BY-NC 2.5 ©