Սովորում ենք C# | Հրամաններ և դրանց կատարման կարգ
Tags: csharp, dotnet, beginners, armenian
Published: 2020-03-18 19:23:50

[Նախորդ գրառման](https://dev.to/n_babajanyan/c-10g5) մեջ ծանոթացանք փոփոխականներին և օպերատորներին, թվարկեցինք տվյալների պահպանմանն ու փոփոխմանն ուղղված պարզագույն գործողություններից մի քանիսին։ Այժմ կուսումնասիրենք **արտահայտությունների** (*expression*) և **հրամանների** (*statement*) միջոցով այդպիսի գործողությունների կատարումը և դրանց համադրմամբ առավել ֆունկցիոնալ ծրագրերի կառուցումը։ 

### Արտահայտություններ (Expressions)

**Արտահայտություն** է կոչվում փոփոխականների, ֆիքսված արժեքների (**literal**) և օպերատորների այնպիսի համադրությունը, որը վերադարձնում է արժեք։

```c#
// Ֆիքսված արժեքն ինքն իրենով արտահայտություն է 
13

// Օպերատորն իր օպերանդ(ներ)ի հետ միասին նույնպես կազմում է արտահայտություն
13++ 
true || false 

// Կարելի է օգտագործել արտահայտությունների բարդ համադրություններ
(true || false) && !(false || false)
```

Արտահայտությունների կառուցման մեջ կարևոր դեր է խաղում **օպերատորների կատարման հերթականությունը** (*operator precedence*)։ Դպրոցական մաթեմատիկայի դասերից հիշում ենք որ մաթեմատիկական արտահայտության մեջ առաջին հերթին կատարվում են բազմապատկման և բաժանման գործողությունները և հետո միայն գումարումն ու հանումը։ C# լեզուն ունի իր սեփական կանոնները, որոնք մասամբ արտացոլում են մաթեմատիկական հերթականությունը։ ```c#
double result = 1.0 - 5.0 / 2.0;
// Առաջին հերթին կատարվում է բաժանումը, հետևաբար result = -1.5


result = (1.0 - 5.0) / 2.0; 
// Փակագծերի ներսում գտնվող գործողությունները կատարվում են առաջին հերթին,
// հետևաբար result = -2
```

Եթե արտահայտության մեջ ներկա են կատարման հավասար կարգով օպերատորներ, հերթականությունը որոշվում է **օպերատորների զուգորդականությամբ** (*operator associativity*)։ Այն կարող է լինել ձախից աջ, կամ աջից ձախ։ Օրինակ, `+` օպերատորի զուգորդականությունը ձախից աջ է, այսինքն գործողությունը կատարվում է ձախ օպերանդից "դեպի" աջ օպերանդ։ Վերագրման օպերատորի (`=`) դեպքում պատկերն այլ է՝ այն ունի աջից ձախ զուգորդականություն․ այսինքն աջ կողմում գտնվող օպերանդի արժեքը նշանակվում է ձախ կողմում գտնվողին։
```c#
int result = 1   +   6   +   5   +   1; 
//           1  -->  7  -->  12 -->  13
// result = 13

int a = -1; 
int b = 2;
int c = 7;

a   =   b   =   c;
/*
7  <--  7  <--  7
a = 7, b = 7, c = 7
*/

// Եթե = օպերատորն ունենար ձախից աջ զուգորդականություն, կկատարվեր հակառակը, 
// Բոլոր երեք փոփոխականները կստանային -1 արժեքը 
```

### Հրամաններ (Statements)
Այժմ արդեն ծանոթ ենք արտահայտություններին, կարող ենք անցնել ծրագրերի հիմնական մասնիկներին՝ **հրամաններին** (*statements*)։ Ծրագրում կատարվելիք գործողությունները կոդում ընդունում են հրամանի տեսք։ 

Առանձնացվում են հրամանների մի քանի տեսակներ (որոնց համար C#-ում տրաամդրվում են համապատասխան բանալի բառեր՝ *keywords*)։ Այժմ կդիտարկենք դրանցից մի քանիսը
* **Հայտարարման հրամաններ** (*declaration statements*) - նախատեսված է նոր փոփոխականների հայտարարման համար,
* **Արտահայտությամբ հրամաններ** (*expression statements*) - այս հրամանները պարունակում են արտահայտություններ, որոնց հաշվարկված արժեքը պահվում է փոփոխականում,
* **Ընտրության հրամաններ** (*selection statements*) - նախատեսված են ծրագրի "ճյուղավորման"՝ որոշակի պայմանների դեպքում տարբեր գործողությունների կատարման համար,
* **Կրկնության հրամաններ** (*iteration statements*) - նախատեսված են որոշակի գործողություններ մի քանի անգամ կրկնելու համար։ Կրկնությունները կարելի է սահմանափակել կա՛մ ֆիքսված քանակով, կա՛մ որոշակի պայմանով։

#### Հայտարարման հրամաններ (declaration statements)
Ինչպես պարզ է դառնում տվյալ տեսակի անվանումից, այս հրամանները նախատեսած են նոր փոփոխականների հայտարարման համար։ Հրամանում նշում է փոփոխականի տիպը, անվանումը, կարող է նաև նշվել սկզբնական արժեքը
```c#
string country = "Հայաստան"; // Հայտարարում սկզբնական արժեքով
int number; // Հայտարարում առանց սկզբնական արժեքի
```

#### Արտահայտությամբ հրամաններ (expression statements)
Արտահայտությամբ հրամանները բաղկացած են երկու մասից՝
* արտահայտություն (expression)
* նշանակում (assignment)

```c#
5 * 4; // Առկա է արտահայտությունը, բայց ոչ նշանակումը, հետևաբար, սա ճիշտ հրաման չէ 
result = 13++ * 5 / 2; // Արտահայտությամբ հրամանի օրինակ
bool check = result == 35; // Հնարավոր է հայտարարումը համատեղել արահայությամբ հրամանի հետ
```

### Ծրագրի կատարման կարգ (Control flow)

Հրամանների տեսակները, որոնք հիմա կուսումնասիրենք հնարավորություն են տալիս փոխել ծրագրի ընթացքն անմիջապես կոդի մեջ, ինչn ինֆորմատիկայում կոչվում է **ծրագրի կատարման կարգ** (*control flow*)։ 
Մասնավորապես, այժմ կսովորենք ինչպես կարող է ծրագրի ընթացքը փոխվել կախված ինչ-որ պայմանից և ինչպես կարելի է կրկնել ինչ-որ գործողություն(ներ)՝ ֆիքսված քանակով կամ քանի դեռ չի կատարվել մեր տրված պայմանը։


#### Ընտրության հրամաններ (selection statements)

Ավելի վաղ ծանոթացել էինք բուլյան (*boolean*) արժեքներին։ Վերջիններիս հիմնական կիրառություններից է պայմանների ճշմարիտ կամ սխալ արժեքների արտացոլումը, հետագայում ստուգելու նպատակով։ Ընտրության հրամանները հնարավորություն են տալիս ստուգել նման արժեքներ և դրա ճշմարտացիությունից կախված փոխել ծրագրի ընթացքը։ Այս նպատակով օգտագործվում են `if` (եթե) և `else` (հակառակ դեպքում) բանալի բառերը։
```c#
// condition-ը բուլյան փոփոխական է
if(condition) {
    // Այստեղ տեղակայված կոդը կկատարվի միայն եթե փակագծերում տրված պայմանը ճիշտ է
} else {
    // ․․․իսկ այստեղինը՝ եթե պայմանը սխալ է
}

/*
Հնարավոր է բուլյան արժեք վերադարձնող արտահայտությունն ամիջապես տեղադրել 
if-ի փակագծերի մեջ, առանց փոփոխականում պահելու
*/
double temperature = 37.5;
if(temperature > 36.6) {
    // Թույլատրվում է ունենալ if բլոկ, առանց else բլոկի
    // ․․․սակայն else բլոկ առանց if բլոկի՝ ոչ
}
```

Այն դեպքերում երբ մեզ հետաքրքրում են ոչ թե ինչ-որ պայմանի ճիշտ կամ սխալ լինելը, այլ փոփոխականի տարբեր հնարավոր արժեքներ, `if`-ի օգտագործումն այդքան էլ օպտիմալ չէ՝
```c#
// Ենթադրենք մեր ծրագրում պետք է ստուգվի նետված զառի արժեք
// 6 տարբեր դեպքերի համար if/else համադրությունն այդքան էլ տեղին չէ
if (diceValue == 1) 
{   
} else if (diceValue == 2) 
{
} else if (diceValue == 3) 
{
} else if (diceValue == 4) 
{
} ․․․
```

Նմանատիպ դեպքերի համար C#-ում նախատեսված են `switch` և `case` բանալի բառերը։
Զառի օրինակը այս բանալի բառերի օգտագործմամբ կունենա այս տեսքը
```c#
switch (diceValue) 
{
    case 1:
        // diceValue փոփոխականի արժեքը 1 է
        break;
    case 2:
        // diceValue փոփոխականիարժեքը 2 է
        break;
    ...
    default:
        // Փոփոխականը չընդունեց տրված արժեքներից ոչ մեկը
        break;
}
```
`switch` բանալի բառից հետո փակագծերի ներսում նշվում է այն փոփոխականը, որի արժեքը ստուգվելու է, իսկ `case` (դեպք) բանալի բառի միջոցով նշվում են մեզ հետաքրքրող արժեքները և դրանց դեպքում կատարվող գործողությունները։ Ուշադրություն դարձրեք, որ ամեն `case`-ի ներսում կատարվող գործողություններից հետո անպայման պետք է տալ `break` հրաման, որպեսզի ծրագիրը դուրս գա `switch` բլոկից։ Մեր կողմից ծրագրավորված դեպքերի վերջում ավելացվում է `default`-ը, որը պարունակում է այն գործողությունները, որոնք կարվեն, եթե փոփոխականը ոչ մի այլ `case`-ում տեղ գտած արժեք չի ընդունել։ Զառի օրինակի պարագայում, եթե `diceValue` փոփոխականն ընդունի 7 արժեքը, `default` դեպքում կարելի է զգուշացնել սխալ (անհնար) արժեքի մասին։

Որոշ դեպքերում անհրաժեշտ է լինում կատարել նույն գործողությունները մի քանի արժեքների (`case`-երի) պարագայում, այդ պարագայում `case`-երը կարելի է միավորել հետևյալ կերպ՝
```c#
switch (diceValue) 
{
    case 1:
        // Փոփոխականի արժեքը 1 է
        break;
    case 2:
    case 3:
        // Այստեղ տեղ գտած կոդը կկատարվի եթե diceValue 
        // փոփոխականն ընդունի կա՛մ 2, կա՛մ 3 արժեքը
        break;
    ...
}
```

#### Կրկնության հրամաններ (iteration statements)

Ինչպես արդեն նշել էի, կրկնության հրամանները հնարավորություն են տալիս կրկնել որոշակի գործողություններ՝
* ֆիքսված քանակով
* քանի դեռ չի կատարվել որոշակի պայման

Առաջին դեպքի համար օգտագործվում է `for` բանալի բառը, որին հետևում է փակագծերով շրջապատված հետևյալ երեք մասերը՝
* "հաշվիչ" փոփոխականի հայտարարում,
* այդ փոփոխականի համեմատում մեր տրված արժեքի հետ(ըստ էության սա բուլյան արժեք վերադարձնող արտահայտություն է՝ այսինքն, պայման),
* փոփոխականի փոփոխություն (ավելացում/պակասեցում)։
Սրանք իրարից բաժանվում են `;` նշանով։ Այնուհետև `{ }` ձևավոր փակագծերի ներսում տրվում են այն գործողությունները, որոնք պետք է կրկնվեն։ Դիտարկենք օրինակ՝
```c#
// 1) int i = 0    - հաշվիչ փոփոխականի հայտարարում
// 2) i < 5        - քանակը սահմանափակող պայման
// 3) i++          - փոփոխականի ավելացում
for(int i = 0; i < 5; i++) 
{
    // Այստեղ գրված կոդը կկատարվի 5 անգամ
    // Ամեն անգամ i փոփոխականն ավելացնելով 1-ով
    // Երբ i-ը հավասարվում է 5-ի, 5 < 5 արտահայտությունը վերադարձնում է 
    // սխալ արժեք, և ծրագիրը դուրս է գալիս ցիկլից։
}
```
`for` հրամանի կողմից կատարվող գործողությունների հերթականությունը հետևյալն է՝
1. առաջին հերթին, հայտարարել հաշվիչ փոփոխականը
2. ստուգել պայմանը
3. եթե պայմանը ճշմարիտ է (արտահայտությունը վերադարձնում է ճշմարիտ արժեք), կատարել բլոկի ներսում գտնվող կոդը
4. կատարել հաշվիչի փոփոխության հրամանը

Այժմ դիտարկենք մյուս ցիկլի (կրկնության) հաջորդ հրամանը՝ `while`-ը։
Վերջինս ունի ավելի պարզ կառուցվածք՝ `while` բանալի բառից հետո փակագծերում տրվում է պայմանը, որը պետք է ստուգվի, այնուհետև ձևավոր փակագծերում՝ կրկնվող գործողությունները։ 
```c#
while (condition) 
{
    // Այդ կոդը կկրկնվի այնքան ժամանակ, 
    // քանի դեռ condition փոփոխականը/արտահայտությունը 
    // վերադարձնում է ճշմարիտ (true)արժեք
}
```
Այս տեսակի ցիկլերի տիպիկ օրինակ են վիդեոխաղերը, որոնց հիմնական գործողություններն ըստ էության կատարվում են այսպիսի ցիկլի մեջ՝
```c#
bool isPaused = false;
while(!isPaused) 
{
    // 1) Արտապատկերել խաղային գրաֆիկան

    // 2) Ստանալ խաղացողի հրամանները (օրինակ՝ ստուգել սեղմված կոճակները)
    if (button == "PAUSE") 
    {
        isPaused = true;
    }

    // 3) Կատարել փոփոխություններ (օրինակ՝ շարժումներ) խաղային օբյեկտների վրա
}
```

Այս տեսակի ցիկլերը կարող են օգտագործվել երկու ձևով՝ միայն `while` հրամանի միջոցով, կամ `do`, `while` զույգի միջոցով։
```c#
while(condition) 
{
    // ...
}

do 
{
    // ...
} while (condition)
```
Էական տարբերություն է հանդիսանում այն փաստը, որ `do`/`while` հրամանների պարագայում, առաջին հերթին կատարվում է ձևավոր փակագծերի ներսում գտնվող կոդը, այնուհետև ստուգվում է `while`-ին տրված պայմանը։ Այսինքն նույնիսկ եթե `condition` պայմանը վերադարձնում է սխալ (`false`) արժեք, կոդը կկատարվի մեկ անգամ, մինչդեռ միայն `while` հրամանի միջոցով կառուցված ցիկլում կոդը կկատարվի միմիայն պայմանի ճշմարիտ լինելու պարագայում։

### Ամփոփում

Այս անգամ ուսումնասիրեցինք
* Արտահայտություններ (*expressions*) և դրանց կառուցումը փոփոխականների, ֆիքսված արժեքների և օպերատորների միջոցով
* Օպերատորների կատարման հերթականությունն (*operator precedence*) ու դրանց զուգորդականությունը (*associativity*) 
* Հայտարարման (*declaration*), արտահայտությամբ (*expression*), ընտրության (*selection) և կրկնության (*iteration*) հրամանները (*statements*)
* Ծրագրի կատարման կարգը (*control flow*)