3570

Синтаксис мови програмування C#

Лекция

Информатика, кибернетика и программирование

Синтаксис мови програмування C# У цьому розділі ми розглянемо основу будь-якої мови програмування — його здатність виконувати привласнення і порівняння за допомогою операторів. Ми побачимо, які оператори є в С# і яке їх старшинство, а потім заг...

Украинкский

2012-11-03

164.5 KB

43 чел.

Синтаксис мови програмування C#

У цьому розділі ми розглянемо основу будь-якої мови програмування — його здатність виконувати привласнення і порівняння за допомогою операторів. Ми побачимо, які оператори є в С# і яке їх старшинство, а потім заглибимося в окремі категорії виразів для виконання арифметичних операцій, привласнення значень і порівняння операндів. Розробники C# постарались розробити синтаксис і семантику операторів найбільш зручною для програмістів.

Оператори

Оператор — це символ, вказуючий операцію, що виконується над одним або декількома аргументами. При виконанні оператора виходить результат. Синтаксис застосування операторів декілька відмінний від виклику методів, і формат виразів, що містять операторів в С#, ви повинні знати як свої п'ять пальців. Як і в більшості інших мов, семантика операторів в С# відповідає правилам і нотаціям, знайомим нам з шкільної лави. Базові оператори в С# включають множення (*), ділення (/), складання (+), віднімання (—), модуль (%) і привласнення (=).

Оператори служать для того, щоб набути нового значення із значень, над якими проводиться операція. Ці початкові значення називаються операндами. Результат операції повинен бути збережений в пам'яті. Іноді він зберігається в змінній, що містить один з початкових операндів. Компілятор С# генерує повідомлення про помилку, якщо при використанні оператора не визначається або не зберігається нове значення. Приведений нижче код значень не міняє. Компілятор видасть повідомлення про помилку, оскільки арифметичний вираз, що не приводить до зміни хоч одного значення, зазвичай розглядається як помилкове.

class NoResultApp

{

public static void Main()

{

int i; int j;

i + j; // Помилка, оскільки результат нічому не привласнюється. } >

Більшість операторів працюють тільки з числовими типами даних, такими як Byte, Short, Long, Integer, Single, Double і Decimal. Виключення — оператори порівняння (== і !=). Крім того, в С# можна застосовувати операторів + і — для класу String і навіть застосовувати операторів інкремента (++) і (—) для таких незвичайних мовних конструкцій як делегати.

Старшинство операторів

Коли в одному виразі декілька операторів, компілятор повинен визначити порядок їх виконання. При цьому компілятор керується правилами, які називаються старшинством операторів. Розуміння старшинства операторів потрібне для правильного написання виразів — іноді результат може не відповідати очікуваному.

Розглянемо вираз 42 + 6 * 10. Якщо скласти 42 і 6, а потім суму помножити на 10, вийде 480. Якщо ж помножити 6 на 10 і до результату додати 42, вийде 102. При компіляції коду спеціальний компонент компілятора — лексичний аналізатор — відповідає за порядок читання цього коду. Саме лексичний аналізатор визначає відносне старшинство різнорідних операторів в одному виразі. Для цього він використовує деяке значення — пріоритет — кожного підтримуваного оператора. Пріоритетніші оператори вирішуються в першу чергу. У нашому прикладі оператор * має старшинство над оператором +, оскільки * поглинає (зараз поясню цей термін) свої операнди до того, як це зробить +. Пояснення криється в загальних арифметичних правилах: множення і ділення завжди мають вищий пріоритет, ніж складання і віднімання. Повернемося наприклад: говорять, що число 6 поглинено оператором * і в 42 + 6 * 10 і в 42 * 6 + 10, так що ці вирази еквівалентні 42 + (6 * 10) і (42 * 6) + 10.

Як старшинство визначається в С#

Тепер подивимося, як старшинство операторів визначається в С#. Нижче оператори перераховані в порядку спадання пріоритету (табл. 1).

Табл. 7.1. Старшинство операторів в С#.

Категорія оператора

Оператори

Простий

(х), х.у, f(x), а, х++, х —, new, typeof, sizeof, checked, unchecked

Унарний

+, - !, ++x, — х, (Т) х

Мультиплікативний

*,/, %

Аддитивний

+, -

Зрушення

«, »

Відношення

<, >, <=, >=, is

Рівність

==

Логічне І (AND)

&

Що логічне виключає АБО (XOR)

^

Логічне АБО (OR)

|

Умовне І (AND)

&&

Умовне НУЛІ (OR)

II

Умова

9-

Привласнення

= *= /= % =, + =, -= « =, » =, &=, ^ =, =

 

Ліва і права асоціативність

Асоціативність визначає, яка частина виразу повинна бути обчислена першою. Наприклад, результатом приведеного виразу може бути 21 або 33 залежно від того, яка асоціативність застосовуватиметься для оператора «— »: ліва або права.

42-15-6

Оператор — має ліву асоціативність, тобто спочатку обчислюється 42—15, а потім від результату віднімається 6. Якби він мав праву асоціативність, спочатку обчислювалася б права частина виразу (15—6), а потім результат віднімався б від 42.

Всі бінарні оператори (оператори з двома операндами), окрім операторів привласнення, — ліво-асоціативні, тобто вони обробляють вирази зліва направо. Таким чином, а + Ь + з — те ж, що і (а + Ь) + з, де спочатку обчислюється а + Ъ, а потім до суми додається з. Оператори привласнення і умовні оператори — право-асоціативні, тобто обробляють вирази справа наліво. Інакше кажучи, а=Ъ=с еквівалентно а = (Ь = з). Багато хто на цьому спотикається, коли хоче помістити в один рядок декілька операторів привласнення, так що давайте розглянемо такий код:

using System;

class RightAssocApp {

public static void Main() {

int а = 1; int b = 2; int з = 3;

Console.WriteLine("a={0} b={1} c={2>", а, b, з); а = b = з;

Console.WriteLine("Після "a=b=c-: a={0} b={1} c={2}", а, b, з); > >

Результат виконання цього прикладу такий:

а=1 ь=2 с=3

Після 'а=Ь=с': а=3 Ь=3 о=3

Спочатку обчислення виразів справа наліво може збивати з пантелику, але давайте підійдемо до цього так: якби оператор привласнення був ліво-асоціативним, компілятор спочатку повинен був би обчислити а = Ь, після чого а було б рівне 2, а потім b = з і в результаті b було б рівне 3. Кінцевий результат був би а=2 Ь=3 с=3. Очевидно, що ми чекаємо не цього, коли пишемо а = b = з, і саме тому оператори привласнення і умовні оператори право-асоціативні.

Оператори С#

Найправильніше розглядати операторів за старшинством.

Прості оператори

Перша категорія — прості оператори. Оскільки більшість з них елементарні, я їх просто перерахую і стисло опишу їх функції. Потім я опишу інші, менш зрозумілі.

  •  (х) Це різновид оператора «дужки» для управління порядком обчислень як в математичних операціях, так і при виклику методів.
  •  х.у Оператор «крапка» використовується для вказівки члена класу або структури. Тут х представляє суть, що містить в собі член у.
  •  f(x) Такий різновид оператора «дужки» застосовується для перерахування аргументів методів.
  •  а[х] Квадратні дужки використовуються для індексації масиву. Ці дужки також застосовуються спільно з індексаторами, коли об'єкти можуть розглядатися як масив. Про індексатори див. розділ 7.
  •  х++ Про оператора інкремента ми поговоримо окремо в розділі «Оператори інкремента і декремента».
  •  х— Оператор декремента ми теж розглянемо пізніше.
  •  new Цей оператор використовується для створення екземплярів об'єктів на підставі визначення класу.

Typeof

Віддзеркалення (reflection) — це здатність отримувати інформацію про тип в період виконання. Ця інформація включає імена типів, класів і елементи структур. У .NET Framework ця функціональність пов'язана з класом System. Type. Цей клас — корінь всіх операторів віддзеркалення і може бути отриманий за допомогою оператора typeof. Простій приклад, що ілюструє простоту застосування оператора typeof 'для отримання практично будь-якої інформації про тип або об'єкт під час виконання програми:

using System;

using System.Reflection;

public class Apple {

public int nSeeds;

public void Ripen()

{

> >

public class TypeOfApp {

public static void Main() {

Type t = typeof(Apple);

string className = t.ToStringO;

Console.ИгШипе("\пИнформация 0 класі {О}", className);

Console.WriteLine("\nMeroflH {0}", className); Console. WriteLine("—"); Methodlnfo[] methods = t.GetMethodsO;

foreach (Methodlnfo method in methods)

{

Console.WriteLine(method.ToSt ring());

}

Console.WriteLine("\nBce члени {О}", className); Console. Writel_ine("—"); Memberlnfo[] allMembers = t.GetMembersO; foreach (Memberlnfo member in allMembers)

{

Console. WriteLine(member.ToStringO);

} > }

У цій програмі міститься клас Apple, у якого всього два члени: поле nSeeds і метод Ripen. Спочатку, використовуючи оператора typeof і ім'я класу, я отримую об'єкт System. Type, який потім зберігається в змінній t. З цієї миті я можу використовувати об'єкт System. Type для отримання всіх методів і членів класу Apple. Це робиться за допомогою методів GetMethods і GetMembers відповідно. Результати виконання цих методів виводяться на стандартний пристрій виводу таким чином:

Інформація про клас Apple Методи Apple

Int32 GetHashCodeQ

Boolean Equals(System.Object)

System.String ToStringQ

Void RIPENO

System.Type GetTypeO

Всі члени Apple

Int32 nSeeds

Int32 GetHashCodeO

Boolean Equals(System.Object)

System.String ToStringO

Void RIPENO

System.Type GetTypeO

Void .ctorO

Перш ніж рухатися далі, хочу зробити два зауваження. По-перше, звернете увагу, що виводяться і успадковані члени класу. Оскільки клас не породжений явно з іншого класу, ми знаємо, що всі члени, не визначені в класі Apple успадковуються від неявного базового класу System.Object. По-друге, об'єкт System.Type можна отримати методом GetType. Цей успадкований від System.Object метод дозволяє працювати з об'єктами, а не з класами. Будь-яким з двох приведених далі фрагментів можна використовувати для отримання об'єкту System. Type.

II Отримання об'єкту System.Type на основі визначення класу. Type t1 = typeof(Apple);

// Отримання об'єкту System.Type з об'єкту. Apple apple = new APPLEQ; Type t2 = apple.GetTypeO;

Sizeof

Оператор sizeof застосовується для отримання розміру вказаного типу в байтах. При цьому пам'ятаєте про два виключно важливі чинники. По-перше, sizeof можна застосовувати тільки до розмірних типів. Отже, хоча його можна використовувати для членів класів, для класів як таких його застосовувати не можна. По-друге, sizeof можна застосовувати тільки в методах або блоках коду, помічених як unsafe. Ось приклад використання оператора sizeof в методі класу, поміченого як unsafe:

using System;

class BasicTypes {

// Примітка: Код, що використовує оператора sizeof, // повинен бути помічений як unsafe, static unsafe public void ShowSizesQ {

Console.WriteLine("\nPa3Mephi основних типів"); Console.WriteLine("Pa3Mep short = {0}", sizeof(short)); Console.WriteLine("Pa3Mep int = {0}", sizeof(int)); Console.Writel_ine("Pa3Mep long = {0}", sizeof(long)); Console.WriteLine("Pa3Mep bool = {0}", sizeof(bool)); } }

class UnsafeUpp

{

unsafe public static void MAINQ

{

BasicTypes.ShowSizes();

} }

Ось результат виконання цього застосування:

Розміри основних типів Розмір short = 2 Розмір int = 4 Розмір long = 8 Розмір bool = 1

Оператора sizeof можна використовувати для визначення розмірів не тільки простих вбудованих типів, але і призначених для користувача розмірних типів, таких як структури. Проте при цьому результати sizeof можуть бути неочевидні:

// Використання оператора sizeof. using System;

struct StructWithNoMembers

{

}

struct StructWithMembers

{

short s;

int i;

long 1;

bool b; }

struct CompositeStruct

{

StructWithNoMembers а; StructWithMembers b;

StructWithNoMembers з; }

class UnSafe2App {

unsafe public static void Main() { Console.WriteLine("\nPa3Mep StructWithNoMembers structure = {0}",

sizeof(StructWithNoMembers)); Console.WriteLine("\nPa3Mep StructWithMembers structure = {0}",

sizeof(StructWithMembers)); Console.WriteLine("\nPa3Mep CompositeStruct structure = {0}",

sizeof(CompositeStruct)); } }

Хоча можна припустити, що це застосування виведе 0 для структури без членів (StructWithNoMembers), 15 для структури з чотирма членами базових типів (StructWithMembers) і 15 для структури, що агрегує дві попередні (CompositeStruct), насправді результат буде таким:

Розмір StructWithNoMembers structure = 1 Розмір StructWithMembers structure = 16

Розмір CompositeStruct structure = 24

Пояснення цьому — спосіб збереження конструкції struct компілятором у вихідному файлі, при якому компілятор застосовує вирівнювання і доповнення пропусками. Наприклад, якщо структура має розмір 3 байти і встановлено вирівнювання по 4-байтним межам, компілятор автоматично додасть в структуру 1 байт, і оператор sizeof вкаже, що розмір структури — 4 байти. Не забувайте це враховувати при визначенні розміру структур в С#.

checked і unchecked

Ці два оператори управляють перевіркою переповнювання при виконанні математичних операцій.

Математичні оператори

С#, як і більшість інших мов, підтримує основних математичних операторів: множення (*), ділення (/), складання (+), віднімання (—) і модуль (%). Призначення перших чотирьох операторів зрозуміле з їх назв; оператора модуля формує залишок від цілочисельного ділення. Ось код, що ілюструє застосування математичних операторів:

using System;

class MathOpsApp

{

public static void MAINQ

{

// Клас System.Random є частиною бібліотеки класів // .NET Framework. У його конструкторі за умовчанням // метод Next використовує поточну дату/час як // початкового значення. Random rand = new RANDOMO; int а, b, з;

а = rand.Next() % 100; // Граничне значення 99. b = rand.NextO % 100; // Граничне значення 99.

Console.WriteLine("a={0} b={1}", а, b);

з = а * b;

Console.WriteLineC'a * b = {0}", з);

// Відмітьте, що тут використовуються цілі числа. // Отже, якщо а менше Ь, результат завжди // буде 0. Для отримання точнішого результату // потрібно застосовувати змінні типу double або float, з = а / b; Console.WriteLineC'a / b = {0}", з);

з = а + b;

Console.WriteLineC'a + b = {0}", з);

з = а - b;

Console.WriteLineC'a - b = {0}", з);

з = а X b;

Console.WriteLineC'a X b = {0}", з); > >

Унарні оператори

Унарних операторів два: плюс і мінус. Оператор унарного мінуса указує компілятору, що число негативне. Таким чином, в наступному коді а буде рівне —42:

using System; using System;

class UnarylApp {

public static void Main()

{

int а = 0;

а = -42;

Console.WriteLine("{0}", a); } }

Проте в цьому коді з'являється невизначеність: using System;

class Unary2App <

public static void Main() {

int а; int b = 2; int з = 42;

а = b * -с;

Console.WriteLine("{0}", a); > >

Вираз а = b * -с не зовсім зрозуміло. Знову повторю, що використання дужок прояснить цей вираз:

// При використанні дужок очевидно, що ми // множимо b на негативне число з. а = b * (-с);

Якщо унарний мінус повертає від’ємне значення операнда, можна подумати, що унарний плюс повертає позитивне. Проте унарний плюс лише повертає операнд в його первинній формі і більше нічого не робить, тобто не впливає на операнд. Наприклад, виконання цього коду приведе до виведення значення -84:

using System;

class UnarySApp {

public static void MAINQ {

int а; int b = 2; int з = -42;

а = b * (+c);

Console.WriteLine("{0}", a); } }

Для набуття позитивного значення служить функція Math.Abs. Цей код виведе значення 84:

using System;

class Unary4App

{

public static void Main()

{

int а; int b = 2; int з = -42;

а = b * Math.Abs(c); Console.Writel_ine("{0}", a); } }

Останній унарний оператор, якого я згадував, — це Т(х). Це різновид оператора «дужки», що дозволяє приводити один тип до іншого.

Оператор присвоювання

Як у мові С++, так й в C# присвоювання формально вважається операцією. Разом з тим запис:

X = expr;

варто вважати дійсним оператором присвоювання, так само, як й одночасне присвоювання зі списком змінних у лівій частині:

X1 = X2 = ... = Xk = expr;

Клас Math, що містить стандартні математичні функції, містить два статичні поля, що задає константи е й π, а також 23 статичних методу. Методи задають:

  •  тригонометричні функції - Sin, Cos, Tan;
  •  зворотні тригонометричні функції - ASin, ACos, ATan, ATan2 (sinx, cosx);
  •  гіперболічні функції - Tanh, Sinh, Cosh;
  •  експоненту й логарифмічні функції - Exp, Log, Log10;
  •  модуль, корінь, знак - Abs, Sqrt, Sign;
  •  функції округлення - Ceiling, Floor, Round;
  •  мінімум, максимум, ступінь, залишок - Min, Max, Pow, IEEERemainder.

Оператор вводу

int k = Console.ReadLine(); (помилка)

string F = Console.ReadLine();

r = Convert.ToDouble(F);

m = float.Parse(Console.ReadLine());

Оператор виводу

Console.WriteLine("m=: " + k);

Блок або складовий оператор

За допомогою фігурних дужок кілька операторів мови (можливо, що перемежовують оголошеннями) можна об'єднати в єдину синтаксичну конструкцію, названу блоком або складовим оператором:

{

оператор_1

...

оператор_N

}

У мовах програмування немає загальноприйнятої норми для використання символу крапки з комою при записі послідовності операторів. Є три різних підходи і їхня варіація. Категоричні супротивники крапок з комою вважають, що кожен оператор повинний записуватися в окремому рядку (для довгих операторів визначаються правила перенесення). У цьому випадку крапки з комою (або інші аналогічні роздільники) не потрібні. Гарячі шанувальники крапок з комою вважають, що крапкою з комою повинний кінчатися кожен оператор. У результаті в операторі if перед else з'являється крапка з комою. Треті думають, що крапка з комою відіграє роль роздільника операторів, тому перед else її не повинно бути.

Синтаксично блок сприймається як одиничний оператор і може використатися всюди в конструкціях, де синтаксис вимагає одного оператора. Тіло циклу, галузі оператора if, як правило, представляються блоком. Приведу досить формальний і злегка заплутаний приклад, де тіло процедури представлене блоком, у якому є вбудовані блоки, що задають тіло оператора циклу for і тіла галузей оператора if:

/// <summary>

/// демонстрація блоків (складових операторів)

/// </summary>

public void Block()

{

int limit = 100;

int x = 120, у = 50;

int sum1 =0, sum2=0;

for (int i = 0; i< 11; i++)

{

int step = Math.Abs(limit -х)/10;

if (x > limit)

{x -= step; у += step;}

else

{x += step; у -= step;}

sum1 += x; sum2 +=y;

}

//limit = step; //змінна step перестала існувати

//limit = i; // змінна i перестала існувати

Console.WriteLine("x= {0}, y= {1}, sum1 ={2}, sum2 = {3}",

x,y,sum1,sum2);

}

Помітьте, тут у тіло основного блоку вкладений блок, що задає тіло циклу, у якому оголошені дві локальні змінні - i й step.

У свою чергу, у тіло циклу вкладені блоки, пов'язані з галузями then й else оператора if. Закоментовані оператори, що коштують відразу за закінченням циклу, нагадують, що відповідні локальні змінні, певні в блоці, перестають існувати по його завершенні.

Наведена процедура Block є методом класу Testing, що входить у проект Statements, створений для роботи із прикладами цієї лекції. Від опису полів і конструктора класу Testing:

/// <summary>

/// Клас Testing - тестуючий клас. Представляє набір

/// скалярних змінних і методів, що тестують роботові

/// з операторами, процедурами й функціями C#.

/// </summary>

public class Testing

{

public Testing(string name, int age)

{

this.age = age;

this.name = name;

}

//поля класу

public string name;

public int age;

 

private int period;

private string status;

}

Порожній оператор

Порожній оператор - це "порожньо", що завершується крапкою з комою. Іноді корисно розглядати відсутність операторів як існуючий порожній оператор. Синтаксично припустимо ставити зайві крапки з комою, думаючи, що уставляються порожні оператори. Наприклад, синтаксично припустима наступна конструкція:

for (int j=1; j<5; j++)

{;;;};

Вона може розглядатися як затримка за годиною, робота на неодруженому ході.

Оператори вибору

У мові C# для вибору однієї з декількох можливостей використовуються дві конструкції - if й switch. Першу з них звичайно називають альтернативним вибором, другу - розбором випадків.

Оператор if

Почнемо із синтаксису оператора if:

if(вираження_1) оператор_1

else if(вираження_2) оператор_2

...

else if(вираження_K) оператор_K

else оператор_N

Які особливості синтаксису слід зазначити? Вираження if повинні полягати в круглі дужки й бути булевого типу. Точніше, вираження повинні давати значення true або false. Нагадаю, арифметичний тип не має явних або неявних перетворень до булевого типу. За правилами синтаксису мови З++, then-галузь оператора треба відразу за круглою дужкою без ключового слова then, типового для більшості мов програмування. Кожний з операторів може бути блоком - зокрема, if-оператором. Тому можливо і такі конструкції:

if(вираження1) if(вираження2) if(вираження3)...

Галузі else й if, що дозволяють організувати вибір з багатьох можливостей, можуть бути відсутнім. Може бути опущена й заключна else-галузь. У цьому випадку коротка форма оператора if задає альтернативний вибір - робити або не робити - виконувати або не виконувати then-оператор.

Семантика оператора if проста й зрозуміла. Вирази if перевіряються в порядку їхнього написання. Як тільки отримане значення true, перевірка припиняється й виконується оператор (це може бути блок), якому треба за виразом, що взяли значення true. Із завершенням цього оператора завершується й оператор if. Галузь else, якщо вона є, ставитися до найближчого відкритого if.

В C# існують наступні логічні оператори:

Оператор

Опис

Приклад

&&

Логічне И. Результат дорівнює true, тільки якщо обоє операнда рівні true

(x==8) && (y==5)

||

Логічне АБО. Результат дорівнює false, тільки якщо обоє операнда рівні false

(y>8) || (y<5)

!

Заперечення. Змінює логічне значення на протилежне

if(!(a==b))...

Оператор switch

Часткою, але важливим випадком вибору з декількох варіантів є ситуація, при якій вибір варіанта визначається значеннями деякого вираження. Відповідній оператор в C# називається оператором switch. Його синтаксис:

switch(вираження)

{

case константне_вираження_1: [оператори_1 оператор_переходу_1]

...

case константне_вираження_K: [оператори_K оператор_переходу_K]

[default: оператори_N оператор_переходу_N]

}

Галузь default може бути відсутнім. Помітьте, по синтаксису припустимо, щоб після двокрапки випливала порожня послідовність операторів, а не послідовність, що закінчується оператором переходу. Константні вираження в case повинні мати тій же тип, що й switch-вираження.

Семантика оператора switch дещо заплутана. Спочатку обчислюється значення switch-вираження. Потім воно по черзі в порядку проходження case рівняється на збіг з константними вираженнями. Як тільки досягнутий збіг, виконується відповідна послідовність операторів case-галузі. Оскільки останній оператор цієї послідовності є оператором переходу (найчастіше це оператор break), то звичайно він завершує виконання оператора switch. Використання операторів переходу - це погана ідея. Таким оператором може бути оператор goto, що передає керування іншої case-галузі, що, у свою чергу, може передати керування ще куди-небудь, одержуючи блюдо "спагетті" замість добре структурованої послідовності операторів. Семантика ускладнюється ще й тим, що case-галузь може бути порожньою послідовністю операторів. Тоді у випадку збігу константного вираження цієї галузі зі значенням switch- послідовність), інакше виникне помилка періоду компіляції.

Розбір випадків - часто зустрічається ситуація в самих різних завданнях. Застосовуючи оператор switch, пам’ятайте про недоліки його синтаксису, використайте його в правильному стилі. Закінчуйте кожну case-галузь оператором break, але не застосовуйте goto.

Коли розбір випадків припускає перевірку влучення в деякий діапазон значень, доводиться прибігати до оператора if для формування спеціальної змінної. Цей прийом демонструється в наступному прикладі, де йде робота над даними нашого класу Testing:

/// <summary>

/// Визначає період поклад від віку - age

/// Використання оператора if, що гілкується

/// </summary>

public void SetPeriod()

{

if ((age > 0)&& (age <7)) period=1;

else if ((age >= 7)&& (age <17)) period=2;

else if ((age >= 17)&& (age <22)) period=3;

else if ((age >= 22)&& (age <27)) period=4;

else if ((age >= 27)&& (age <37)) period=5;

else period =6;

}

Цей приклад демонструє застосування оператора if, що дає можливість виконати дію при умові в діапазоні значень. Зі змістовної точки зору він цікавий тим, що в поля класу довелося ввести спеціальну змінну period, що дозволяє надалі використати розбір випадків поклад від періоду життя:

/// <summary>

/// Визначає статус покладу від періоду - period

/// Використання розбору випадків - оператора Switch

/// </summary>

public void SetStatus()

{

switch (period)

{

case 1:

status = "child";

break;

case 2:

status = "schoolboy";

break;

case 3:

status = "student";

break;

case 4:

status = "junior researcher";

break;

case 5:

status = "senior researcher";

break;

case 6:

status = "professor";

break;

default :

status = "не визначений";

break;

}

Console.WriteLine("Ім'я = {0}, Вік = {1}, Статус = {2}",

name, age, status);

}//SetStatus

Цей приклад демонструє коректний стиль використання оператора switch. У наступному прикладі показана роль порожних послідовностей операторів case-галузей для організації списку виражень одного варіанта:

/// <summary>

/// Розбір випадків з використанням списків виражень

/// </summary>

/// <param name="operation">операція над аргументами</param>

/// <param name="arg1">перший аргумент бінарної операції</param>

/// <param name="arg2">другий аргумент бінарної операції</param>

/// <param name="result">результат бінарної операції</param>

public void ExprResult(string operation,int arg1, int arg2

ref int result)

{

switch (operation)

{

case "+":

case "Plus":

case "Плюс":

result = arg1 + arg2;

break;

case "-":

case "Minus":

case "Мінус":

result = arg1 - arg2;

break;

case "*":

case "Mult":

case "Помножити":

result = arg1 * arg2;

break;

case "/":

case "Divide":

case "Div":

case "розділити":

case "Діліті":

result = arg1 / arg2;

break;

default:

result = 0;

Console.WriteLine("Операція не визначена");

break;

}

Console.WriteLine ("{0} ({1}, {2}) = {3}",

operation, arg1, arg2, result);

}//ExprResult

Оператори переходу

Операторів переходу, що дозволяють перервати природний порядок виконання операторів блоку, у мові C# :

Оператор goto

Оператор goto має простий синтаксис і семантику:

goto [мітка|case константний_вираз|default];

Всі оператори мови C# можуть мати мітку - унікальний ідентифікатор, що передує операторові й відділений від нього символом двокрапки. Передача керування позначеному операторові - це класичне використання оператора goto. Два інших способи використання goto (передача керування в case або default-галузь) використаються в операторі switch, про що йшла мова вище.

"Про шкоду оператора goto" і про тих, як можна обійтися без нього, писав ще Едгар Дейкстра при обґрунтуванні принципів структурного програмування.

Я вже багато років не застосовую цей оператор і вважаю, що гарний стиль програмування не припускає використання цього оператора в C# ні в якому з варіантів - ні в операторі switch, ні для організації безумовних переходів.

Оператори break й continue

У структурному програмуванні є корисним дія "переходь вперед" (але не назад), що дозволяють при виконанні деякої умови вийти із циклу, з оператора вибору із блоку. Для цієї мети можна використати оператора goto, але краще застосовувати спеціально призначені для цих цілей оператори break або continue.

Оператор break може стояти в тілі циклу або завершувати case-галузь в операторі switch. Приклад його використання в операторі switch вже демонструвався. При виконанні оператора break у тілі циклу завершується виконання самого внутрішнього циклу. У тілі циклу, найчастіше, оператор break міститься в одну з галузей оператора if, що перевіряє умову передчасного завершення циклу:

public void Jumps()

{

int i = 1, j=1;

for(i =1; i<100; i++)

{

for(j = 1; j<10;j++)

{

if (j>=3) break;

}

Console.WriteLine("Віхід із циклу j при j = {0}", j);

if (i>=3) break;

}

Console.WriteLine("Віхід із циклу i при i= {0}", i);

}//Jumps

Оператор continue використовується тільки в тілі циклу. На відміну від оператора break, що завершує внутрішній цикл, continue здійснює перехід до наступної ітерації цього циклу.

Оператор return

Ще одним оператором, що відноситься до групи операторів переходу є оператор return, що дозволяє завершити виконання процедури або функції. Його синтаксис:

return [вираження];

Для функцій його присутність й аргумент обов'язкові, оскільки вираження в операторі return задає значення, що повертає функцією.

Оператори циклу

Оператор for

Його синтаксис:

for(ініціалізації; умова; список_виражень) оператор

Оператор, що розміщений після закриваючої дужки, задає тіло циклу. У більшості випадків тілом циклу є блок. Скільки разів буде виконуватися тіло циклу, залежить від трьох керуючих елементів, заданих у дужках. Ініціалізації задають початкове значення однієї або декількох змінних, часто названих лічильниками або просто змінними циклу. У більшості випадків цикл for має один лічильник, але часто корисно мати кілька лічильників, що й буде продемонстровано в наступному прикладі. Умова задає закінчення циклу, що відповідає вираження при обчисленні повинне одержувати значення true або false. Список виражень, записаний через кому, показує, як міняються лічильники циклу на кожному кроці виконання. Якщо умова циклу істинна, то виконується тіло циклу, потім змінюються значення лічильників і знову перевіряється умова. Як тільки умова стає помилковою, цикл завершує свою роботу. У циклі for тіло циклу може жодного разу не виконуватися, якщо умова циклу false після ініціалізації, а може відбуватися зациклення, якщо умова завжди залишається true. У нормальній ситуації тіло циклу виконується кінцеве число разів.

Лічильник циклу найчастіше оголошуються безпосередньо в ініціалізації й відповідно є змінними, локалізованими в циклі, так що після завершення циклу перестають існувати.

У тих випадках, коли передбачається можливість передчасного завершення циклу за допомогою одного з операторів переходу, лічильники оголошуються до циклу, що дозволяє аналізувати їхні значення при виході із циклу.

for (int i = 1; i <= 5; i=i+1)

{

Console.WriteLine(i);

}

Як приклад розглянемо класичне завдання: чи є рядок тексту паліндромом. Нагадаю, паліндромом називається симетричний рядок тексту, що читається однаково ліворуч праворуч і праворуч ліворуч. Для її рішення цикл for підходить щонайкраще: тут використаються два лічильники - один зростаючий інший спадаючий. Від тексту відповідної процедури:

/// <summary>

/// Визначення паліндромів. Демонстрація циклу for

/// </summary>

/// <param name="str">текст</param>

/// <returns>true - якщо текст є паліндромом</returns>

public bool Palindrom(string str)

{

for (int i =0,j =str.Length-1; i<j; i++,j--)

if(str[i]!=str[j]) return(false);

return(true);

}//Palindrom

Циклі While

Цикл while (вираження) є універсальним виглядом циклу, що включають в усі мови програмування. Тіло циклу виконується доти, поки залишається true вираження while. У мові C# у цього вигляду циклу дві модифікації - з перевіркою умови на початку і наприкінці циклу. Перша модифікація має наступний синтаксис:

while(вираження) оператор

Ця модифікація відповідає стратегії: "спочатку перевір, а потім роби". У результаті перевірки може виявитися, що й робити нічого не потрібно. Тіло такого циклу може жодного разу не виконуватися. Звичайно ж, можливо й зациклення. У нормальній ситуації кожне виконання тіла циклу - це черговий крок до завершення циклу.

Цикл, що перевіряє умову завершення наприкінці, відповідає стратегії: "спочатку роби, а потім перевір". Тіло такого циклу виконується, щонайменше, один раз. Синтаксис цієї модифікації:

do

оператор

while(вираження);

int n = 1;

while (n < 6)

{

Console.WriteLine("Current value of n is {0}", n);

n++;

}

 

int n = 1;

while (n++ < 6)

{

Console.WriteLine("Current value of n is {0}", n);

}

int x = 0;

 do

{

Console.WriteLine(x);

x++;

} while (x < 5);

Приведу приклад, у якому присутні обидві модифікації циклу while. У зовнішньому циклі перевірка виконується наприкінці, у внутрішньому - на початку. Зовнішній цикл являє собою типовий зразок організації навчальних програм, коли в діалозі з користувачем багаторазово вирішується деяке завдання. На певному кроці користувач відводити нові дані, вирішує завдання й аналізує отримані дані. У його владі, продовжити обчислення чи ні, але хоча б один раз вирішити завдання йому доводитися. Внутрішній цикл do while використовується для рішення вже відомого завдання з паліндромами. Текст відповідної процедури:

/// <summary>

/// Два цикли: з перевіркою наприкінці й на початку.

/// Зовнішній цикл - зразок багаторазово розв'язуваного завдання.

/// Завершення циклу визначається в діалозі

/// з користувачем.

/// </summary>

public void Loop()

{

string answer, text;

do

{

Console.WriteLine("Уведіть слово");

text = Console.ReadLine();

int i =0, j = text.Length-1;

while ((i<j) && (text[i]== text[j]))

{i++; j--;}

if (text[i]== text[j])

Console.WriteLine(text +" - це паліндром!");

else

Console.WriteLine(text +" - це не паліндром!");

Console.WriteLine("Продовжімо? (yes/no)");

answer = Console.ReadLine();

}

while(answer =="yes");

}//Loop

Цикл foreach

Новим вигляд циклу є цикл foreach, зручний при роботі з масивами, колекціями й іншими подібними контейнерами даних. Його синтаксис:

foreach(тип ідентифікатор in контейнер) оператор

Цикл працює в повній відповідності зі своєю назвою - тіло циклу виконується для кожного елемента в контейнері. Тип ідентифікатора повинний бути погоджений з типом елементів, що зберігаються в контейнері даних. Передбачається також, що елементи контейнера (масиву, колекції) упорядковані. На кожному кроці циклу ідентифікатор, що задає поточний елемент контейнера, одержує значення чергового елемента відповідно до порядку, установленим на елементах контейнера. Із цим поточним елементом і виконується тіло циклу - виконується стільки разів, скільки елементів перебуває в контейнері. Цикл закінчується, коли повністю перебрані всі елементи контейнера.

Серйозним недоліком циклів foreach у мові C# є ті, що цикл працює тільки на читання, але не на запис елементів. Так що наповнювати контейнер елементами доводитися за допомогою інших операторів циклу.

int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };

 foreach (int i in fibarray)

{

System.Console.WriteLine(i);

}

У наведеному нижче прикладі показана робота із тривимірним масивом. Масив створюється з використанням циклів типу for, а при знаходженні суми його елементів, мінімального й максимального значення використається цикл foreach:

/// <summary>

/// Демонстрація циклу foreach. Обчислення суми

/// максимального й мінімального елементів

/// тривимірного масиву, заповненого випадковими числами.

/// </summary>

public void SumMinMax()

{

int [,,] arr3d = new int[10,10,10];

Random rnd = new Random();

for (int i =0; i<10; i++)

for (int j =0; j<10; j++)

for (int до =0; k<10; k++)

arr3d[i,j,k]= rnd.Next(100);

long sum =0; int min=arr3d[0,0,0], max=arr3d[0,0,0];

foreach(int item in arr3d)

{

sum +=item;

if (item > max) max = item;

else if (item < min) min = item;

}

Console.WriteLine("sum = {0}, min = {1}, max = {2}",

sum, min, max);

}//SumMinMax

Задача 7.1.

Написати програму: Обчислити значеня функції , коли х міняється від А до В з кроком H. Результати вивести у вигляді таблиці " № розр.- Х- У". Врахувати не значимі значення аргументу. Використати відомі методи організації циклів.


 

А также другие работы, которые могут Вас заинтересовать

19366. Податок на прибуток підприємств 112.08 KB
  Тема 5: Податок на прибуток підприємств Загальна характеристика податку на прибуток Платники та об’єкт оподаткування Склад доходів та порядок їх визнання Склад витрат та порядок їх визнання Порядок нарахування амортизації Ставки податку на прибуток ...
19367. Податок на доходи фізичних осіб 129.21 KB
  Тема 6: Податок на доходи фізичних осіб Платники та об’єкт оподаткування Види доходів що включаються і не включаються до загального оподатковуваного доходу Податкові соціальні пільги Податкова знижка Ставки податку та особливості оподакування окре...
19368. Плата за землю 113.24 KB
  Тема 7: Плата за землю Загальна характеристика плати за землю Платники об’єкт оподаткування та ставки плати за землю Пільги щодо сплати за землю порядок сплати до бюджету 24 зведеного бюджету Платники: Фізичні особи – власники землі і землекористу...
19369. Екологічне оподаткування 132.41 KB
  Тема 8: Екологічне оподаткування Система екологічного оподаткування Екологічний податок Збір за першу реєстрацію транспортного засобу Рентна плата за нафту природний газ і газовий конденсат що видобуваються в Україні Рентна плата за транспорттуванн
19370. Платежі за ресурси 112.72 KB
  Тема 9: Платежі за ресурси Збір за спеціальне використання води Збір за використання лісових ресурсів Плата за користування ресурсами Збір за користування радіочастотним ресурсом Платники збору – водокористувачі: Юридичні особи Фізичні особи – підп
19371. Міни спеціального призначення 28.5 KB
  Міни спеціального призначення: а освітлювальна міна б димова міна Основні складові частини: оболонка; запалюючий стакан; вибуховий заряд; димоутворююча речовина; стабілізатор; виштовхуючий заряд; діафрагма; смолоскип; парашут; нап...
19372. Дивизионная артиллерийская ремонтная мастерская ДАРМ-70 38 KB
  Дивизионная артиллерийская ремонтная мастерская ДАРМ70 Предназначена для проведения текущего ремонта артиллерийского вооружения в полевых условиях. Принята на вооружение в 1975 г. в начале 80х гг. появился несколько улучшенный вариант ДАРМ70М.ДАРМ70 состоит на осна...
19373. Автоматичні лінії з агрегатних верстатів та нормалізованих вузлів 86.5 KB
  ЛАБОРАТОРНА РОБОТА №1 Автоматичні лінії з агрегатних верстатів та нормалізованих вузлів. Мета роботи: 1. Ознайомлення з роботою лінії та її устаткуванням. 2. Вивчення принципу керування і послідовності роботи механізму лінії. 3. Вивчення конструкції та принципу ді
19374. ЗНЯТТЯ ЦИКЛОГРАМИ АВГОМАТИЧНОЇ ЛІНІЇ 134 KB
  ЛАБОРАТОРНА РОБОТА №2 ЗНЯТТЯ ЦИКЛОГРАМИ АВГОМАТИЧНОЇ ЛІНІЇ Мета роботи: Визначення тривалості окремих складових циклу роботи автоматйчної лінії. Побудувати циклограму роботи автоматичної лінії. Теоретичні відомості. Для б