Структура switch

Розглянемо наступний оператор, що організовує розгалуження. Це оператор switch, який представляє з себе альтернативний спосіб опису умови if з перевіркою якогось виразу на різні значення.

Розглянемо наступний оператор, що організовує розгалуження. Це оператор switch, який представляє з себе альтернативний спосіб опису умови if з перевіркою якогось виразу на різні значення. Синтаксис цього оператора представлений нижче.

switch (вираз) {
    case значення1: ...... break;
    case значення2:
    case значенняЗ: ...... break;
    default: ...... break;
}

Під виразом розуміється будь-який вираз, який має цілий тип або тип даних char, enum чи string.
Цей оператор обчислює значення виразу і починає проходити по всіх мітках case, порівнюючи значення міток із значенням виразу.Якщо програма знайшла таку мітку, то виконуються всі оператори, які знаходяться після цієї мітки до оператора break, після якого здійснюється перехід в кінець оператора switch. У випадку, якщо мітка не знайдена, то перехід здійснюється на мітку default. Мітка default може бути відсутньою, тоді перехід здійснюється відразу в кінець оператора switch.

char temperature;
            //......
            switch (temperature)
            {
                case 'C': Console.WriteLine("Celsius"); break;
                case 'F': Console.WriteLine("Farenheit"); break;
                case 'K': Console.WriteLine("Kelvin"); break;
                default: Console.WriteLine("Unknown"); break;
            }

Якщо необхідно виконати один и той же блок коду для декількох значень, то для цього записують послідовність case виразів. В цьому випадку працює механізм відсутності оператора break, тобто в прикладі нижче, вирази приймають значення 'с', то перехід здійснюється на мітку case 'с':, але операторів після цієї мітки немає і немає оператора break, тому виконуються всі оператори підряд, тобто ті, що йдуть після мітки case 'С':

  char temperature;
            //......
            switch (temperature)
            {
                case 'c':
                case 'C': Console.WriteLine("Celsius"); break;
                case 'f':
                case 'F': Console.WriteLine("Farenheit"); break;
                case 'k':
                case 'K': Console.WriteLine("Kelvin"); break;
                default: Console.WriteLine("Unknown"); 
            }
        }


Зауважимо, що мітки, які вказані в case, повинні бути унікальними.
На відміну від інших мов програмування, у вас є можливість використовувати goto-оператор для переходу на інші мітки в операторі switch.   

switch (someChar)
{
    case 'a' ......
    goto case 'c';
    case 'b': ......
    break;
    case 'с': ......
    goto default;
    default:
        ......
    break;
}

 

Структури вибору

С# підтримує дві структури вибору, це конструкція if... та конструкція switch. Завдяки цим двом операторам можна реалізовувати розгалуження у наших програмах.

Умова if...

Розглянемо синтаксис цієї конструкції.

if(вираз)
{
……
//блок1
}
else
{
……
//блок 2
}

Вираз в дужках повертає значення або істина (true), або фальш (false), тобто значення типу boolean. Якщо вираз істинний, то виконуються оператори, які стоять в блоці 1, якщо вираз хибний, то виконуються оператори, що стоять в блоці 2.

Оператора if можна використовувати і без оператора else:

if(вираз)
{
……
//блок1
}

В цьому випадку виконуються оператори, що стоять в блоці 1, якщо вираз істинний; якщо вираз помилковий, то жоден з операторів блоку if не виконується.
Розглянемо приклад.

using System;
class StatementDemo01
{
    public static Main()
    {
        Console.WriteLine("Input first string:");
        string firstString=Conole.ReadLine();
        Console.WriteLine("Input second string:");
        string secondString=Console.ReadLine();
        if (firstString.Equals(secondString)) {
            Console.WriteLine("First string is equals second string");
        }
        else {
            Console.WriteLine ("First string is not equals second string");
        }
    }
}

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

//приклад 1
if(x==0) {
    х=х+10;
}
//приклад 2
if(x==0)
    х=х+10;

Якщо необхідно зробити вибір більш ніж між двома варіантами, то існує складніша версія умови if з множинним вибором. Для побудови таких конструкцій використовується вираз else if.

if (x<0) {
    х=х+10;
}
else if (x>10) {
    х=х-10;
    }
    else {
        х=5;
    }

В даному прикладі відбувається перевірка умови в першому if, і якщо умова істинна, то виконується код x=x+10, після чого здійснюється перехід на оператор, що йде за всім блоком if. У випадку, якщо перша умова помилкова, перевіряється умова в другому блоці if, і якщо воно повертає значення true, то виконується код х=х-10. Якщо жодна з умов не повернула значення true, то перехід здійснюється в блок else. Важливим є те, що після виконання операторів в одному з блоків оператора if програма переходить відразу на оператор, що йде за if, навіть якщо умови в нижчестоящих блоках цього оператора істинні.
Структури if можуть бути вкладені один в одного:

if (x<10) {
    if (y<5) {
        y=y+х;
        }
    else {
        у=у-х;
        }
}

Відзначимо, що на відміну від мови C++ тип int не приводиться автоматично до типу boolean, тому ми не можемо використовувати конструкцію, допустиму в C++:

int i=0;
  ……
if(i)  //помилка 
{
  ……
}

Таким чином, необхідно використовувати вирази, що повертають значення типу boolean, або перетворювати до цього типу явно.
У прикладах вище ми використовували тільки прості вирази у вигляді умов, насправді частіше доводиться комбінувати декілька виразів за допомогою логічних операторів.
Припустимо, що у нас є два вирази — X і У, які повертають значення типу boolean. Нижче приведена таблиця, яка показує, що відбуватиметься, якщо Ми почнемо комбінувати ці вирази за допомогою логічних операцій.

 

 X X&&Y  X||Y 
true  true   true   true  
true  alse  false true 
false true  false true
false false false false

Припустимо, нам необхідно перевірити, чи потрапляє змінна а в інтервал від -10 до 10. Для цього ми можемо написати наступний код, в якому ми використовуємо логічну операцію «і»:

using System;
class StatementDemo02
{
    static void Main() {
        double а;
        a=Convert.ToInt32 (Console.ReadLine ());
        if ((a>-10)&&(a<10)) {
            Console.WriteLine("а is in (-10;10)");
        }
        else {
            Console.WriteLine("а is not in (-10; 10)");
        }
    }
}

Припустимо, що ми хочемо перевірити, чи потрапляє а в інтервал, який не містить проміжок [-10;10].

using System;
class StatementDemo03 {
    static void Main()
    {
        double а;
        a=Convert.ToInt32(Console.ReadLine());
        if ((a<-10)||(a>10)) {
            Console.WriteLine("а is in (-10;10)");
        }
        else {
            Console.WriteLine("а is not in (-10;10)");
        }
    }
}

В даному прикладі ми використовували логічну операцію «або». Умови можуть бути значно складніше по своїй структурі.

Перетворення типів

У С# існують два варіанти приведення типів: явне приведення і неявне.

У С# існують два варіанти перетворення типів: явне приведення і неявне.

Неявне перетворення

Як і в інших мовах програмування, існує неявне приведення типів. Так, наприклад, якщо ви використовуєте вираз, який має тип int, а результат його ви хочете помістити в змінну типу double, то програма автоматично розширить вашу змінну до необхідного розміру, причому самі дані не будуть втрачені: 

using System;
class CastDemo 
{
    static void Main() 
    {
        int iValue=5; 
        double dValue; 
        dValue=iValue; // dValue набуде значення 5 
        Console.WriteLine ("dValue ={0} ",dValue);
    }
}

Явне перетворення

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

using System;
class CastDemo2 
{ 
    static void Main() 
    { 
        double nVar1=6.489; 
        int nVar2=nVar1; 
        Console.WriteLine("nVar2={0}",nVar2); 
        } 
    } 
}

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

using System;
class CastDemo3
{ 
    static void Main() 
    { 
        double nVar1=6.489; 
        int nVar2=(int)nVar1; 
        Console.WriteLine("nVar2={0}",nVar2); 
        } 
    } 
}

Результатом роботи цієї програми буде число 6. Таким чином, частина даних втрачена. Можна використовувати оператор checked для перевірки цілісності даних в змінних, і, у разі втрати інформації, викидуватиметься виключення.

using System;
class CastDemo4 
{ 
    static void Main() 
    { 
        double nVar1=6.489; 
        checked { 
            int nVar2=(int) nVar1; 
            Console.WriteLine("nVar2={0}",nVar2); 
        } 
    } 
}

 

Оператори у C#

Оператори дозволяють обробляти прості типи даних і об&#39;єкти. Вони отримують в якості вхідного один або більше операндів і повертають деяке значення як результат.
Кожна мова програмування використовує оператори, через яких ми можемо виконувати різні дії над даними. Розглянемо оператори в C# і спробуємо розібратися для чого вони потрібні і як вони використовуються.

Що таке оператор?

Після того, як ми дізналися, як оголошувати і встановлювати змінні ми розповімо про те, як виконувати різні операції з ними. Для цієї мети ми будемо знайомитися з операторами.
Оператори дозволяють обробляти прості типи даних і об'єкти. Вони отримують в якості вхідного один або більше операндів і повертають деяке значення як результат.
Оператори в C# є спеціальними символами (такі як "+", ".", "^", і т. д.) і вони виконують перетворення над одним, двома або трьома операндами. Прикладами операторів C# є математичні знаки додавання, віднімання, множення і ділення (+, -, *, /) і відповідні операції, які вони виконують на цілими і дійсними числами. 

Оператори в C#

 
Оператори в C# можна поділити на декілька різних категорій: 
  • Арифметичні оператори – так як і в математиці, служать для виконання простих арифметичних операцій.
  • Оператори присвоювання – дозволяють присвоювання значень змінних.
  • Оператори порівняння – дають можливість порівняти два літерала та/або змінних.
  • Логічні оператори – оператори для роботи з логічними типами даних та логічними виразами.
  • Побітові (бітові) оператори використовуються для виконання операцій на двійковим представлення числових даних.
  • Оператори перетворення типів – дозволяють перетворення даних з одного типу в інший.

Категорії операторів

Далі подано список операторів за категоріями:

Категорії

Оператори

Арифметичні

-, +, *, /, %

Інкремент (декремент)

++, --

Логічні

&&, ||, !, ^

Бітові

&, |, ^, ~, <<, >>

Порівняння

==,!=, >, <, >=, <=

Присвоєння

=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

Об’єднання рядків

+ (конкатенація)

Перетворення типів

(type), as, is, typeof, sizeof

Індексні, лямбда-числення, інші

[],=>,., new, (), [], ?:, ??

Класифікація операторів за числу аргументів

Оператори також поділяються за числом аргументів

Тип оператора исло аргументів)

Приклади

Первинні (постфіксні)

Math.Abs(x)-виклик методу

Унарний, один

-x, y++, !x

Бінарний, два

x+y, x>y, x&&y

Тернарний, три

(a>b) ? c : d

 

Усі бінарні оператори в C# є лівоасоціативним, тобто вирази обчислюються зліва направо, за винятком операторів присвоювання. Всі оператори присвоювання та умовні оператори ?: і ?? є правоасоціативними, тобто вирази обчислюються справа наліво. Унарні оператори не є асоціативними.

В залежності від типів даних, над якими виконується дія, знаки операторів мають різний сенс. Класичним прикладом у цьому випадку є оператори + та /.

Приклад

double result = (2+3)/2;
string greetings = "Hello ";
string company = "Microsoft!";
Console.WriteLine("{0} {1}", result, greetings + company );

У цьому прикладі знак + виконує додавання для чисел і конкатенацію для рядків, а знак / виконує цілочисельне ділення і результат буде 2, а не 2.5.

Приорітет операцій у C#

Деякі оператори мають перевагу (пріоритет) над іншими. Наприклад, в математиці множення має пріоритет над додаванням. Оператори з вищим пріоритетом обчислюються раніше тих, що мають нижчий пріоритет. Оператор ()  використовується, щоб змінити пріоритет, і, як в математиці, його вміст обчислюється в першу чергу.

У наступній таблиці подано пріоритети операцій від найвищого до найнижчого:

Категорія

Оператори

Первинні

x.y  f(x)  a[x]  x++  x--  new typeof  checked  unchecked

Унарні

+  -  !  ~  ++x  --x  (T)x

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

*  /  %

Аддитивні

+  -

Зсуву

<<  >>

Відношення і визначення типу

<  >  <=  >=  is  as

Рівності

==  !=

Логічне AND

&

Логічне XOR

^

Логічне OR

|

Умовне AND

&&

Умовне OR

||

Умовне

?:

Присвоєння

=  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=

 

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

Арифметичні оператори.

Арифметичні оператори в C# +, -, * такі ж, як у математиці. Вони виконують додавання, віднімання та множення числових значень і результат також числове значення.

Оператор ділення має різний вплив на цілі і дійсні числа. Коли ми ділимо ціле на ціле число (наприклад, int, long і sbyte) результуюче значення є також цілим числом (без округлення дробової частини). Нагадаємо, що таке ділення називається цілочисельним. Приклад цілочисельного ділення: 7 / 3 = 2.

Цілочисельне ділення на 0 не допускається і призводить до виникнення виняткової ситуації під час виконання програми (runtime exception) DivideByZeroException. Остачу від ділення цілих чисел можна отримати оператором %.

Наприклад, 7 % 3 = 1, і -10 % 2 = 0.

 

При діленні двох дійсних чисел або двох чисел, одне з яких є дійсним (наприклад, float, double, і т. д.), результат буде дійсним числом з цілою і дробовою частиною. Наприклад: 5.0 / 2 = 2.5. У діапазоні дійсних чисел допускається ділення на 0.0 і відповідно результат +∞ (нескінченність), -∞ (нескінченності) або NaN (неприпустиме значення, Not a Number).

Оператор інкременту ++ додає одиницю до значення змінної, відповідно оператор декременту -- віднімає одиницю значення. Для даних операторів існує префіксна і постфіксна (суфіксна) форма.

Коли ми використовуємо оператори ++ і – як префікс, то спочатку обчислюється нове значення, а потім повертається результат. При постфіксній(суфіксній) формі спочатку повертається початкове значення операнда, а потім виконуєтся дія додавання або віднімання.

Приклад.

namespace ConsoleProgram
{
   class Program
   {
       static void Main(string[] args)
       {
           double totalCost = 120;
           int quantityOfBooks = 50;
           double averageBookPrice = totalCost / quantityOfBooks;
           double halfOfTotalCost = 1/2 * totalCost;

           Console.WriteLine(averageBookPrice); // 2.5
           Console.WriteLine(halfOfTotalCost); // 0

           halfOfTotalCost = totalCost * 1 / 2 ;

           Console.WriteLine(halfOfTotalCost); // 60

           int numberA = 12;
           int numberB = 5;

           Console.WriteLine(numberA + numberB);     // 17
           Console.WriteLine(numberA + (numberB++)); // 17
           Console.WriteLine(numberA + numberB);     // 18
           Console.WriteLine(numberA + (++numberB)); // 19
           Console.WriteLine(numberA + numberB);     // 19
           Console.WriteLine(24 / numberA);     // 2
           Console.WriteLine(24 % numberB);     // 4

           numberA = 1;
           numberB = 0;
           // Console.WriteLine(one / zero); // DivideByZeroException

           double zero = 0.0;
           Console.WriteLine("{0} / {1} = {2}", zero, zero, zero / zero);
 
           double dZero = 0.0;
           Console.WriteLine(-1.0 / zero); // -Infinity
           Console.WriteLine(1.0 / dZero); // Infinity
       }
}

 

 

Бінарні дерева і фракали

Бінарне дерево може також виступати у ролі конструктивного фрактала. Він будується за наступним прин

Бінарне дерево може також виступати у ролі конструктивного фрактала. Він будується за наступним принципом: на кожному рівні вертикальна лінія розділяється на дві з деяким показником зменшення. Такі розгалужені фрактали називаються дендритами (в перекладі з грецької « δένδρον» — дерево).

Код для побудови такого фракталу:

private void DrawTTree(int x, int y, int lenght, int level)
        {
            if (lenght < 4) return;
            var l = lenght / 2;
            var pen = new Pen(Colors[level % 5], (5-level)>1?(5-level):1);
            _graphics.DrawLine(pen,x, y, x, y - l);
            _graphics.DrawLine(pen,x, y - l, x - l, y - l);
            _graphics.DrawLine(pen,x, y - l, x + l, y - l);
            DrawTTree(x - l, y - l, l, level + 1);
            DrawTTree(x + l, y - l, l, level + 1);
        }
Існують і інші подання двійкового дерева: H-дерево і V-дерево.
 
H-дерево будується наступним чином: беремо одиничний відрізок, і на першому кроці два коротших відрізка поміщаємо перпендикулярно кінцях початкового так, щоб утворилася буква H, повторюємо дії.

 

Код для побудови такого фракталу:

 {            
            if (lenght < 20) return; 
            var l = lenght/2;            
            int x1=centerX-l, x2=centerX+l, y1=centerY-l/2, y2=centerY+l/2;
            var pen = new Pen(Colors[level], 4-level/2);            
            _graphics.DrawLine(pen, x1, centerY, x2, centerY);
            _graphics.DrawLine(pen, x1, y1, x1, y2);
            _graphics.DrawLine(pen, x2, y1, x2, y2);          
            DrawHTree(x1, y1, l, level + 1);
            DrawHTree(x1, y2, l, level + 1);
            DrawHTree(x2, y1, l, level + 1);
            DrawHTree(x2, y2, l, level + 1);
        }

 

V-дерево будується аналогічно:

 private static void DrawVTree(int centerX, int centerY, int lenght, int level)
{
            if (lenght < 2) return;
            var delta= Convert.ToInt32(lenght * Math.Sqrt(2)/2.0);
            var x1 = centerX - delta;
            var x2 = centerX + delta;
            var y = centerY - delta;
            var pen = new Pen(Colors[level%5], 2);
            _graphics.DrawLine(pen, centerX, centerY, x1, y );
            _graphics.DrawLine(pen, centerX, centerY, x2, y );
            DrawVTree(x1, y, 2*delta/3, level + 1);
            DrawVTree(x2, y, 2*delta/3, level + 1);            
}

 

Клас для роботи з Yandex Translate API

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using WindowsFormsApplication2.Properties;
 
namespace WindowsFormsApplication2
{
    public  class YandexTranslate
    {
        private readonly string _apiKey;
 
        public YandexTranslate()
        {
            _apiKey = Settings.Default.ApiKey;
        }
 
        public YandexTranslate(string key)
        {
            _apiKey = key;
        }
 
        public  List<string> GetLangs()
        {
            var requestString =
                String.Format("https://translate.yandex.net/api/v1.5/tr.json/getLangs?key={0}",
                _apiKey);
            var request = WebRequest.Create(requestString);
            var response = request.GetResponse(); 
            var yandexDataContractSerializer = new DataContractJsonSerializer(typeof(GetLangsData));
            var getLangsData = (GetLangsData)yandexDataContractSerializer.ReadObject(response.GetResponseStream());
            return getLangsData.Dirs;
        }
        public  List<string> GetLangs(string ui)
        {
            var requestString =
                String.Format("https://translate.yandex.net/api/v1.5/tr.json/getLangs?key={0}&ui={1}",
                _apiKey, ui);
            var request = WebRequest.Create(requestString);
            var response = request.GetResponse();
            var sr = new StreamReader(response.GetResponseStream());
            var json = sr.ReadToEnd();
            json = json.Remove(json.Length - 3);
            json = json.Substring(json.IndexOf("langs") + 8);
            json = json.Replace('"', ' ');            
            return json.Split(',').ToList();
        }
        public  string Detect(string text)
        {
            var requestString =
                String.Format("https://translate.yandex.net/api/v1.5/tr.json/detect?key={0}&text={1}",
                _apiKey, text);
            var request = WebRequest.Create(requestString);
            var response = request.GetResponse();
            var yandexDataContractSerializer = new DataContractJsonSerializer(typeof(DetectData));
            var detectData = (DetectData)yandexDataContractSerializer.ReadObject(response.GetResponseStream());
            return detectData.Lang;
        }
        public  List<string> Translate(string lang, string text)
        {
            var requestString =
                String.Format("https://translate.yandex.net/api/v1.5/tr.json/translate?key={0}&text={1}&lang={2}&format={3}",
                _apiKey, text, lang, "plain");
 
            var request = WebRequest.Create(requestString);
            if ((requestString.Length > 10240) && (request.Method.StartsWith("GET")))
                throw new ArgumentException("Text is too long (>10Kb)");
            var response = request.GetResponse();
 
            TranslateData translateData;
            var yandexDataContractSerializer = new DataContractJsonSerializer(typeof(TranslateData));
            try
            {
                translateData = (TranslateData)yandexDataContractSerializer.ReadObject(response.GetResponseStream());
            }
            catch (Exception exception)
            {
                translateData = new TranslateData();
                translateData.Text = new List<string>();
            }
            return translateData.Text;
        }
        [DataContract]
        internal class TranslateData
        {
            [DataMember (Name = "code")]
            internal int Code { get; set; }            
            [DataMember(Name = "lang")]
            internal string Lang { get; set; }
            [DataMember(Name = "text")]
            internal List<string> Text { get; set; }
        }
        [DataContract]
        public class GetLangsData
        {
            [DataMember(Name = "dirs")]
            internal List<string> Dirs { get; set; }
        }
        [DataContract]
        internal class DetectData
        {
            [DataMember(Name = "code")]
            internal int Code { get; set; }            
            [DataMember(Name = "lang")]
            internal string Lang { get; set; }
        }
    }
}

 

Як серіалізувати ArrayList у C#

Наведу приклад серіалізації колекції ArrayList з власних елементів MyElementClass: using Syste

Наведу приклад серіалізації колекції ArrayList з власних елементів MyElementClass:

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml.Serialization;
using System.IO; 

namespace ConsoleApplication1
{
 class Program
 {
   static void Main(string[] args)
   {
     ArrayList al = new ArrayList();
     XmlSerializer serializer=new XmlSerializer(typeof(ArrayList),new Type[] {typeof (MyElementClass )});
     al.Add(new MyElementClass());
     al.Add (new MyElementClass (2,"AAA"));
     Console.WriteLine("Writing With Stream"); 
     try
     {
        Stream writer = new FileStream("C:\A.XML", FileMode.Create);
        serializer.Serialize(writer, al);
        writer.Close();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message );
      }
  }
} 

Нижче подано код для елемента

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 

namespace ConsoleApplication1
{
  public class MyElementClass: IComparable 
  {
    public int ID;
    public string Name;
    public MyElementClass()
    {
      ID = 1;
      Name = "ABC";
    }
    public MyElementClass(int id, string name)
    {
      ID = id;
      Name = name;
    }
    public int CompareTo(object obj)
    {
       if (obj is MyElementClass)
        {
           MyElementClass otherElement = (MyElementClass)obj;
           return this.ID.CompareTo (otherElement.ID);
        }
       else
        {
          throw new ArgumentException("object is not a MyElement");
        }
   }
 }
}