Програмен език C++
(съдържание)

Част 9. Операторите за управление II част (Advanced Decisions)

В тази предната лекция разгледахме логическите оператори ако (if) и ако-иначе (if-else). В тази ще разгледаме ключ (switch) и условния оператор " ?: , ", както и една специфична конструкция на if-else оператора.

1. Конструкцията else-if . Нека разгледаме примера от предната лекция, който определя възрастовите категории.

if (age < 2)
  cout << "\nInfant";              // it's an infant
  else
    if (age < 18)
      cout << "\nChild";           // it's a child
      else
        if (age < 70)
          cout << "\nAdult";       // it's an adult
          else
           cout << "\nElderly";   // it's an elderly

Самата конструкция по-горе е доста объркваща, въпреки отместването на редовете. Сравнете горните редове с редовете по-долу, които са същият код, но написан без отместванията и с двата оператора else и if на един ред.

if (age < 2)
  cout << "\nInfant";         // it's an infant
else if (age < 18)
  cout << "\nChild";          // it's a child
else if (age < 70)
  cout << "\nAdult";          // it's an adult
else
  cout << "\nElderly";        // it's an elderly

Както споменахме в предната лекция  операторът else "принадлежи" на последния if оператор. Ето защо кодът по-горе може да се тълкува като "стълбица", в която, ако условието е вярно, ще се изпълни редът след условието или, ако не е вярно - по-следващия ред, който е проверка на следващото условие.

Обърнете внимание, че конструкцията else-if не е част от синтактиса на C++, а просто е начин на подредба на двата оператора -- реално погледнато, както показва най-горният код, конструкцията е if-else.

2. Оператор "прекъсване" (The break Statement) . Операторът break препраща изпълнението на програмата на следващия ред след най-вътрешния цикъл, в който той е употребен. Този оператор прекъсва изпълнението на конструкцията switch и циклите for, while, и do-while.

Примерът по-долу проверява дали цялото число n е просто. За целта то се дели на всички числа, започвайки от 2 и стигайки до половината му. Ако се осъществи целочислено делене с j, т.е. ако (n%j == 0) е истина, то числото не е просто (има множител, равен на j) и по-нататъшна проверка за други множители е излишна, т.е. трябва да спрем изпълнението на цикъла. Това се постига с оператора break.

 int isPrime = 1;               // assume n is prime
 for(int j = 2; j < n/2; j++)   // divide by all integers from 2 to n/2
 {
   if (n%j == 0)                // if evenly divisible,
   {
     isPrime = 0;               // n is not a prime
     break;                     // no point in looping again
    }
 }

Ако условието след if оператора е вярно, то променливата isPrime става неистина и програмата достига до оператора break. Неговото действие е програмата да излезе от най-вътрешния цикъл, който съдържа този оператор. В случая това е цъкълът for(int j = 2; j < n/2; j++). Аналогично, с break се излиза и от на другите два цикъла while и do, както и от конструкцията switch, стига те да са най-вътрешни цикли или, съответно, конструкции.

Искаме да обърнем внимание върху израза "излиза от най-вътрешния цикъл" -- операторът break не повлиява по-външните цикли, както показва следващата кратка програма за намиране на всички прости числа сред нечетните числа между 3 и 1001 (2 е също просто число, въпреки че е четно).

// test_prime.cpp
// finds all prime numbers between 3 and 1001

#include <iostream.h>              // for cout and endl
#include <conio.h>                 // for getch()
#include <iomanip.h>               // for setw()

void main(int argc, char* argv[] )
{

  int n, isPrime;
  int prNumCoun = 0;               // counter of prime numbers

  for(n = 3; n <= 1001; n = n + 2) // all numbers between 3 and 1001
  {
    isPrime = 1;                   // assume n is prime
    for(int j = 2; j < n/2; j++)   // divide by all integers from 2 to n/2
    {
      if(n%j == 0)                 // if evenly divisible,
      {
        isPrime = 0;               // n is not a prime
        break;                     // no point in looping again
       }
    }                              // } of for(int j = 2; j < n/2; j++)

    if (isPrime)                   // if n is a prime number ...
    {
      prNumCoun++;                 // another prime number
      cout << setw(3)
           << n << ", ";           // ... print it
      if (prNumCoun%10 == 0)       // print exactly 10 prime numbers a line
        cout << endl;
    }
  }                                // } of for(n = 3; n <= 1001; n = n + 2)

  cout << "\nEnd of the program!";
  getch();
}   // main()

Най-външния цикъл, for(n = 3; n <= 1001; n = n + 2), пробягва всички нечетни числа, и както се вижда от резултата по-долу, той не се повлиява от изпълнението на break. Резултатът от изпълнение на горния код е:

  3,   5,   7,  11,  13,  17,  19,  23,  29,  31,
 37,  41,  43,  47,  53,  59,  61,  67,  71,  73,
 79,  83,  89,  97, 101, 103, 107, 109, 113, 127,
131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
479, 487, 491, 499, 503, 509, 521, 523, 541, 547,
557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997,
End of the program!

3. Оператор "продължавам" (The continue Statement) . Този оператор е подобен на break, но за разлика от него управлението на програмата се предава на първия ред на цикъла, а не на първия ред след цикъла, както прави break. Ето един пример, който илюстрира употребата на continue.

  float dividend, divisor;
  char ch;
  do
  {
    cout << "Enter dividend: ";
    cin >> dividend;
    cout << "Enter divisor: ";
    cin >> divisor;
    if (divisor == 0)                       // if user error,
    {
      cout << "Divisor can't be zero\n";
     continue;                             // go back to top of loop
    }
    cout << "Quotient is " << dividend / divisor;
    cout << "\nDo another (y/n)? ";
    cin >> ch;
  } while(ch != 'n');

При делител (divisor), равен на нула, не е възможно делене, затова на екрана се изписва предупредителен надпис "Divisor can't be zero" и програмата преминава в началото на цикъла, без да извърши деленето.

Често се появява необходимост от използването на continue и break в програмите и употребата им прави кода по-прегледен -- напълно е възможно с операторите if-else или други оператори да се постигне същия резултат както с break или continue,  но разбираемостта на кода намалява драстично: сравнете тези два примера с примерите в настоящия текст.

4. Оператор ключ (The switch Statement). Това е конструкция за взимане на решения, които се основават на стойността на една променлива. Структурата на switch ключа е следната:

switch ( <switch variable> )
{
  case <constant expression 1> : <statement 1>; [break;]
  case <constant expression 2> : <statement 2>; [break;]
  case <constant expression 3> : <statement 3>; [break;]
  ...
  case <constant expression K> : <statement K>; [break;]
  default : <statement>;
}

Ако стойността на променливата <switch variable> е равна на стойността на някой от изразите <constant expression k> то се изпълнява съответният оператор <statement k>: това е вярно при наличие на операторите break;,  иначе се изпълняват всички редове след оператора, избран по условието <constant expression K>. Ако  стойността на променливата <switch variable> не отговаря на нито една от стойностите в изразите <constant expression k>, то се изпълняват операторите в твърдението <statement>;, намиращи се след default клаузата. Последната клауза не е задължителна, и ако я няма и стойността на променливата <switch variable> не отговаря на нито една от стойностите в изразите <constant expression k>, то програмата продължава изпълнението си след последната голяма скоба на конструкцията switch.

Ето един пример от втората лекция от програмата за управление на полетите

  switch (type)
  {
    case AIRLINER : ceiling = 35000; break;
    case COMMUTER : ceiling = 20000; break;
    case PRIVATE  : ceiling = 8000;
  }

Ако променливата type  има стойност AIRLINER, то се изпълнява присвояването ceiling = 35000; и операторът break;. Ако променливата type  има стойност COMMUTER, то се изпълнява присвояването ceiling = 20000; и операторът break; и т.н. Обърнете внимание, че при последния случай (case) няма нужда от оператора break.

! Изпускането на break води до много неприятна логическа грешка. Това е много често срещана грешка при хората, които са програмирали преди това на Pascal, където при съответната конструкция case няма нужда от break.

5. Условният оператор "? :  , "  (The Conditional Operator). Това е оператор който замества цяла if-else конструкция както показва следният пример за определяне на по-малкото от две числа.

if (x < y)
   min = x;
else
   min = y;

Тази конструкция може да се замести само с един ред, а именно

min = (x < y) ? x : y;

В скоби е дадено условието, което се проверява, а след питанката стоят двете стойности (променливи, изрази), които трябва да приеме променливата min. Ако е вярно условието преди питанката min приема стойността след питанката (в примера - стойността на x), а ако не е вярно - стойността след двоеточието (в примера - стойността на y).

Интересно е, че в програмата Excel на Microsoft има същата функция по подобие на условният оператор "? :  , ". Но нейното име е IF и е със следния синтаксис: IF(logical_test, value_if_true, value_if_false).

(съдържание)

Литература

[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.

Автор: Проф. Процесор Аритметиков

[ това е материал от брой 15 от януари 2008 г. на списание "Коснос" www.kosnos.com ]





Keywords: С++,  OOP programming , C++ , Classes , Inheritance , Reusability , Creating New Data Types , Polymorphism and Overloading
Ключови думи: клас , обект, обектно ориентирано програмиране , полиморфизъм switch if else ?