Добавил:
Допоможу чим зможу) Відсигнальте якщо знайшли шось корисне) Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
75
Добавлен:
10.03.2018
Размер:
751.51 Кб
Скачать

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ

НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”

МАСИВИ. РОБОТА З МАСИВАМИ

ІНСТРУКЦІЯ ДО ЛАБОРАТОРНОЇ РОБОТИ № 7

З КУРСІВ «ТЕХНОЛОГІЇ ПРОГРАМУВАННЯ, Ч. 2»

для студентів базових напрямів 125 «Кібербезпека»

Львів – 2017

Масиви. Робота з масивами: інструкція до лабораторної роботи №7 з курсів «Технології програмування, част.2» для студентів спеціальності 125 «Кібербезпека». / Укл.: В.І. Отенко, А.І. Партика. - Львів: НУЛП, 2017.- 15с.

Укладачі: В.І. Отенко, к.т.н., доцент,

А.І. Партика, к.т.н., асистент.

2

Мета роботи – вивчити синтаксис опису і використання у програмах змінних типу масивів та властивостей. Навчитися складати та відлагоджувати програми з використанням індексаторів при роботі з масивами.

1. ОСНОВНІ ТЕОРЕТИЧНІ ВІДОМОСТІ

1.1. Масиви

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

Масив відноситься до посилальних типів даних, тобто розташовується в динамічній області пам'яті, тому створення масиву починається з виділення пам'яті під його елементи. Елементами масиву можуть бути величини як значимих, так і посилальних типів (у тому числі масиви). Масив значимих типів зберігає значення, масив посилальних типів - посилання на елементи. Всім елементам при створенні масиву привласнюються значення за замовчуванням: нулі для значимих типів й null - для посилальних.

От, наприклад, як виглядають оператори створення масиву з 10 цілих чисел і масиву з 100 рядків:

int [ ] w = new int [10] ; string[] z = new string[100];

У першому операторі описаний масив w типу int[]. Операція new виділяє пам'ять під 10 цілих елементів, і вони заповнюються нулями. У другому операторі описаний масив z типу string[]. Операція new виділяє пам'ять під 100 посилань на рядки, і ці посилання заповнюються значенням null. Пам'ять під самі рядки, що становлять масив, не виділяється – це буде необхідно зробити перед заповненням масиву.

Кількість елементів у масиві (розмірність) не є частиною його типу, ця кількість задається при виділенні пам'яті й не може бути змінене згодом. Розмірність може задаватися не тільки константою, але й виразом.

Результат обчислення цього виразу повинен бути не від’ємним, а його тип повинен мати неявне перетворення до int, uint, long або ulong.

Приклад розмірності масиву, заданої виразом: short [] = . . . ;

string [] z = new string[n + 1];

Елементи масиву нумеруються з нуля, тому максимальний номер елемента завжди на одиницю менше розмірності (наприклад, в описаному вище масиві w елементи мають індекси від 0 до 9). Для звертання до елемента масиву після імені масиву вказується номер елемента у квадратних дужках.

3

Зелементом масиву можна робити все, що припустимо для змінних того

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

Масиви одного типу можна привласнювати один одному. При цьому відбувається присвоювання посилань, а не елементів, як і для будь-якого іншого об'єкта посилального типу, наприклад:

int[ ] а = new int[10];

int[ ] b = а; // b й а вказують на той самий масив

Всі масиви в С# мають загальний базовий клас Array, визначений у просторі імен System. У ньому є кілька корисних методів, що спрощують роботу з масивами, наприклад методи одержання розмірності, сортування й пошуку.

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

1.2. Одномірні масиви

Одномірні масиви використовуються в програмах найчастіше. Варіанти опису масиву:

тип[] ім'я:

тип[] ім'я = new тип [ розмірність ]; тип[] ім'я = { список ініціалізаторів };

тип[] ім'я = new тип [] { список ініціалізаторів };

тип[] ім'я = new тип [ розмірність ] { список ініціалізаторів };

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

Приклади описів (один приклад для кожного варіанта опису):

int [ ] а

// 1

елементів немає

int [ ] b = new int [4];

// 2 елементи рівні 0

int [ ] с = { 61, 2, 5, -9 } ;

// 3

new мається на увазі

int [ ] d = new int [ ] { 61, 2, 5, -9 } ;

// 4

розмірність обчислюється

int [ ] e = new int [4] { 61, 2, 5, -9 } ;

// 5

надлишковий опис

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

У кожному з інших масивів по чотирих елементи цілого типу. Як видно з операторів 3-5, масив при описі можна ініціалізувати. Якщо при цьому не задана розмірність (оператор 4), кількість елементів обчислюється по кількості ініціалізованих значень. Для полів об'єктів і локальних змінних можна

4

опускати операцію new, вона буде виконана за замовчуванням (оператор 3). Якщо є присутнім і розмірність, і список ініціалізаторів, розмірність повинна бути константою (оператор 5) .

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

Як приклад розглянемо програму, що визначає суму й кількість від’ємних елементів, а також максимальний елемент масиву, що складає з 6 цілочисельних елементів (приклад 1).

Приклад 1. Робота з одномірним масивом

using System;

namespace ConsoleApplication1

{

class Classl

{

static void Main()

{

const int n = 6; // буде помилка, оскільки n = 4 int[] a = new int[n] { 3, 12, 5, -9 }; Console.WriteLine("Вихідний масив:");

for (int i = 0; i < n; ++i) Console.Write("\t" + a[i]); Console.WriteLine();

long sum = 0; // сума відємних елементів

int num = 0; // кількість відємних елементів for (int i = 0; i < n; ++i)

if (a[i] < 0)

{

sum += a[i]; ++num;

}

Console.WriteLine("Сума відємних = " + sum); Console.WriteLine("Кількість відємних = " + num); int max = a[0]; // максимальний елемент

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

if (a[i] > max) max = a[i]; Console.WriteLine("Максимальний елемент = " + max); Console.ReadLine();

}

}

}

1.3. Прямокутні масиви

Прямокутний масив має більше одного виміру. Найчастіше в програмах використаються двовимірні масиви. Варіанти опису двовимірного масиву:

тип [ , ] ім'я;

тип [ , ] ім'я = new тип [ розм_1, розм_2 ]; тип [ , ] ім'я = { список ініціалізаторів };

тип [ , ] ім'я = new тип [ , ] { список ініціалізаторів };

тип [ , ] ім'я = new тип [ розм_1, розм_2 ] { список ініціалізаторів };

5

Приклади описів (один приклад для кожного варіанта опису):

int [ , ] a ;

// 1

елементів немає

int [ , ] b = new int [2,3] ;

// 2

елементи рівні 0

int [ , ] с = { {1,2,3} , {4, 5,6} } ;

// 3 new мається на увазі

int [ , ] d = new int [ , ] {{1,2,3} , {4,5,6}} ;

// 4 розмірність обчислюється

int [ , ] е = new int [2,3] {{1,2,3} , {4,5,6}} ;

// 5 надлишковий опис

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

а [1, 4], b[i, j], b[j, i]

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

1.4. Клас System.Array

Раніше вже говорилося, що всі масиви в С# побудовані на основі базового класу Array, що містить корисні для програміста властивості й методи, частина з яких перераховані в табл. 1.

 

 

Таблиця 1. Основні елементи класу Array

Елемент

Вид

Опис

 

 

Length

Властивість

Кількість елементів масиву (по всім

 

 

розмірностям)

 

Rank

Властивість

Кількість розмірностей масиву

BinarySearch

Статичний метод

Двійковий

пошук

у відсортованому

 

 

масиві

 

 

Clear

Статичний метод

Присвоювання елементам масиву значень

 

 

за замовчуванням

 

Copy

Статичний метод

Копіювання заданого діапазону елементів

 

 

одного масиву в інший масив

CopyTo

Метод

Копіювання

всіх

елементів поточного

 

 

одномірного масиву в інший одномірний

 

 

масив

 

 

GetValue

Метод

Одержання значення елемента масиву

IndexOf

Статичний метод

Пошук першого входження елемента в

 

 

одномірний масив

 

LastlndexOf

Статичний метод

Пошук останнього входження елемента в

 

 

одномірний масив

 

Reverse

Статичний метод

Зміна порядку проходження елементів на

 

 

зворотний

 

 

SetValue

Метод

Установка значення елемента масиву

Sort

Статичний метод

Впорядкування елементів одномірного

 

 

масиву

 

 

6

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

Методи Sort, IndexOf й BinarySearch є статичними, тому до них звертаються через ім'я класу, а не екземпляра, і передають у них ім'я масиву. Двійковий пошук можна застосовувати тільки для впорядкованих масивів. Він виконується набагато швидше, ніж лінійний пошук, реалізований у методі IndexOf. У прикладі 2 пошук елемента, що має значення 18, виконується обома цими способами.

Приклад 2. Використання класу System.Array

using System;

namespace ConsoleApplication1

{

class Classl

{

static void Main()

{

int[] a = { 24, 50, 18, 3, 16, -7, 9, -1 }; PrintArray("Вихідний масив:", a); Console.Write(Array.IndexOf(a, 18)); Array.Sort(a);

PrintArray("Упорядкований масив:", a); Console.Write(Array.BinarySearch(a, 18)); Console.ReadLine();

}

public static void PrintArray(string header, int[] a)

{

Console.WriteLine(header);

for (int i = 0; i < a.Length; i++) Console.Write("\t" + a[i]);

Console.WriteLine();

}

}

}

У класі Classl описаний допоміжний статичний метод PrintArray, призначений для виведення масиву на екран. У нього передаються два параметри: рядок заголовка header і масив. Кількість елементів масиву визначається усередині методу за допомогою властивості Length. Таким чином, цей метод можна використати для виведення будь-якого цілочисельного одномірного масиву.

Для того щоб застосовувати метод PrintArray до масивів, що складаються із елементів іншого типу, можна описати його другий параметр як Array. Правда, при цьому значення елемента масиву доведеться одержувати за допомогою методу GetValue, оскільки доступ по індексу для класу Array не передбачений. Узагальнений метод виклику масиву виглядає так:

7

public static void PrintArray(string header, Array a)

{

Console.WriteLine(header);

for (int i = 0; i < a.Length; ++i) Console.Write("\t" + a.GetValue(i)); Console.WriteLine();

}

1.5. Властивості

Властивості служать для організації доступу до полів класу. Як правило, властивість пов'язана із закритим полем класу й визначає методи його одержання й установки.

Синтаксис властивості:

[ атрибути ] [ специфікатори ] тип <ім'я властивості>

{

[ get код доступу ] [ set код_доступу ]

}

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

Код доступу являє собою блоки операторів, які виконуються при одержанні (get) або установці ( set ) властивості. Може бути відсутнім або частина get, або set, але не обидві одночасно. Якщо відсутня частина set, властивість доступно тільки для читання (read-only), якщо відсутня частина get, властивість доступно тільки для запису (write-only).

Приклад 3. Опис властивостей.

public class Button : Control

{

private string caption; // закрите поле, з яким зв'язана властивість

public string Caption // властивість

{

get // спосіб одержання властивості

{

return caption;

}

set // спосіб встановлення властивості

{

if (caption != value)

{

caption = value;

}

}

}

}

8

При звертанні до властивості автоматично викликаються зазначені в ньому методи читання й встановлення. Синтаксично читання й запис властивості виглядають майже як методи. Метод get повинен містити оператор return, що повертає вираз, для типу якого повинне існувати неявне перетворення до типу властивості. У методі set використається параметр зі стандартним ім'ям value, що містить встановлюване значення.

Загалом, властивість може й не зв'язуватися з полем. Фактично, воно описує один або два методи, які здійснюють деякі дії над даними того ж типу, що й властивість. На відміну від відкритих полів, властивості забезпечують поділ між внутрішнім станом об'єкта і його інтерфейсом й, таким чином,

спрощують внесення змін у клас.

1.6. Індексатори

Індексатор являє собою різновид властивості. Якщо в класі є сховане поле, що представляє собою масив, то за допомогою індексатора можна звернутися до елемента цього масиву, використовуючи ім'я об'єкта й номер елемента масиву у квадратних дужках. Іншими словами, індексатор - це такий «розумний» індекс для об'єктів.

Синтаксис індексатора аналогічний синтаксису властивості: специфікатори тип this [ список_параметрів ]

get код доступу set код доступу

Специфікатори аналогічні специфікаторам властивостей і методів. Список параметрів містить одне або кілька описів індексів, по яких виконується доступ до елемента. Найчастіше використається один індекс цілого типу. Індексатори в основному застосовуються для створення спеціалізованих масивів, на роботу з якими накладаються які-небудь обмеження. У прикладі 4 створений клас-масив, елементи якого повинні перебувати в діапазоні [0,100]. Крім того, при доступі до елемента перевіряється, чи не вийшов індекс за припустимі границі.

Приклад 4. Використання індексаторів

class Vector

{

private int hIndex; private int nIndex; private int kIndex; public int[] vector;

public Vector(int Index, int StartIndex, int konecIndex)//

конструктор классу

{

hIndex = Index; nIndex = StartIndex; kIndex = konecIndex;

vector = new int[Index];

for (int i = 0; i < Index; i++) vector[i] = i;

}

9

public int StartIndex

{

//код доступу

get { return nIndex; } set { nIndex = value; }

}

public int konecIndex

{

//код доступу

get { return kIndex; } set { kIndex = value; }

}

public int Index

{

get { return hIndex; }

}

public int this[int NumOfElement]// індексатор

{

get

{

if (NumOfElement >=0 && NumOfElement < hIndex)

{

return vector[NumOfElement];

}

else

throw new IndexOutOfRangeException();// виключення

}

set

{

if (NumOfElement >=0 && NumOfElement < hIndex && value >= 0 && value <= 100)

{

vector[NumOfElement] = value;

}

else

throw new IndexOutOfRangeException();

}

}

}

Видно, що індексатори описуються аналогічно властивостям. Завдяки застосуванню індексаторів з об'єктом, що містить у собі масив, можна працювати так само, як зі звичайним масивом. Якщо звертання до об'єкта зустрічається в лівій частині оператора присвоювання (оператор 1), автоматично викликається метод get. Якщо звернення виконується в складі виразу (оператор 2), викликається метод set.

1.7. Оператор foreach

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

10

Соседние файлы в папке Лаби (умови)