You are on page 1of 22

1

Урок № 7
Багатовимірні
масиви

Зміст
1. Генератор випадкових чисел...................................... 3
Використання функції rand..............................................3
Використання функції srand.............................................5
Використання функції time...............................................7
Установка діапазону для генератора...............................8
2. Використання генератора випадкових чисел........ 10
3. Двовимірні масиви як окремий випадок
багатовимірних масивів........................................... 12
Двовимірний масив.
Оголошення та розташування в пам'яті......................12
Ініціалізація........................................................................14
4. Практичний приклад................................................ 16
Постановка задачі..............................................................16
5. Поняття статичного виділення пам'яті.................. 18
6. Домашнє завдання.................................................... 20

Додаткові матеріали уроку прикріплені до даного PDF-файлу.


Для доступу до матеріалів, урок необхідно відкрити в програмі
Adobe Acrobat Reader.

2
1. Генератор випадкових чисел

1. Генератор випадкових
чисел
На минулому уроці ми з вами познайомилися з та-
ким поняттям як масив і навчилися заповнювати його
значеннями. Усі наші значення ми вписували самі, тобто
заздалегідь знали, якими вони будуть. Такий спосіб за-
повнення змінних і масивів обмежує можливості про-
грами. Неможливо створити щось, що володіє штучним
інтелектом, якщо немає способу отримувати дані, що не
залежать від користувача. Що ж робити, якщо нам необ-
хідні значення, обрані випадковим чином?

Використання функції rand


У мові С++ є можливість генерувати випадкове число.
Для цієї операції використовується функція під назвою
rand(). Ця функція знаходиться в бібліотечному файлі
stdlib.h, отже, для її роботи необхідно цей файл підключити
за допомогою директиви #include. На місце виклику rand()
у програмі підставиться випадкове число в діапазоні від
0 до 32767. Розглянемо простий приклад:

#include<iostream>
#include<stdlib.h> // у цьому файлі міститься
// фунцкія rand
using namespace std;
int main()
{
int a;

3
Урок № 7

// генерація випадкового числа і запис його


// в змінну a
a=rand();
cout<<a<<"\n";

/* Повторна генерація випадкового числа і запис


його в змінну a
*/
a=rand();
cout<<a<<"\n";
return 0;
}

Якщо ви створили проєкт, набрали і запустили наш


приклад на виконання, то виявили, що програма послідовно
генерувала два так звані випадкові числа. Це можуть бути
числа на зображенні нижче або пара будь-яких інших:

Малюнок 1

Запустіть ще раз. І знову та сама картина — пара зно-


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

4
1. Генератор випадкових чисел

здатний на асоціативне мислення, тому функція rand() не


отримує число з повітря, а працює, використовуючи як
початкову точку точку, визначену при написанні алгорит-
му генератора випадкового числа, тобто якесь постійне
число. Іншими словами, спираючись на цю точку, при
різних викликах програми ця функція генерує одне й те
саме число, у чому ми вже встигли переконатися. З цьо-
го можна зробити висновок — для того, щоб rand() при
різних викликах програми видавав різні числа, необхідно
змінити початкову точку генерації.
Використання функції srand
Місцезнаходження функції — бібліотека stdlib.h. Функція
srand встановлює початкову точку для генерації випад-
кових чисел і має наступний синтаксис:
void srand(unsigned int start)

Параметр start, який приймає функція, і є новою точкою


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

#include<iostream>
// у цьому файлі містяться функції rand і srand
#include<stdlib.h>

5
Урок № 7

using namespace std;


int main()
{
srand(5);
int a;
/*
генерація випадкового числа і запис його
в змінну
*/
a=rand();
cout<<a<<"\n";
return 0;
}

Приклад зі змінною як відправною точкою

#include<iostream>
// у цьому файлі містяться функції rand і srand
#include<stdlib.h>

using namespace std;


int main()
{
int start=25;
srand(start);
int a;
// генерація випадкового числа і запис його в
//змінну
a=rand();
cout<<a<<"\n";
return 0;
}

Нам з вами необхідна якась величина, яка змінюється


постійно, незалежно від будь-яких зовнішніх факторів.

6
1. Генератор випадкових чисел

Погодьтеся, такою величиною є час. І саме час ми вико-


ристаємо як відправну точку.
Використання функції time
Місцезнаходження функції — бібліотека time.h.
Функція time має декілька призначень, і докладно
розбирати ми її зараз не будемо. Візьмемо тільки те, що
необхідно нам для роботи. А саме — якщо функцію time
викликати з параметром NULL, то на місце свого виклику
в програмі ця функція поверне кількість мілісекунд, що
минулі з 1 січня 1970 року. Погодьтеся, що ця величина
щоразу буде різною. Це саме те, що ми шукали. «Зберемо»
отриману інформацію в єдине ціле й отримаємо:
srand(time(NULL));

Функція srand встановлює як стартову точку число,


що є кількістю мілісекунд, що минулі з 1 січня 1970 року.
Спробуємо:

#include<iostream>
/* у цьому файлі містяться rand і srand */
#include<stdlib.h>
// у цьому файлі міститься функція time
#include<time.h>

using namespace std;


int main()
{
srand(time(NULL));
int a;
// генерація випадкового числа і запис його
// в змінну
a=rand();

7
Урок № 7

cout<<a<<"\n";
return 0;
}

Набравши виправлений приклад, ви, звичайно, пере-


коналися, що тепер при різних запусках програми гене-
руються різні числа, але на цьому можливості генератора
не вичерпуються.

Установка діапазону для генератора


Числа, які виходять шляхом виклику функції rand,
лежать у діапазоні від 0 до 32767. Але ж нам не завжди
потрібен такий масштабний розкид даних. Що робити,
якщо необхідно генерувати числа від 0 до 10 або від 0 до
100 і так далі?! На допомогу в таких випадках приходить
старе-добре ділення за модулем.
Візьмемо для прикладу довільне число  — 23.
Погодьтеся, що хай би яке число ви розділите на 23 за
модулем, ви отримаєте або 0 (якщо остачі немає), або
остачу в діапазоні від 1 до 22. Цією властивістю ми й
скористаємося, розділивши згенероване випадкове
число за модулем:
int a=rand()%23;

На підставі цього правила можна вивести формулу:


ЧИСЛО В ДІАПАЗОНІ ВІД НУЛЯ ДО Х:
rand() % X

Але діапазон не завжди починається з нуля. Нехай


нам потрібен діапазон від 11 до 16. Усе просто. Необхідно

8
1. Генератор випадкових чисел

генерувати числа від 0 до 5 (різниця між 16 і 11), а потім


«зрушити» отриманий результат на 11 одиниць.
int a=rand()%5+11;

І на підставі вже модифікованого правила можна


вивести формулу: ЧИСЛО В ДІАПАЗОНІ ВІД Y ДО Х:
rand() % (X-Y) + Y

Отже, ми з вами познайомилися з генератором ви-


падкових чисел і тепер можемо полегшити собі роботу
з масивами. Як? Наступний розділ уроку розповість
про це.

9
Урок № 7

2. Використання генератора
випадкових чисел
Давайте розглянемо приклад використання генератора
випадкових чисел, а саме заповнення масиву випадко-
вими числами:

#include<iostream>
// у цьому файлі містяться функції rand() і srand()
#include<stdlib.h>
// у цьому файлі міститься функція time()
#include<time.h>
using namespace std;

int main()
{
int array[10];
srand(time(NULL));
for (int i=0;i<10;i++)
{
// генерація випадкового числа і запис його
// в поточний елемент масиву
array[i]=rand()%100;
// вивід значення елемента на //екран
cout<<array[i]<<"\n";
}
return 0;
}

1. У наведеному вище прикладі на екран буде виведе-


ний масив з 10 елементів, заповнений випадковими
числами.

10
2. Використання генератора випадкових чисел

2. На кожній ітерації циклу генерується нове випадкове


число.
3. При кожному запуску програми масив буде заповнений
по-різному завдяки рядку srand(time(NULL));
4. Числа, що розташовані в масиві, будуть варіюватися
в діапазоні від нуля до 100, тому що результат генерації
ділиться на 100 за модулем.
Як бачите, генератор випадкових чисел простий в обі-
гу, і тепер у ваших руках є зброя, яка дозволить вам не
тільки тестувати програми, не вводячи дані з клавіатури,
а й створювати примітивний штучний інтелект.

11
Урок № 7

3. Двовимірні масиви
як окремий випадок
багатовимірних масивів
Ми з вами вже маємо уявлення про те, що таке масиви,
на минулому уроці ми розібрали так званий одновимірний
масив. Одновимірний масив — масив даних, де кожне
значення має тільки одну характеристику — порядковий
номер (індекс). Саме за цим індексом ми і звертаємося
до конкретного елемента.
Сьогодні ми поговоримо про багатовимірні масиви,
тобто про масиви, де кожен елемент описується декількома
характеристиками. Прикладом значення багатовимірного
масиву може бути що завгодно:
1. Шахова дошка — кожна клітина має дві розмірності
E2 (літера й цифра);
2. Оцінка КВК — три розмірності ЧЛЕН_ЖЮРІ, КОН-
КУРС, КОМАНДА.
Ми з вами зупинимося на двовимірному масиві, друга
назва якого — матриця (так його зазвичай називають
математики).
Двовимірний масив.
Оголошення та розташування в пам'яті
Двовимірний масив є сукупністю рядків і стовп-
ців, на перетині яких розташоване конкретне значення.
Оголосити двовимірний масив нескладно, необхідно

12
3. Двовимірні масиви як окремий випадок багатовимірних масивів

вказати кількість рядків і стовпців. При цьому, тут ді-


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

тип_даних ім'я_масиву [кількість_рядків]


[кількість_стовбців];

Приклад:

const int row=3; // рядки


const int col=4; // стовпці
int array[row][col]; // масив розміром row
// на col(3х4)

Стовпець 0 Стовпець 1 Стовпець 2 Стовпець 3


Рядок 0 a[0] [0] a[0] [1] a[0] [2] a[0] [3]
Рядок 1 a[1] [0] a[1] [1] a[1] [2] a[1] [3]
Рядок 2 a[2] [0] a[2] [1] a[2] [2] a[2] [3]

Індекс стовпця
Індекс рядка
Ім’я масиву

Малюнок 2

Незважаючи на те, що ми представляємо масив у ви-


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

13
Урок № 7

Малюнок 3

Ініціалізація
Ініціалізація двовимірного масиву аналогічна до іні-
ціалізації одновимірного:
1. Ініціалізація при створенні
Кожен рядок пишеться в окремих фігурних дужках:
int array[2][2]={{1,2},{7,8}};

Значення вказуються поспіль і по рядках вписуються


в масив:
int array[2][2]={7,8,10,3};

Якщо значення пропущено, воно буде ініціалізовано


нулем:
int array[3][3]={{7,8},{10,3,5}};

2. Ініціалізація за допомогою циклу.


Відкриємо один секрет — двовимірний масив можна
розглядати як сукупність не просто рядків, а одновимірних
масивів. Тобто один одновимірний масив ми заповнюємо
простим циклом, перебираючи конкретні елементи, а при
сукупності нам необхідно перебирати ще й окремі масиви.
Примітка. Звернення до конкретного елемента
масиву здійснюється за номером рядка й номером
стовпця, наприклад, mr[2][1] — значення, що ле-
жить на перетині другого рядка і першого стовпця.

14
3. Двовимірні масиви як окремий випадок багатовимірних масивів

Робота з двовимірним масивом не набагато складніша,


ніж з одновимірним — доведемо це на практиці.

#include<iostream>
// у цьому файлі містяться rand і srand
#include<stdlib.h>
// у цьому файлі міститься функція time
#include<time.h>

using namespace std;


int main()
{
const int row=3; // рядки
const int col=3; // стовпці
int mr[row][col]; // масив розміром row на col
/* перебираємо окремі рядки (одновимірні масиви
в сукупності) */
for(int i=0; i<row; i++)
{
// перебираємо окремі елементи кожного
// рядка
for(int j=0; j<col;j++)
{
/* ініціалізація елементів значеннями
у діапазоні від 0 до 100 */

mr[i][j]=rand()%100;
// вивід значень на екран
cout<<mr[I][j]<<" ";
}
/* перехід на інший рядок матриці */
cout<<"\n\n";
}
return 0;
}

15
Урок № 7

4. Практичний приклад
Постановка задачі
Написати програму, яка у двовимірному масиві зна-
ходить максимальний елемент кожного рядка.
Код реалізації

// у цьому файлі містяться rand і srand


#include<stdlib.h>
#include<time.h> // у цьому файлі міститься функція time
using namespace std;

int main()
{
// задаємо розмірність масиву
const int m = 3;
const int n = 2;
int A[m][n]; // оголошуємо двовимірний масив

// заповнення масиву випадковими числами


// і вивід на екран
// перебираємо окремі рядки
for(int i=0; i<m; i++)
{
// перебираємо окремі елементи кожного рядка
for(int j=0; j<n;j++)
{
// ініціалізація елементів значеннями
// у діапазоні від 0 до 100
A[i][j]=rand()%100;
// вивід значень на екран
cout<<A[i][j]<<" ";
}

16
4. Практичний приклад

// перехід на інший рядок матриці


cout<<"\n\n";
}
cout << "\n\n";
// пошук у рядках максимального елемента
// перебираємо окремі рядки
for (int i=0; i<m; i++)
{
// припускаємо, що максимальним є
// нульовий елемент рядка
int max = A[i][0];
// пошук максимального елемента
// в поточному рядку

// зміна індексу стовпця для поточного рядка


for (int j=0; j<n; j++)
{
if (A[i][j] > max)
max = A[i][j];
}
cout << "Max element "<< i << " row=" <<
max << endl;
}
return 0;
}

Зверніть увагу!
1. На кожній ітерації циклу як максимум вибирається
нульовий елемент поточного рядка.
2. Після аналізу конкретного рядка, знайдений максимум
виводиться на екран.

17
Урок № 7

5. Поняття статичного
виділення пам'яті
Настав час трохи поговорити про роботу з пам'яттю.
Поки ми всерйоз не замислювалися про те, як відбу-
вається виділення пам'яті для тієї чи іншої оголошеної
змінної.
Поки що ми використовуємо тільки один вид виді-
лення пам'яті — статичне виділення пам'яті.
Що це означає? Механізм статичного виділення пам'яті
обчислює потрібну кількість байтів для змінної або масиву
на етапі компіляції програми.
Наприклад:

// під змінну a буде виділено 4 байти


int a;

// під масив буде виділено 40 байтів


int arr[10];

Коли виконання програми дійде до місця оголошення


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

18
5. Поняття статичного виділення пам'яті

Це означає, що статичне виділення пам'яті не підходить


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

19
Урок № 7

6. Домашнє завдання
1. Дан двовимірний масив розмірністю 3×4. Необхідно
знайти кількість елементів, значення яких дорівнює
нулю.
2. Дана квадратна матриця порядку n (n рядків, n стовпців).
Знайти найбільше зі значень елементів, розташованих
у темно-синіх частинах матриць.

Малюнок 4

3. Усі масиви в цьому домашньому завданні заповню-


ються випадково.

20
6. Домашнє завдання

21
Урок № 7
Багатовимірні масиви

© Компьютерна Академія «Шаг», www.itstep.org

Усі права на захищені авторським правом фото, аудіо та відеотвори,


фрагменти яких використані в матеріалі, належать їхнім законним влас-
никам. Фрагменти творів використовуються з ілюстративною метою
в обсязі, виправданому поставленим завданням, в межах навчального
процесу і в навчальних цілях Відповідно до ст. 1274 ч. 4 ГК РФ і ст. 21 і 23
Закону України «Про авторське право й суміжні права». Обсяг і спосіб
цитованих творів відповідає прийнятим нормам, не завдає шкоди
нормальному використанню об'єктів авторського права і не обмежує
законні інтереси автора та правовласників. Цитовані фрагменти творів
на момент використання не можуть бути замінені альтернативними,
що незахищені авторським правом аналогами, і як такі відповідають
критеріям сумлінного і чесного використання.
Усі права захищені. Повне або часткове використання матеріалів
заборонено. Узгодження використання творів або їхніх фрагментів
проводиться з авторами і правовласниками. Узгоджене використання
матеріалів можливе лише за умов згадування джерела.
Відповідальність за несанкціоноване копіювання і комерційне вико-
ристання матеріалів визначається чинним законодавством України.

You might also like