Условно извршување (if-else, switch)

Сите програми кои ги разгледавме досега беа составени од наредби кои се извршуваат последователно (една по друга). Но, понекогаш сакаме, зависно од направениот избор од страна на корисникот, нашите програми да извршуваат различни наредби - или да повторуваат одредени наредби повеќе пати. На пример, програмата може да прочита еден цел број од тастатура и да отпечати дали прочитаниот број е парен или не (две различни наредби за печатење од кои само една треба да се изврши).

Во C++ постојат неколку искази (наречени управувачки структури) кои овозможуваат промена на регуларниот тек на програмата.

Исказ if-else

Наједноставниот исказ за овозможување на условно извршување е исказот if:

if (uslov)
     naredba;

Притоа, наредбата naredba се извршува единствено доколку е задоволен условот uslov. Дополнително, програмерот може да специфицира и наредба која би се извршила доколку условот не е задоволен:

if (uslov)
      naredba1;
else
      naredba2;

Во продолжение е дадена една програма која користи if искази: програмата најпрвин чита еден цел број, а потоа печати неколку информации за него:

Програма 10.1

#include <iostream>
using namespace std;

int main()
{
      int n;
      cin >> n;
      
      /* samo edna od slednite 3 naredbi
      za pecatenje moze da se izvrshi */
      if (n > 0)
            cout << "Vnesen e pozitiven broj!" << endl;
      
      if (n < 0)
            cout << "Vnesen e negativen broj!" << endl;
      
      if (n == 0)
            cout << "Vnesen e brojot 0!" << endl;
      
      
      /* if-else */
      
      //ako e brojot deliv so 2, togash e paren
      if (n%2 == 0)
            cout << "Vnesen e paren broj!" << endl;
      else
            cout << "Vnesen e neparen broj!" << endl;
      
      return 0;
}

Во C++ постои интересна поврзаност помеѓу целите броеви и вредностите точно и неточно. Имено, во C++, ако некој услов наместо од вредностите точно и неточно зависи од аргумент цел број, условот ќе се смета за неисполнет ако и само ако тој цел број е (точно) еднаков на 0. Во спротивно, за кој било цел број различен од 0, условот ќе се смета за исполнет:

Програма 10.2

#include <iostream>
using namespace std;

int main()
{
      int x = 4;
      
      if (x)
      {
            cout << "x ne e ednakov na 0!" << endl;
      }
      
      return 0;
}

Бидејќи if-else е самото по себе наредба, можно е поврзување на повеќе if искази - на пример, за проверка на опсег на броеви:

Програма 10.3

#include <iostream>
using namespace std;

int main()
{
      int n;
      cin >> n;
      
      if (n > 0)
            cout << "Vnesen e pozitiven broj!" << endl;
      else if (n < 0)
            cout << "Vnesen e negativen broj!" << endl;
      else
            cout << "Vnesen e brojot 0!" << endl;
      
      return 0;
}

Важно е да повториме (од претходното предавање) дека C++ ги врши само неопходните наредби за пресметка на вредност на услов: доколку имаме израз од типот "a && b && c", и a има вредност false, каква и да е вредноста на b и c, изразот повторно ќе има вредност false (бидејќи, кај логичко И, изразот е true само ако сите операнди се true). Кај логичко ИЛИ важи обратното - ако еден од операндите е true, тогаш целиот израз е true (нема потреба да се пресмета остатокот).

Понекогаш сакаме, доколку е исполнет if условот, да извршиме повеќе од една наредба. Во C++, ова можеме да го направиме со помош на т.н. блок од наредби.

Блок од наредби

Блок претставува група од наредби. Блоковите започнуваат со симболот '{', содржат група од наредби и завршуваат со симболот '}'. Наредбите во блокот се одделуваат како и сите останати наредби (со помош на симболот ';'). Блоковите може да се сместуваат еден во друг - еден блок може да се стави во внатрешноста на друг блок, кој пак е сместен во трет блок, итн..

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

Програма 10.4

#include <iostream>
using namespace std;

int main()
{
      int n;
      cin >> n;
      
      if (n < 10)
      {
            cout << "Vnesen e brojot " << n << endl;
            cout << "Ovoj broj e pomal od 10." << endl;
      } else
      {
            //eden blok moze da sodrzi i samo edna naredba
            cout << "Ne vnesovte broj pomal od 10." << endl;
      }
      
      return 0;
}

Во програмите кои ги разгледавме досега, сите променливи беа декларирани во внатрешноста од main() функцијата, и тоа, пред кое било читање или запишување на вредност. Дефинирањето на терминот блок од наредби ни овозможува да споменеме дека C++ овозможува декларирање на променливи на два начини: глобално (надвор од која било функција) и локално (во одредена функција или блок). Променливите кои се декларирани глобално може да се користат на која било локација во кодот (во која било функција или блок). Од друга страна, променливите кои се декларирани локално може да се користат само во функцијата/блокот во кој се дефинирани (и тоа, откако ќе бидат декларирани - т.е. по наредбата за декларирање на променлива), вклучувајќи ги и сите блокови кои се наоѓаат во внатрешноста на таа функција/блок.

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

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

Програма 10.5

#include <iostream>
using namespace std;

int promenliva;                           //globalna promenliva

int main()
{
      int a = 10, b = 20, c = 30;         //lokalni promenlivi
      
      if (b > a)
      {
            int d;                        //lokalna promenliva
            d = a+b;                      //vidliva samo vo ovoj blok
            
            cout << d << endl;            //pechati '30'
      }
      
      //promenlivata 'd' ne e vidliva tuka
      
      int promenliva;
      promenliva = 10;                    //lokalna promenliva
      ::promenliva = 100;                 //globalna promenliva
      
      cout << promenliva << endl;         //pechati '10'
      cout << ::promenliva << endl;       //pechati '100'
      
      return 0;
}

Исказ switch

Управувачката структура switch овозможува условно извршување на група од наредби зависно од вредноста на одреден израз. Во продолжение е дадена синтаксата на оваа управувачка структура:

switch (izraz)
{
     case konstanta1:
             naredba1-1;
             naredba1-2;
             ...
             break;
     case konstanta2:
             naredba2-1;
             ...
             break;
     ...
     default:
             naredbaD-1;
             naredbaD-2;
             ...
}

Зависно од вредноста на изразот izraz и нејзиното поклопување со една од константите konstanta1, konstanta2, ..., програмата продолжува со извршување од локацијата каде има совпаѓање на вредноста на изразот со некоја од дефинираните константи. Извршувањето на управувачката структура switch завршува кај првото среќавање на break. На пример, доколку вредноста на изразот izraz е еднаква на konstanta1, програмата ги извршува naredba1-1, naredba1-2, .., се до среќавањето на break. Доколку вредноста е еднаква на konstanta2, програмата ги извршува naredba2-1, naredba2-2, итн. Доколку вредноста на izraz не е еднаква на ниту една константа, програмата ги извршува наредбите од делот default: naredbaD-1, naredbaD-2, итн.

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

Програма 10.6

#include <iostream>
using namespace std;

int main()
{
      int ocena;
      cin >> ocena;
      
      switch (ocena)
      {
            case 1:
                  cout << "Nedovolen (1)" << endl;
                  break;
            
            case 2:
                  cout << "Dovolen (2)" << endl;
                  break;
            
            case 3:
                  cout << "Dobar (3)" << endl;
                  break;
            
            case 4:
                  cout << "Mnogu dobar (4)" << endl;
                  break;
            
            case 5:
                  cout << "Odlicen (5)" << endl;
                  break;
            
            default:
                  cout << "Ne zezaj. Vakva ocena nema." << endl;
      }
      
      return 0;
}

Сите дефинирани константи (konstanta1, konstanta2, итн.) мора да бидат различни. Исказот switch може да замени неколку if искази, но само доколку сакаме да ја споредуваме вредноста на изразот izraz со константа. Доколку сакаме да ја споредуваме вредноста со променливи, тогаш мора да користиме if наредби.

Наредбата break овозможува исклучување (скокање надвор) од switch блокот. По среќавање на break, програмата продолжува со извршување на наредбата која следи по switch исказот. Доколку немавме break по наредбите кои одговараат на среќавањето на одредена константа, програмата ќе продолжеше со извршување на сите следни наредби наведени во case деловите od switch наредбата - се додека не дојдовме до крајот на блокот. На пример, доколку програмата дадена погоре не содржеше break наредби и корисникот внесеше ocena=3, програма ќе отпечатеше 3 оценки ("Dobar (3)", "Mnogu dobar (4)" и "Odlicen (5)") и изразот "Ne zezaj. Vakva ocena nema.".

Поради фактот што изгледот на исказот switch е толку различен од изгледот на сите останати наредби во C++ (користи break наместо блок од наредби '{ ... }'), тој многу ретко и се користи. Сепак, важно е да се каже дека потребата од повикување на break не е случајна. Понекогаш, навистина постои потреба од извршување на иста група од наредби за различни вредности на еден израз:

Програма 10.7

#include <iostream>
using namespace std;

int main()
{
      char ch;
      cin >> ch;
      
      switch (ch)
      {
            case 'A':
            case 'E':
            case 'I':
            case 'O':
            case 'U':
                  cout << "Vnesovte samoglaska." << endl;
                  break;
            
            default:
                  cout << "Ne vnesovte samoglaska." << endl;
      }
      
      return 0;
}

За крај, важно е да напоменеме дека делот default е незадолжителен, и еден switch исказ не мора да содржи default група на наредби.

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