мета лекції
Вивчення простих, багатовимірних і динамічних масивів.
У практиці програмування нерідко виникає необхідність обробити велику кількість однотипних даних. Припустимо, розподілити тижневу прибуток кафе по днях. Що для цього потрібно? Використовувати змінні типу currency. як раз для таких випадків і застосовуються. І скільки змінних нам потрібно? Ну, зрозуміле питання - по змінної на день, всього сім штук. Давайте подивимося, як таке завдання можна було б вирішити на Lazarus (приклад академічний, виконувати його не потрібно):
А якби довелося вважати місячну або річний прибуток. Якої довжини оператор тоді б вийшов? Але ж часто бувають і більш складні розрахунки, які потрібно провести з кожної однотипної змінної.
На щастя, в мовах програмування існує такий інструмент, як масиви.
Масив - це формальне об'єднання декількох однотипних змінних в єдиний набір, з одним загальним ім'ям.
Фактично, виходить ланцюжок однотипних змінних під загальним ім'ям, де у кожної такої змінної є власний номер в осередку - індекс. Такі змінні називаються елементами масиву. кожен елемент має свій номер. Оголошується масив в розділі змінних наступним чином:
Ключове слово array вказує, що це буде масив. Числа в квадратних дужках поділяються двома точками і позначають діапазон індексів. Так, [1..7] означає, що індекси масиву будуть від 1 до 7, тобто, 7 штук. Після ключового слова of вказується тип масиву. такий же тип буде і у кожного елемента масиву. В результаті, компілятор створює в оперативній пам'яті сім осередків по 8 байт кожна (тип currency займає 8 байт):
Мал. 13.1. Розміщення елементів масиву a в пам'яті
Добре, масиви ми оголосили. Що з ними робити далі? Ми можемо звернутися до будь-якого елементу масиву, вказавши після імені в квадратних дужках індекс цього елемента. Так, ми можемо присвоїти значення елементу або отримати його значення. Іншими словами, ми можемо звертатися з елементами масиву, як з окремими змінними. приклади:
Ну, гаразд, ми навчилися створювати і використовувати масиви. Але які ж переваги у масивів на відміну від простих однотипних змінних? Про перший такої переваги ми вже говорили, ось як просто можна оголосити масив з елементами, розрахованими на рік:
Спробуйте-но оголосити 365 окремих змінних! Друга перевага набагато важливіше: обробляти елементи масиву набагато простіше, ніж окремі змінні. Наприклад, нам потрібно створити програму, яка б могла зробити переклад температур зі звичних нам Цельсію в незвичні американські Фаренгейт. І нехай діапазон можливих температур буде від -100 градусів до +200. Ідея така: користувач вводить потрібну температуру, а програма виводить результат на екран. Звичайно, простіше було б робити потрібний розрахунок в момент, коли користувач введе свої дані, і натисне кнопку "розрахувати". Але ми поступимо по-іншому: ми спочатку зробимо все розрахунки і помістимо результати в масив. а потім будемо просто виводити потрібні дані. Масив зробимо глобальним, щоб заповнювати його в одну подію, а виводити дані в іншому. Відкриваємо Lazarus з новим проектом, зберігаємо його відразу в папку 13-01 там, де у нас зберігаються всі навчальні проекти. Проект збережемо під ім'ям MyTemp. а модуль головної форми, як зазвичай - Main. Займемося головною формою, змініть у неї такі параметри:
- Name = fMain
- Caption = Переклад температурних шкал
- BorderStyle = bsDialog
- Position = poMainFormCenter
Далі, перейдіть на вкладку Additional Палітри компонентів. знайдіть і встановіть на форму компонент TStaticText. який призначений для виведення на екран пояснювального тексту, в тому числі і многострочного. Якщо ви забули, то знайти потрібний компонент просто: потрібно просто підвести покажчик миші до компоненту, і через короткий час з'явиться підказка з ім'ям компонента.
В принципі, для цих цілей можна використовувати і просту мітку TLabel. але було б цікавіше познайомитися і з іншими компонентами. У Інспектора об'єктів у властивості Caption натисніть на кнопку "..." праворуч від властивості:
Мал. 13.2. Властивість Caption компонента TStaticText
Саме так, в два рядки. Потім змініть розміри компонента на формі, щоб текст відображався точно в такому вигляді, як ми ввели. І ще: у властивості Alignment виберіть taRightJustify. щоб текст вирівнювався по правому краю.
Тепер перейдіть на вкладку Misc палітри компонентів, знайдіть там і встановіть на форму, правіше TStaticText. компонент TSpinEdit. який призначений для введення користувачем цілих чисел. Цей компонент схожий на простий TEdit. але праворуч від нього є стрілки вгору і вниз, якими користувач може додавати або збавляти вказане в рядку число. Використання цього компонента гарантує нам, що користувач не зможе ввести в нього нічого, крім цілого числа. А щоб ще гарантувати правильний діапазон цих чисел, у властивості MaxValue (максимальне можливе значення) встановіть 200, а в MinValue (мінімальне можливе значення) встановіть -100 (мінус сто). Тепер користувач не зможе ввести в це поле нічого, крім цілих чисел. Якщо ж він спробує перевищити максимальне значення. то компонент автоматично встановить число 200 - максимально можливе. І навпаки, якщо вказати число менше, ніж -100, компонент встановить -100, так що нам не потрібно турбуватися про помилки. Крім того, в цьому компоненті пізніше нам знадобляться ще два властивості: Text (встановлене значення у вигляді рядка), і Value (встановлене значення в вигляді цілого числа).
За замовчуванням, компонент недостатньо широкий, тому встановіть в його властивості Width значення 75. І ще: нам доведеться звертатися до компоненту на ім'я, а SpinEdit1 - це занадто довге ім'я. Змініть його властивість Name на SE1.
Ну і нарешті, встановіть на форму просту кнопку, у властивості Caption якої напишіть Розрахувати температуру. Напис на кнопці недоречний, тому кнопку доведеться подовжити. Розмістіть компоненти на формі приблизно так:
Мал. 13.3. Зовнішній вигляд форми
Тепер займемося попередніми розрахунками. Для початку нам потрібно зробити глобальний масив дійсних чисел - температура за Фаренгейтом вже не буде цілим числом. Значення за Фаренгейтом обчислюються так: береться температура за Цельсієм, множиться на 9/5, потім до результату додається 32. Тому в глобальному розділі var. відразу над ключовим словом implementation оголошуємо масив atemp:
Оскільки це глобальний масив. він буде створений відразу ж при завантаженні програми, і буде існувати, поки програма не від'ôднаôтесь свою роботу. Тепер займемося заповненням цього масиву.
Виділіть форму, клацнувши по її вільного місця, потім в інспектор об'єктів перейдіть на вкладку Події. Нам потрібно подія OnCreate - воно виникає тільки один раз, при створенні форми. Клацніть двічі по цій події, щоб згенерувати його. Код події наступний:
Ось тепер, нарешті, ми зможемо оцінити всю красу використання масивів! Давайте розберемо цей код. У розділі var ми оголосили змінну i типу smallint. Це - лічильник для циклу for. який ми використовували в коді. Так як діапазон потрібних нам значень розташовується від -100 до +200, тип цілих чисел smallint - найкращий. А тепер зверніть увагу на код:
Це - найголовніша "фішка" масивів - обробка всього масиву, яким би великим він не був, в простому циклі. Спочатку лічильник i приймає значення -100. Всередині циклу ми присвоюємо значення одному елементу масиву. Якщо ми замінимо змінну i на її значення. як це робить компілятор в процесі роботи, то отримаємо наступне:
Таким чином, ми вираховуємо переклад температури з Цельсія в Фаренгейт для конкретної температури: -100 градусів за Цельсієм, і отриманий результат присвоюємо елементу масиву atemp [-100]. Потім цикл повторюється, i збільшується на одиницю, і вже дорівнює -99. Нове значення присвоюється новому елементу масиву, і так до кінця циклу. Як ви думаєте, скільки елементів масиву буде заповнено в цьому циклі? Хто сказав 300. А про нуль ви забули? 301 раз буде працювати цикл, і 301 різне значення буде присвоєно 301 елементу масиву. А тепер уявіть, як це виглядало б для окремих змінних:
Замість двох рядків циклу ми отримали б 301 рядок коду з однаковими обчисленнями!
Але повернемося до нашого проекту, адже нам ще потрібно вивести на екран результат перекладу температур. Згенеруємо для кнопки Button1 подія OnClick. Її код буде зовсім простий:
Тут у нас всього один оператор - процедура ShowMessage (). Вона формує виведене повідомлення з 4 частин: SE1.Text - це те значення. яке встановив користувач в компоненті TSpinEdit у вигляді рядка. Потім ми вставляємо в повідомлення текст 'Цельсія ='. Зверніть увагу на прогалини спочатку і в кінці цього шматочка - без них слова злипалися б, а це некрасиво. Далі, ми додаємо до рядка наступний код:
Тут SE1.Value - це те значення. яке встановив користувач. але вже у вигляді цілого числа! Припустимо, користувач встановив значення 35, тоді цей код буде таким:
В елементі масиву atemp [35] у нас вже зберігається перекладене у Фаренгейт значення температури 35 за Цельсієм. А функція FloatToStr () тільки переведе це значення в рядок. Таким чином, для значення 35 сформується повідомлення: "35 Цельсія = 95 Фаренгейта". Збережіть проект, скомпілюйте його і переконайтеся, що програма коректно працює в зазначених межах температур, а перевищити їх користувач не зможе, якщо і захоче, як не зможе ввести нічого іншого, крім цілого числа.
багатовимірний масив
Масиви, які ми до цих пір розбирали, були одновимірними - візуально їх можна уявити, як ланцюжок осередків або один рядок таблиці. Однак бувають ситуації, коли цього недостатньо. Припустимо, потрібно зберегти якусь таблицю. Одновимірна масив з таким завданням не впорається. Для цього існують багатовимірні масиви. які мають розмірність від двох і більше. Наприклад, оголосити двомірні масиви з 5 рядків і 10 колонок можна наступним чином:
Тобто, в квадратних дужках через кому вказується діапазон спочатку рядків, а потім колонок. Візуально, такий масив можна було б уявити так:
У першому випадку ми звертаємося до елементу у другому рядку, дев'ятої колонці. У другому - до третьому рядку, десятої колонці. Перший спосіб звернення до елементу здається більш компактно, його ми і будемо використовувати надалі.
Доопрацюємо наш проект. Що, якщо ми будемо конвертувати нашу температуру не тільки в Фаренгейт, але і в Кельвіна (одиниця термодинамічної температури в СІ - Міжнародної Системі Одиниць)? Перерахунок Цельсія в Кельвіна ще простіше, ніж у Фаренгейт: потрібно до температури за Цельсієм додати 273,15. Для цього нам буде потрібно замість одновимірного масиву оголосити двомірний. Змініть код над службовим словом implementation:
У першому рядку у нас будуть Фаренгейт, в другій - Кельвіна. А колонки ми відведемо під необхідний діапазон. Далі, нам буде потрібно змінити цикл в подію OnCreate форми:
Зверніть увагу: оскільки нам в циклі потрібно виконати не один оператор, а два, нам довелося зробити висновок їх в програмні дужки begin ... end. зробивши складовою оператор. Далі, все просто: для рядка 1 нашого масиву ми розраховуємо Фаренгейт, як в минулий раз. А для рядка 2 вже Кельвіна.
Але нам потрібно переробити і подія кнопки OnClick:
З кодом, сподіваюся, ви розберетеся самостійно? Отже, якщо користувач введе, наприклад, 36 градусів Цельсія, то натиснувши на кнопку, отримає наступне повідомлення:
Мал. 13.4. Сгенерированное програмою повідомлення
Але розмірність масиву може бути і більше. Тривимірний масив візуально можна представити таким чином:
Мал. 13.5. Візуальне уявлення тривимірного масиву
Оголосити подібний масив можна було б так:
А звертатися до окремих елементів так:
Як би виглядав чотиривимірний масив візуально взагалі неможливо уявити. У вас є можливість працювати хоч з десятімерним масивом, проте в практиці програмування зазвичай використовують одно- і двомірні масиви, і дуже рідко виникає потреба в тривимірному. Не забувайте про один з основних принципів програмування, який самі програмісти називають KISS (Keep It Simple, Stupid - будь простішим, дурник). Цей принцип має на увазі, що код програми не варто ускладнювати без потреби - складний код важче сприймається самим програмістом, більше навантажує процесор. а помилки часу виконання (run time errors - помилки, що виникають під час виконання програми, зазвичай це логічні помилки) в такому коді складніше відстежувати.
динамічний масив
У практиці програмування іноді трапляється працювати з масивами, розмірність яких заздалегідь невідома - вона може залежати від даних, введених користувачем, від поточних параметрів, від обсягу оброблюваної інформації, та ще багато від чого. Програміст в цих випадках не може вказати конкретні кордону індексів масиву. У таких випадках використовують динамічні масиви.
Оголошуються динамічні масиви також в розділі var. наступним чином:
Як бачите, ми вказуємо тільки тип масиву. але не його розмірність. Пам'ять під оголошений масив при цьому не приділяється. Надалі з динамічним масивом ми можемо робити різні операції. встановлювати розмірність (довжину) масиву, збільшувати або зменшувати цю розмірність (тому масив і динамічний), дізнаватися вищі і нижчі межі діапазону індексів масиву, присвоювати значення окремих елементах або навпаки, зчитувати ці значення. Зустрітися з функціями, які все це роблять.
SetLength () - встановлює розмір масиву. синтаксис: