Ճյուղավորում և ցիկլեր

Մինչ այս պահը դիտարկում էինք ծրագրեր, որոնց վարքը գծային էր․ բոլոր հրամանները, առանց բացառության, կատարվում էին առաջինից մինչև վերջինը՝ միայն մեկ անգամ։ Սակայն գործնականում շատ հազվադեպ են հանդիպում զուտ գծային ալգորիթմներ։ Համարյա միշտ ծրագրավորողին պետք է լինում հրամանների շարքը կատարել մի ինչ֊որ պայմանից կախված, կամ կրկնել մի քանի անգամ։

Օրինակ, ուզում ենք տեղեկացնել, որ ստեղնաշարից ներմուծված x փոփոխականի արժեքը դրական է։ Այսինքն՝ «x֊ը դրական է։» տեքստն արտածել միայն այն դեպքում, երբ ճշմարիտ է պայմանը։

int x = 0;
std::cin >> x;
if( x >= 0 )
    std::cout << x << "-ը դրական է։\n";

if ծառայողական բառով սկսվում է C++ լեզվի պայմանական կամ ճյուղավորման հրամանը։ Այն թույլ է տալիս հրամանի (կամ հրամանների բլոկի) կատարվելը ղեկավարել տրված պայմանով։ if հրամանը թույլ է տալիս գործողություններ նկարագրել նաև այն դեպքի համար, երբ տրված պայմանը ճշմարիտ չէ (կեղծ է)։ Այսպես.

int x = 0;
std::cin >> x;
if( x >= 0 )
    std::cout << x << "-ը դրական է։\n";
else
    std::cout << x << "-ը բացասական է։\n";

Ընդհանուր դեպքում եթե բանաձևով ներկայացնենք if հրամանը, ապա այն կունենա հետևյալ տեսքը.

if( ⟨condition⟩ ) ⟨statements-1⟩ else ⟨statements-2⟩

Եթե ճշմարիտ է ⟨condition⟩ պայմանը, ապա կատարվում է հրամանների ⟨statements-1⟩ շարքը, հակառակ դեպքում կատարվում է else ծառայողական բառից հետո գրված ⟨statements-2⟩ շարքը։ Արդեն նկատեցինք նաև, որ if հրամանի else ճյուղը պարտադիր չէ։

⟨statements-1⟩-ը և ⟨statements-2⟩-ը կարող են լինել կամայական հրամաններ կամ հրամանների շարք։ Դա նաև հուշում է, որ դրանց տեղում կարող է հանդիպել նույն if հրամանը՝ թույլ տալով կառուցել պայմանների շարք։ Օրինակ, ուզում ենք ստուգել, թե ո՛ր կոորդինատական քառորդում է գտնվում տրված կետը։

double x = 0, y = 0;
std::cin >> x >> y;
if( x >= 0 && y >= 0 )
    std::cout << "առաջին\n";
else if( x >= 0 && y < 0 )
    std::cout << "չորրորդ\n";
else if( x < 0 && y >= 0 )
    std::cout << "երկրորդ\n";
else if( x < 0 && y >= 0 )
    std::cout << "երրորդ\n";

Այս կոնկրետ դեպքում, քանի որ հնարավոր դեպքերը ճիշտ չորսն են, կարելի է բաց թողնել վերջին պայմանի ստուգումը։

Երկու արժեքների մեջ ընտրություն կատարելու համար հաճախ օգտագործվում է «?:» տերնար (եռատեղ) գործողությունը․ ex0 ? val1 : val2։ Եթե ճիշտ է ex0 պայմանը, ապա արտահայտության արժեքը val1 է, հակառակ դեպքում՝ val2 է։ Օրինակ, c փոփոխականին a և b արժեքներից առավել մեծը վերագրելու համար կարող ենք գրել ինչպես if հրամանը․

if( a > b ) c = a; else c = b;

այնպես էլ ?: գործողությունը․

c = a > b ? a : b;

Հատուկ նշենք, որ ի տարբերություն if֊ի, ?:֊ը ոչ թե հրաման է, այլ՝ գործողություն․ այն կարելի է օգտագրծել միայն արտահայտությունների մեջ։

Ճյուղավորման մասին առայժմ այսքանը։ Հիմա տեսնենք, թե ինչ միջոցներ է առաջարկում C++ լեզուն այն դեպքերի համար, երբ հարկավոր է ինչ որ հրամաններ կրկնել մեկից ավելի անգամներ՝ գրել ցիկլիկ ալգորիթմներ։ Օրինակ, թող որ պահանջվում է գրել digitSum ֆունկցիան, որը վերադարձնում է տրված ամբողջ թվի թվանշանների գումարը։ Թվի թվանշաններն առանձնացնելը հարմար է վերջից։ Պարզ է, որ, օրինակ, 2016 թվից 6-ը առանձնացնելու համար պետք է այն բաժանել 10-ի և վերցնել մնացորդը։ Հետո, 1 նիշը ստանալու համար պետք է նախորդ քայլի բաժանումից ստացված քանորդը նորից բաժանել 10-ի և վերցնել քանորդը։ Այսպես՝ քանի դեռ բաժանման քանորդը զրո չէ։

Մի որևէ պայմանով, իսկ մեր դեպքում պայմանը բաժանման հերթական քանորդի զրո չլինելն է, ցիկլերը կազմակերպվում են while հրամանով։ Դրա բանաձևային տեսքն այսպիսինն է. «քանի դեռ ճշմարիտ է ⟨condition⟩ պայմանը, պետք է կատարել ⟨statements⟩ հրամանները»․

while( ⟨condition⟩ ) ⟨statements⟩

Վերջապես սահմանենք digitSum ֆունկցիան.

int digitSum( unsigned long int num )
{
    int sum = 0;
    while( num != 0 ) {
        sum += num % 10;
        num /= 10;
    }
    return sum;
}

while կառուցվածքի օգտագործման դեպքում նախ ստուգվում է ցիկլի պայմանը, ապա, եթե այն ճշմարիտ է, կատարվում են ցիկլի մարմնի հրամանները։ Այսպիսի ցիկլերը կոչվում են նախապայմանով ցիկլեր։ C++ լեզվի do-while կառուցվածքը թույլ է տալիս կազմակերպել նաև ետպայմանով ցիկլեր, որում նախ կատարվում է ցիկլի մարմինը, ապա ստուգվում է պայմանը։ Օրինակ,

C++ լեզվում նախատեսված է նաև պարամետրով ցիկլերի կազմակերպման for կաառուցվածքը։ for հրամանը ծրագրավորողին հնարավորություն է տալիս ցիկլի մարմնում ունենալ լոկալ պարամետր։ Օրինակ, եթե ուզում ենք տրված տողում հաշվել բացատանիշերի քանակը, ապա հարմար է ունենալ մի i ինդեքս, որի օգնությամբ կդիմենք տողի հերթական նիշին։ Այսպես.

int countSpaces( const string& text )
{
    int count = 0;
    for( int i = 0; i < text.length(); ++i )
        if( text[i] == ' ' )
            ++count;
    return count;
}

Այս ֆունկցիայում օգտագործվել է for հրամանը, որի ընդհանուր տեսքը հետևյալն է.

for( ⟨initialize⟩; ⟨condition⟩; ⟨increment⟩ )
    ⟨statements⟩

Նախ հաշվարկվում է ⟨initialize⟩ արտահայտությունը, հետո ստուգվում է ⟨condition⟩ պայմանը, և եթե այն ճշմարիտ է, ապա կատարվում են ցիկլի մարմնի ⟨statements⟩ հրամանները։ Այնուհետև հաշվարկվում է ⟨increment⟩ արտահայտությունը, որը սովորաբար ազդեցություն է թողնում ⟨condition⟩-ի վրա։ Ավելի պատկերավոր ասած՝ for հրամանը կարող ենք գրառել while հրամանի օգնությամբ.

⟨initialize⟩
while( ⟨condition⟩ ) {
    ⟨statements⟩
    ⟨increment⟩
}

Որքան էլ որ տարօրինակ կթվա՝ ճյուղավորման հրամանով հնարավոր է ծրագրավրել նաև կրկնություններ։ Օրինակ, գրենք մի ֆունկցիա, որը հաշվում է Ֆիբոնաչիի շարքի n֊րդ անդամը։ Հիշենք, որ այդ շարքի առաջին երկու անդամները 1 են, իսկ ամեն մի հաջորդը իր նախորդ երկուսի գումարն է․

C++ լեզվով այս բանաձևի գրառումը համարյա նույնական է․

int f( int n )
{
  if( n == 1 || n == 2 )
    return 1;

  return f(n-1) + f(n-2);
}

հաշվում է տրված ամբողջ թվի բաժանարարների (բացի իրենից) գումարը։

int sum_divisors( int n, int k )
{
  if( k = 1 )
    return 1;

  if( n % k == 0 )
    return k + sum_divisors( n, k - 1 );

  return sum_divisors( n, k - 1 );
}

!!! Երկուսն էլ անհաջող օրինակներ են !!!

Այսպիսի ֆունկցիան, որի մարմնում կանչ է կատարվում ինքն իրեն, կոչվում է ռեկուրսիվ (անդրադարձ) ֆունկցիա։

results matching ""

    No results matching ""