Масиви Двовимірні масиви

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Міністерство освіти і науки Республіки Казахстан

Казахстанський Інженерно Технологічний університет

(Коледж)

Кафедра «Обчислювальна техніка, автоматизація і телекомунікація»

Курсова робота

з дисципліни

програмування

Тема: Масиви. Двовимірні масиви

Виконала: <ІС> 3 курс Ісмаїлова А. С.

Перевірила: Желілова К.А.

Алмати, 2010р

Зміст:

1.Вступ

1) Історія створення мови Pascal

2) Короткий огляд мови

2.Основні частина

1) Масив.

2) Одновимірні масиви

3) Алгоритми сортування одновимірних масивів

4) Масиви в мовах Pascal і Basic

5) Масив в Бейсіку

6) Масив у Паскалі

7) Двовимірні масиви Паскаля - матриці

8) Опис двовимірного масиву Паскаля

9) Основні дії з двовимірними масивами Паскаля

10) Введення двовимірного масиву Паскаля

11) Висновок двовимірного масиву Паскаля на екран

12) Представлення двовимірного масиву Паскаля в пам'яті

13) Методи доступу до елементів масивів

14) Індексний масив

15) Специфічні типи масивів

16) Динамічні масиви

17) Гетерогенні масиви

3.Заключеніе

1) Основна

2) Додаткова

Список літератури

1) основна література

2) додаткова додаткова

Введення

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

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

Сучасні концепції типів даних розвиваються впродовж останніх 40 років. У ранніх мовами програмування всі структури даних, що відповідають конкретним завданням, моделювалися невеликою кількістю основних структур даних, підтримуваних цими мовами. Наприклад, у версіях мови FORTRAN, розроблених до мови FORTRAN 90, зв'язні списки і виконавчі дерева зазвичай моделювалися за допомогою масивів.

Перший крок у бік від моделі, використаної у мові FORTRAN I, був зроблений розробниками структур даних у мові COBOL, що дозволили програмістам встановлювати точність десяткових чисел і запропонували використовувати структурні типи даних для представлення записів, що містять інформацію.

Концепції розробки типів даних, що з'явилися в кінці 1970-х років в результаті природного узагальнення ідеї типів, визначених користувачем, були втілені в мові Ada 83. Методологія, що лежить в основі визначених користувачем типів даних, полягає в тому, що програмістові слід дозволити створювати окремий тип для кожного окремого класу змінних, визначених предметною областю завдання. Більше того, мова повинна забезпечувати унікальність типів, які є, фактично, абстракціями змінних з предметної області завдання. Це досить потужна концепція, що надає значний вплив на загальний процес розробки програмного забезпечення.

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

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

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

Різні мови програмування, як буде описано нижче, пропонують різні варіанти використання масивів.

Історія створення мови Pascal

Pascal розроблявся з 1968 по 1970 р. Ніколаусом Віртом. Мета полягала в тому, щоб створити мову, позбавлений численних недоліків ALGOL. Pascal був названий на честь французького математика Блеза Паскаля, який ще в 1642 р. винайшов цифровий калькулятор. З кінця 70-х до кінця 80-х рр.. цю мову домінував серед мов, що використовуються на початковому етапі навчання програмуванню; пізніше його замінили С і C + +, а потім Java.

ALGOL 60 був першою спробою створення мови на основі формального опису, проте його реалізація виявилася складною. Зокрема, виявилося досить важко реалізувати передачу параметрів на ім'я, хоча це досить елегантний механізм. У мові ALGOL 60 не були визначені оператори введення-виведення, оскільки в той час вважалося, що вони залежать від реалізації, та й власну статичну пам'ять також важко було реалізувати. Крім того, в 60-х рр.. були розроблені нові практичні рішення, наприклад типи даних і структурне програмування. Мови типу FORTRAN були популярні завдяки своїй ефективності при виконанні програм, незважаючи на відсутність елегантності.

У 1965 р., під час роботи в Стенфордському університеті (Stanford University), Вірт розробив нову, розширену версію ALGOL 60 для комп'ютерів серії IBM 360, в яку увійшло визначення покажчиків і структур даних. Ця мова, відомий як ALGOLW, використовувався в декількох університетах, але його реалізація обмежувалася тільки комп'ютерами IBM 360. Для виконання програм на цій мові потрібен значний за розмірами пакет програм підтримки обробки рядків, дійсних чисел подвійної точності та інших складних типів даних. Таким чином, ALGOL W в якості системного мови програмування виявився малоефективним.

У 1968 р. Вірт повернувся до Швейцарії і почав роботу над наступником ALGOL W - мовою, який міг би компілюватися за один прохід. Для створення вихідного компілятора був використаний алгоритм рекурсивного спуску. Цей компілятор виконувався на комп'ютері Control Data. Також був розроблений широко відомий тепер інтерпретатор Р-коду. Компілятор мови Pascal спочатку транслював вихідну програму в програму мовою гіпотетичної машини зі стекової архітектурою. Завдяки такій своїй організації Pascal легко переносився на комп'ютери інших систем. Компілятор Pascal був написаний на однойменному мовою. Все, що було потрібно для переходу в іншу систему, - це переписати відповідним чином інтерпретатор Р-кода.Появівшійся в 1970 р. Pascal почав завойовувати прізнаніе.В 1983 р. був розроблений американський стандарт мови (IEEE 770 / ANSI X3.97), а незабаром був розроблений стандарт ISO (ISO 7185).

Короткий огляд мови

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

У Pascal є досить широкий набір простих і структурованих типів даних: цілі та дійсні числа, символьні дані, перерахування, логічні (булеві) значення, масиви, записи, послідовні файли і обмежений тип множин. Оператор type дозволяє програмісту визначати нові типи даних, хоча не забезпечує групування і інкапсуляцію визначення нового типу даних з набором підпрограм, які забезпечують виконання основних операцій над об'єктами даних цього нового типу. Крім того, покажчик і операція створення нових об'єктів даних будь-якого типу дозволяють програмісту конструювати нові об'єкти пов'язаних даних безпосередньо під час виконання програми.

Підпрограми приймають форму функцій (якщо вони повертають одне яке-небудь значення) або процедур (якщо їх дія зводиться до модифікації переданих параметрів або глобальних змінних). Оператори управління послідовністю дій базуються на конструкціях структурного програмування: складових операторах, умовних операторах і операторах вибору (case), а також трьох видах операторів циклу. У Pascal є також оператор goto, який рідко використовується і без якого практично завжди можна обійтися. Виклик підпрограм і повернення значень здійснюється за допомогою звичайної рекурсивної структури виклику-повернення.

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

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

З допоміжних підпрограм потрібні в основному стандартні програми введення-виведення для послідовних файлів і процедури для управління ресурсами пам'яті.

Хоча Pascal в цілому дуже зручний і корисний мову, у нього є свої недоліки, перелік яких наведено нижче.

1. У визначенні цієї мови є деяка суперечність між ідеологією самої мови і його реалізацією. Наприклад, конструкція forward потрібна тільки для того, щоб компіляція могла виконуватися в один прохід, - це наслідок уявлень про те, що таким чином досягається максимальна ефективність компіляції. Але це не завжди вірно. Наприклад, компілятор PL / C для мови PL / I здійснював три проходи і разом з тим був одним з найбільш ефективних серед найпоширеніших компіляторів свого часу. Крім того, в даний час при використанні недорогих швидкодіючих комп'ютерів швидкість компіляції не має великого значення.

2. Можливо, найголовнішою слабкістю мови Pascal є те, що масиви розглядаються як окремі типи, а не як агрегація різних об'єктів одного типу. Це призводить до того, що, наприклад, array [1. .10] Of Integer і аггау [1. .20] Of integer представляють собою / різні типи даних. У результаті алгоритми обробки масивів ускладнюються, оскільки масиви різних розмірів неможливо передати загальної підпрограмі (наприклад, підпрограмі перемноження матриць). Рядки реалізовані як масиви символів, що також ускладнює їх обробку в разі рядків різної довжини.

3. Синтаксис визначення процедури в Pascal виглядає наступним чином: заголовок процедури локальні змінні параметри локального begin тіло процедури end. Оскільки в програмі може міститися велика кількість вкладених локальних процедур, то визначення локальної змінної, яка використовується у будь-якій процедурі, виявляється (синтаксично) сильно віддалених від місця її використання в тілі підпрограми. Це призводить до ускладнень при створенні документації та читанні великих програм на Pascal.

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

розглядали листинги програм, намагаючись виявити помилку, пов'язану з пропуском ключового слова var.

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

було прийнято угоду, що допускаються додаткові зовнішні процедури, аналогічні заголовним файлів з ​​розширенням h в мові С. Але така нестандартна реалізація обмежує можливість перенесення програм на Pascal на інші машини.

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

Масив - це безліч однотипних елементів, об'єднаних загальним ім'ям і займають в комп'ютері певну область пам'яті. Кількість елементів у масиві завжди звичайно. У загальному випадку масив - це структурований тип даних, що складається з фіксованого числа елементів, що мають один і той же тип. Назва регулярний тип (або ряди) масиви отримали за те, що в них об'єднані однотипні (логічно однорідні) елементи, впорядковані (врегульовані) за індексами, що визначає положення кожного елемента в масиві. В якості елементів масиву можна використовувати будь-який тип даних, тому цілком правомірно існування масивів записів, масивів покажчиків, масивів рядків, масивів і т.д.Елементамі масиву можуть бути дані будь-якого типу, включаючи структурірованние.Тіп елементів масиву називається базовим. Особливістю мови Паскаль є те, що число елементів масиву фіксується при описі і в процесі виконання програми не змінюється. Елементи, що утворюють масив, впорядковані таким чином, що кожному елементу відповідає сукупність номерів (індексів), що визначають його місце розташування в загальній послідовності. Доступ до кожного окремого елементу здійснюється шляхом індексування елементів масиву. Індекси представляють собою вираження будь-якого скалярного типу (частіше цілого), крім речовинного. Тип індексу визначає межі зміни значень індексу. Для опису масиву призначено словосполучення array of (масив з).

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

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

Алгоритми сортування одновимірних масивів. Сортування - один з найбільш поширених процесів сучасної обробки даних. Сортуванням називається розподіл елементів масиву у відповідності з певними правилами. Наприклад, сортування масиву за збільшенням або убуванню його елементів. Обмінна сортування (метод "бульбашки"). Алгоритм починається з порівняння 1-го і 2-го елементів масиву.

Якщо 2-й елемент менше 1-го, то вони міняються місцями. Цей процес повторюється для кожної пари сусідніх елементів масиву, поки все N елементів не будуть оброблені. За один "прохід" масиву найбільший елемент встане на старше (N-е) місце. Далі алгоритм повторюється, причому наприклад "проході" перші (Np) елементів порівнюються зі своїми правими сусідами. Якщо на черговому "проході" перестановок не було, то алгоритм свою роботу закінчив. Таким чином, самі "легкі" елементи в процесі виконання алгоритму поступово "спливають".

Сортування вставками. Спочатку упорядковуються два перші елемента масиву. Вони утворюють початкову впорядкована множина S. Далі на кожному кроці береться наступний по порядку елемент і вставляється у вже впорядкована множина S так, щоб зліва від нього всі елементи були не більше, а праворуч не менше оброблюваного. Місце для вставки поточного елемента в упорядкований безліч S шукається методом ділення навпіл. Алгоритм сортування закінчує свою роботу, коли елемент, що стоїть на N-му місці, буде оброблений. (Саме таким чином гравці в бридж зазвичай впорядковують свої карти).

Сортування вибором. Знаходиться найбільший елемент в масиві з N елементів (нехай він має номер р) і міняється місцями з елементом, що стоїть на N-му місці, за умови, що N <> p. З решти (N-1) елементів знову виділяється найбільший і міняється місцями з елементом, що стоїть на (N-1)-му місці і т. д. Алгоритм закінчує свою роботу, коли елементи, що стоять на 1-м і 2-му місцях в масиві, будуть впорядковані (для цього знадобиться N-1 "прохід" алгоритму). Аналогічно даний алгоритм можна застосовувати і до найменших елементів.

Дії над масивами

Для роботи з масивом як єдиним цілим використовується ідентифікатор масиву без вказівки індексу вквадратних дужках. Масив може брати участь тільки вопераціях відносини "дорівнює", "не дорівнює" і воператоре присвоєння. Масиви, що беруть участь ветіх діях, повинні бути ідентичні за структурою, тобто мати однакові типи індексів і однакові типи компонентов.Напрімер, якщо масиви А і Вопісани як var А, В: array [1 .. 20] of real; то застосування до них допустимих операцій дасть наступний результат: вираз результат А = ВTrue, якщо значення кожного елемента масиву А одно відповідного значенням елемента масиву ВА <> ВTrue, якщо хоча б одне значення елемента масиву А не дорівнює значенню відповідного елемента масиву ВА: = У всі значення елементів масиву У присвоюються відповідним елементам масиву А. Значення елементів масиву У залишаються незмінні.

Дії над елементами масиву Після оголошення масиву кожен його елемент можна обробити, вказавши ідентифікатор (ім'я) масиву та індекс елемента в квадратних дужках. Наприклад, запис Mas [2], VectorZ [10] дозволяє звернути-ся до другого елементу масиву Mas і десятій елементу масиву VectorZ.

При роботі з двовимірним масивом вказуються два індекси, з n-мірним масивом - n індексів. Наприклад, запис MatrU [4,4] справи-ет доступним для обробки значення елемента, що знаходиться в чет-вертом рядку четвертого стовпця масиву MatrU. Індексовані елементи масиву називаються індексованими пе-ремінними і можуть бути використані так само, як і прості змінні. Наприклад, вони можуть перебувати у виразах як операнди, використовуватися в операторах for, while, repeat, вхо-дить в якості параметрів в оператори Read, Readln, Write,

Масиви в мовах Pascal і Basic

З поняттям "масив" доводиться стикатися при вирішенні науково-технічних і економічних задач обробки сукупностей великої кількості значень.

Масив в Бейсіку. Описувати масив DIM A (N) - це означає надати <N> вільних комірок в пам'яті ЕОМ для масиву з ім'ям А. Якщо опис масиву відсутній, то під одновимірний масив виділяється 10 осередків пам'яті. Кожен елемент масиву в загальному вигляді описується як А (I), де А - ім'я масиву, I-номер або індекс масиву (0 <= I <= N, але практично вживається 1 <= I <= N) A (I) - значення елемента масиву.

Масив в Паскалі. <Ім'я масиву>: = array <кількість елементів> of <тип змінної>; Кожен елемент масиву в загальному вигляді описується як А [I], де А - ім'я масиву, I - номер або індекс масиву (0 <= I <= N, але практично вживається 1 <= I <= N) A [I] - значення елемента масиву.

Wri-teln; їм можна присвоювати будь-які значення, відповідні їх типу.

Двовимірні масиви Паскаля - матриці

Двовимірний масив в Паскалі трактується як одновимірний масив, тип елементів якого також є масивом (масив масивів). Положення елементів у двовимірних масивах Паскаля описується двома індексами. Їх можна представити у вигляді прямокутної таблиці або матриці.

Розглянемо двовимірний масив Паскаля розмірністю 3 * 3, тобто в ній буде три рядки, а в кожному рядку по три елементи:

Кожен елемент має свій номер, як у одновимірних масивів, але зараз номер вже складається з двох чисел - номери рядка, в якому знаходиться елемент, і номери стовпця. Таким чином, номер елемента визначається перетинанням рядка та стовпця. Наприклад, a 21 - це елемент, що стоїть в другому рядку і в першому стовпці.

Опис двовимірного масиву Паскаля.

Існує кілька способів оголошення двовимірного масиву Паскаля.

Ми вже вміємо описувати одновимірні масиви, елементи яких можуть мати будь-який тип, а, отже, і самі елементи можуть бути масивами. Розглянемо наступний опис типів і змінних:

Приклад опису двовимірного масиву Паскаля

Type

Vector = array [1 .. 5] of <тип _ елементів>;

Matrix = array [1 .. 10] of vector;

Var m: matrix;

Ми оголосили двовимірний масив Паскаля m, що складається з 10 рядків, в кожному з яких 5 стовпців. При цьому до кожної i-му рядку можна звертатися m [i], а кожному j-му елементу всередині i-го рядка - m [i, j].

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

Type

Matrix = array [1 .. 5] of array [1 .. 10] of <тип елементів>;

або ще простіше:

type

matrix = array [1 .. 5, 1 .. 10] of <тип елементів>;

Звернення до елементів двовимірного масиву має вигляд: M [i, j]. Це означає, що ми хочемо отримати елемент, розташований в i-му рядку і j-му стовпці. Тут головне не переплутати рядки зі стовпцями, а то ми можемо знову отримати звернення до неіснуючого елементу. Наприклад, звернення до елемента M [10, 5] має правильну форму запису, але може викликати помилку в роботі програми.

Основні дії з двовимірними масивами Паскаля

Все, що було сказано про основні дії з одновимірними масивами, справедливо і для матриць. Єдина дія, яке можна здійснити над однотипними матрицями цілком - це привласнення. Тобто, якщо в програмі у нас описані дві матриці одного типу, наприклад,

type

matrix = array [1 .. 5, 1 .. 10] of integer;

var

a, b: matrix;

то в ході виконання програми можна привласнити матриці a значення матриці b (a: = b). Всі інші дії виконуються поелементно, при цьому над елементами можна виконувати всі припустимі операції, які визначені для типу даних елементів масиву. Це означає, що якщо масив складається з цілих чисел, то над його елементами можна виконувати операції, визначені для цілих чисел, якщо ж масив складається з символів, то до них застосовні операції, визначені для роботи з символами.

Введення двовимірного масиву Паскаля

Для послідовного введення елементів одновимірного масиву ми використовували цикл for, в якому змінювали значення індексу з 1-го до останнього. Але положення елемента в двовимірному масиві Паскаля визначається двома індексами: номером рядка та номером стовпця.

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

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

type

matrix = array [1 .. 5, 1 .. 10] of integer;

var

a,: matrix;

i, j: integer; {індекси масиву}

begin

for i: = 1 to 5 do {цикл для перебору всіх рядків}

for j: = 1 to 10 do {перебір всіх елементів рядка по стовпцях}

readln (a [i, j]); {введення з клавіатури елемента, що стоїть в i-му рядку і j-му стовпці}

Двовимірний масив Паскаля можна заповнити випадковим чином, тобто використовувати функцію random (N), а також присвоїти кожному елементу матриці значення деякого вираження. Спосіб заповнення двовимірного масиву Паскаля вибирається залежно від поставленого завдання, але в будь-якому випадку повинен бути визначений кожен елемент у кожному рядку і кожному стовпці.

Висновок двовимірного масиву Паскаля на екран

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

Приклад програми виведення двовимірного масиву Паскаля

for i: = 1 to 5 do {цикл для перебору всіх рядків}

begin

for j: = 1 to 10 do {перебір всіх елементів рядка по стовпцях}

write (a [i, j]: 4); {друк елементів, що стоять в i-му рядку матриці в одній екранної рядку, при цьому для виведення кожного елемента відводиться 4 позиції}

writeln; {перш, ніж змінити номер рядка в матриці, потрібно перевести курсор на початок нової екранного рядка}

end;

Зауваження (це важливо!): Дуже часто в програмах студентів зустрічається помилка, коли введення з клавіатури або виведення на екран масиву намагаються здійснити наступним чином: readln (a), writeln (a), де а - це змінна типу масив. При цьому їх дивує повідомлення компілятора, що змінну цього типу неможливо вважати або надрукувати. Може бути, ви зрозумієте, чому цього зробити не можна, якщо представите N кухлів, що стоять в ряд, а у вас в руках, наприклад, чайник з водою. Можете ви по команді «налий воду» наповнити відразу всі гуртки? Як би ви не намагалися, але в кожну кухоль доведеться наливати окремо. Заповнення та виведення на екран елементів масиву також має здійснюватися послідовно і поелементно, тому що в пам'яті ЕОМ елементи масиву розташовуються в послідовних осередках.

Представлення двовимірного масиву Паскаля в пам'яті

Елементи абстрактного масиву в пам'яті машини фізично розташовуються послідовно, згідно з описом. При цьому кожен елемент займає у пам'яті кількість байт, відповідне його розміром. Наприклад, якщо масив складається з елементів типу integer, то кожен елемент буде займати по два байти. А весь масив займе S ^ 2 байти, де S - кількість елементів у масиві.

А скільки місця займе масив, що складається з масивів, тобто матриця? Очевидно: S i ^ S j, де S i - кількість рядків, а S j - кількість елементів у кожному рядку. Наприклад, для масиву типу

Matrix = array [1 .. 3, 1 .. 2] of integer;

буде потрібно 12 байт пам'яті.

Як будуть розташовуватися в пам'яті елементи цього масиву? Розглянемо схему розміщення масиву M типу matrix в пам'яті.

Під кожен елемент M [i, j] типу integer виділяється два відділення пам'яті. Розміщення в пам'яті здійснюється «знизу вгору». Елементи розміщуються в порядку зміни індексу, що відповідає схемі вкладених циклів: спочатку розміщується перший рядок, потім друга, третя ... Усередині рядка по порядку йдуть елементи: перший, другий і т.д.

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

При реальному доступі до комірки пам'яті, в якій зберігається елемент двовимірного масиву, система обчислює її адресу за формулою:

Addr + Size Elem * Cols * (I -1) + Size Elem * (J -1),

де Addr - фактичний початковий адреса, за якою масив розташовується в пам'яті; I, J - індекси елемента в двовимірному масиві; SizeElem - розмір елемента масиву (наприклад, два байти для елементів типу integer); Cols - кількість елементів у рядку.

Вираз SizeElem * Cols * (I -1) + SizeElem * (J -1) називають зсувом щодо початку масиву.

Приклади розв'язання задач з двовимірними масивами Паскаля

Завдання: Знайти добуток ненульових елементів матриці.

Рішення:

Для вирішення даної задачі нам потрібні змінні: матриця, що складається, наприклад, з цілочисельних елементів; P - твір елементів, відмінних від 0; ​​I, J - індекси масиву; N, M - кількість рядків і стовпців в матриці. Вхідними даними є N, M - їх значення введемо з клавіатури; матриця - введення матриці оформимо у вигляді процедури, заповнення матриці здійснимо випадковим чином, тобто за допомогою функції random (). Вихідними даними буде значення змінної P (твір). Щоб перевірити правильність виконання програми, необхідно вивести матрицю на екран, для цього оформимо процедуру виведення матриці. Хід виконання завдання:

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

введемо значення N і M; Введемо двовимірний масив Паскаля, для цього звертаємося до процедури vvod (a), де а - матриця; Надрукуємо отриману матрицю, для цього звертаємося до процедури print (a); Привласнимо початкове значення змінної P = 1; Будемо послідовно перебирати всі рядки I від 1-ої до N-й, у кожному рядку будемо перебирати всі стовпці J від 1-го до M-го, для кожного елемента матриці будемо перевіряти умову: якщо a ij? 0, то твір P будемо домножать на елемент a ij (P = P * a ij); Виведемо на екран значення твору ненульових елементів матриці - P;

А тепер поговоримо про процедури.

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

Type

Matrix = array [1 .. 10, 1 .. 10] of integer;

..............................

procedure primer (a: matrix);

..............................

Повернемося тепер до наших процедур.

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

Тоді заголовок нашої процедури буде виглядати так:

Procedure vvod (var m: matrix);

Для реалізації вкладених циклів у процедурі нам будуть потрібні локальні змінні-лічильники, наприклад, k і h. Алгоритм заповнення матриці вже обговорювалося, тому не будемо його повторювати.

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

Procedure print (m: matrix);

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

Приклад програми двовимірного масиву Паскаля

Program proizvedenie;

Type

Matrix = array [1 .. 10, 1 .. 10] of integer;

Var

A: matrix;

N, m, i, j: byte;

P: integer;

Procedure vvod (var m: matrix);

Var k, h: byte;

Begin

For i: = 1 to n do {мінлива n для процедури є глобальною, а значить «відомої»}

For j: = 1 to m do {мінлива m для процедури є глобальною, а значить «відомої»}

M [i, j]: = random (10);

End;

Procedure print (m: matrix);

Var k, h: byte;

Begin

For i: = 1 to n do

begin

For j: = 1 to m do

Write (M [i, j]: 4);

Writeln;

end;

End;

Begin {початок основної програми}

Writeln ('Введіть розмірність матриці:');

Readln (N, M);

Vvod (a);

14

Print (a);

P: = 1;

For i: = 1 to N do

For j: = 1 to M do

If a [i, j] <> 0 then p: = p * a [i, j];

Writeln (p);

End.

Методи доступу до елементів масивів

У мові СІ між покажчиками і масивами існує тісний зв'язок. Наприклад, коли оголошується масив у вигляді int array [25], то цим визначається не тільки виділення пам'яті для двадцяти п'яти елементів масиву, але й для покажчика з ім'ям array, значення якого дорівнює адресою першого по рахунку (нульового) елемента масиву, тобто . сам масив залишається безіменним, а доступ до елементів масиву здійснюється через покажчик з ім'ям array. З точки зору синтаксису мови покажчик arrey є константою, значення якої можна використовувати у виразах, але змінити це значення не можна.

Оскільки ім'я масиву є вказівником припустимо, наприклад, таке присвоювання:

int array [25];

int * ptr;

ptr = array;

Тут покажчик ptr встановлюється на адресу першого елемента масcіва, причому присвоювання ptr = arrey можна записати в еквівалентній формі ptr = & arrey [0].

Для доступу до елементів масиву існує два різні способи. Перший спосіб пов'язаний з використанням звичайних індексних виразів у квадратних дужках, наприклад, array [16] = 3 або array [i +2] = 7. При такому способі доступу записуються два вирази, причому другий вираз у квадратних дужках. Одне з цих висловів має бути дороговказом, а друге - вираженням цілого типу. Послідовність запису цих виразів може бути будь-який, але у квадратних дужках записується вираз наступне другим. Тому записи array [16] і 16 [array] будуть еквівалентними і позначають елемент масиву з номером шістнадцять. Покажчик використовуваний в індексному вираженні не обов'язково повинен бути константою, що вказує на який-небудь масив, це може бути і змінна. Зокрема після виконання присвоювання ptr = array доступ до шістнадцятого елементу масиву можна отримати за допомогою покажчика ptr у формі ptr [16] або 16 [ptr].

Другий спосіб доступу до елементів масиву пов'язаний з використанням адресних висловів та операції разадресаціі у формі * (array +16) = 3 або * (array + i +2) = 7. При такому способі доступу адресне вираз рівне адресою шістнадцятого елемента масиву теж може бути записано різними способами * (array +16) або * (16 + array).

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

15

Для наведених прикладів array [16] і 16 [array] перетворюються в * (array +16).

Для доступу до початкової елементу масиву (тобто до елементу з нульовим індексом) можна використовувати просто значення покажчика array або ptr. Будь-яке з присвоювання

* Array = 2;

array [0] = 2;

* (Array +0) = 2;

* Ptr = 2;

ptr [0] = 2;

* (Ptr +0) = 2;

присвоює початковому елементу масиву значення 2, але швидше за все виконаються присвоювання * array = 2 і * ptr = 2, тому що в них не потрібно виконувати операції додавання.

Покажчики на багатовимірні масиви

Покажчики на багатовимірні масиви в мові СІ - це масиви масивів, тобто такі масиви, елементами яких є масиви. При оголошенні таких масивів у пам'яті комп'ютера створюється кілька різних об'єктів. Наприклад при виконанні оголошення двовимірного масиву int arr2 [4] [3] в пам'яті виділяється ділянка для зберігання значення змінної arr, яка є покажчиком на масив з чотирьох покажчиків. Для цього масиву з чотирьох покажчиків теж виділяється пам'ять. Кожен з цих чотирьох покажчиків містить адресу масиву з трьох елементів типу int, і, отже, в пам'яті комп'ютера виділяється чотири ділянки для збереження чотирьох масивів чисел типу int, кожен з яких складається з трьох елементів. Таке виділення пам'яті показано на схемі на arr

Розподіл пам'яті для двовимірного масиву.

arr [0] а

arr [0] [0]

arr [0] [1]

arr [0] [2]

arr [1] а

arr [1] [0]

arr [1] [1]

arr [1] [2]

arr [2] а

arr [2] [0]

arr [2] [2]

arr [2] [1]

arr [3], а

arr [3] [0]

arr [3] [1]

arr [3] [2]

Таким чином, оголошення arr2 [4] [3] породжує в програмі три різних об'єкта: покажчик з ідентифікатором arr, безіменний масив з чотирьох покажчиків і безіменний масив з дванадцяти чисел типу int. Для доступу до безіменних масивів використовуються адресні вираження з покажчиком arr. Доступ до елементів масиву покажчиків здійснюється за вказівкою одного індексного вираження у формі arr2 [2] або * (arr2 +2). Для доступу до елементів двовимірного масиву чисел типу int повинні бути використані два індексні вираження у формі arr2 [1] [2] або еквівалентних їй * (* (arr2 +1) +2) і (* (arr2 +1)) [2] . Слід враховувати, що з точки зору синтаксису мови СІ покажчик arr і покажчики arr [0], arr [1], arr [2], arr [3] є константами та їх значення не можна змінювати під час виконання програми.

Розміщення тривимірного масиву відбувається аналогічно і оголошення float arr3 [3] [4] [5] породжує в програмі окрім самого тривимірного масиву з шістдесяти чисел типу float масив з чотирьох покажчиків на тип float, масив з трьох покажчиків на масив покажчиків на float, і покажчик на масив масивів вказівників на float.

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

Наприклад, звернення до елемента arr2 [1] [2] можна здійснити за допомогою покажчика ptr2, оголошеного у формі int * ptr2 = arr2 [0] як звернення ptr2 [1 * 4 +2] (тут 1 і 2 це індекси використовуваного елемента, а 4 це число елементів у рядку) або як ptr2 [6]. Зауважимо, що зовні схоже звернення arr2 [6] виконати неможливо так як покажчика з індексом 6 не існує.

Для звернення до елемента arr3 [2] [3] [4] з тривимірного масиву теж можнo використовувати покажчик, описаний як float * ptr3 = arr3 [0] [0] з одним індексним вираженням у формі ptr3 [3 * 2 +4 * 3 +4] або ptr3 [22].

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

struct INDEX {int i,

int j,

int k} min_index;

struct INDEX * find_min (int * ptr1, int l, int m int n)

{Int min, i, j, k, ind;

min =* ptr1;

min_index.i = min_index.j = min_index.k = 0;

for (i = 0; i * (ptr1 + ind)

{Min =* (ptr1 + ind);

min_index.i = i;

min_index.j = j;

min_index.k = k;

}

}

return & min_index;

}

Операції з вказівниками

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

Приклад:

int * ptr, a [10];

ptr = & a [5];

ptr + + / * одно адресою елемента a [6] * /

ptr - / * одно адресою елемента a [5] * /

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

Приклад:

int * ptr1, * ptr2, a [10];

int i = 2;

ptr1 = a + (i +4); / * одно адресою елемента a [6] * /

ptr2 = ptr1-i; / * одно адресою елемента a [4] * /

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

Приклад:

int * ptr1, * ptr2, a [10];

int i;

ptr1 = a +4;

ptr2 = a +9;

i = ptr1-ptr2; / * дорівнює 5 * /

i = ptr2-ptr1; / * одно -5 * /

Значення двох покажчиків на однакові типи можна порівнювати в операціях ==,! =, <, <=,>,> = при цьому значення покажчиків розглядаються просто як цілі числа, а результат порівняння дорівнює 0 (брехня) або 1 (істина).

Приклад:

int * ptr1, * ptr2, a [10];

ptr1 = a +5;

ptr2 = a +7;

if (prt1> ptr2) a [3] = 4;

У даному прикладі значення ptr1 менше значення ptr2 і тому оператор a [3] = 4 не буде виконаний.

Масиви покажчиків

У мові СІ елементи масивів можуть мати будь-який тип, і, зокрема, можуть бути покажчиками на будь-який тип. Розглянемо кілька прикладів з використанням покажчиків.

Наступні оголошення змінних

int a [] = {10,11,12,13,14,};

int * p [] = {a, a +1, a +2, a +2, a +3, a +4};

int ** pp = p;

породжують програмні об'єкти, що представлені на схемі

pp pа. . . . .

в у в у в

18

aа 11 12 13 14 15

Схема розміщення змінних при оголошенні.

При виконанні операції pp-p отримаємо нульове значення, так як посилання pp і p рівні і вказують на початковий елемент масиву покажчиків, пов'язаного з покажчиком p (на елемент p [0]).

Після виконання операції pp + = 2 схема зміниться і прийме вигляд, зображений

pp pа. . . .

в у в у в

aа 10 11 12 13 14

Схема розміщення змінних після виконання операції pp + = 2.

Результатом виконання вирахування pp-p буде 2, оскільки значення pp є адреса третього елемента масиву p. Посилання * pp-a теж дає значення 2, оскільки звернення * pp є адреса третього елемента масиву a, а звернення a є адреса початкового елемента масиву a. При зверненні за допомогою посилання ** pp отримаємо 12 - це значення третього елемента масиву a. Посилання * pp + + дасть значення четвертого елемента масиву p тобто адреса четвертого елемента масиву.

Якщо вважати, що pp = p, то звернення * + + pp це значення першого елемента масиву a (тобто значення 11), операція + + * pp змінить вміст покажчика p [0], таким чином, що він стане рівним значенню адреси елемента a [1].

Складні звернення розкриваються зсередини. Наприклад звернення *(++(* pp)) можна розбити на наступні дії: * pp дає значення початкового елемента масиву p [0], далі це значення інкременіруется + + (* p) у результаті чого покажчик p [0] стане дорівнює значенню адреси елемента a [1], і останнє дію це вибірка значення за отриманим адресою, тобто значення 11.

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

int a [3] [3] = {{11,12,13},

{21,22,23},

{31,32,33}};

int * pa [3] = {a, a [1], a [2]};

int * p = a [0];

Схема розміщення покажчиків на двовимірний масив.

Відповідно до цієї схеми доступ до елемента a [0] [0] отримати за вказівниками a, p, pa за допомогою наступних посилань: a [0] [0], * a, ** a [0], * p, ** pa , * p [0].

Розглянемо тепер приклад з використанням рядків символів. Оголошення змінних можна зобразити схемою представленої:

char * c [] = {"abs", "d", "yes", "no"};

char ** cp [] = {c +3, c +2, c +1, c};

char *** cpp = cp;

Схема розміщення покажчиків на рядки.

Динамічне розміщення масивів

При динамічному розподілі пам'яті для масивів слід описати відповідний покажчик і присвоювати йому значення за допомогою функції calloc. Одновимірний масив a [10] з елементів типу float можна створити таким чином

float * a;

a = (float *) (calloc (10, sizeof (float));

Для створення двовимірного масиву спочатку потрібно розподілити пам'ять для масиву покажчиків на одновимірні масиви, а потім розподіляти пам'ять для одновимірних масивів. Нехай, наприклад, потрібно створити масив a [n] [m], це можна зробити за допомогою наступного фрагмента програми:

# Include

main ()

{Double ** a;

int n, m, i;

scanf ("% d% d", & n, & m);

a = (double **) calloc (m, sizeof (double *));

for (i = 0; i <= m; i + +)

a [i] = (double *) calloc (n, sizeof (double));

. . . . . . . . . . . .

}

Аналогічним чином можна розподілити пам'ять і для тривимірного масиву розміром n, m, l. Варто тільки пам'ятати, що непотрібну для подальшого виконання програми пам'ять слід звільняти за допомогою функції free.

# Include

main ()

{Long *** a;

int n, m, l, i, j;

scanf ("% d% d% d", & n, & m, & l);

/ * -------- Розподіл пам'яті -------- * /

a = (long ***) calloc (m, sizeof (long **));

for (i = 0; i <= m; i + +)

{A [i] = (long **) calloc (n, sizeof (long *));

for (j = 0; i <= l; j + +)

a [i] [j] = (long *) calloc (l, sizeof (long));

}

. . . . . . . . . . . .

/ * --------- звільнення пам'яті ----------*/

for (i = 0; i <= m; i + +)

{For (j = 0; j <= l; j + +)

free (a [i] [j]);

free (a [i]);

}

free (a);

}

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

Приклад:

# Include

main ()

{Int vvod (double ***, long **);

double ** a / * вказівник для масиву a [n] [m] * /

long * b / * вказівник для масиву b [n] * /

vvod (& a, & b);

.. / * У функцію vvod передаються адреси покажчиків, * /

.. / * А НЕ їх значення * /

..

}

int vvod (double *** a, long ** b)

{Int n, m, i, j;

scanf ("% d% d", & n, & m);

* A = (double **) calloc (n, sizeof (double *));

* B = (long *) calloc (n, sizeof (long));

for (i = 0; i <= n; i + +)

* A [i] = (double *) calloc (m, sizeof (double));

.....

}

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

Приклад:

# Include

int main ()

{Float * q, ** b;

int i, j, k, n, m;

scanf ("% d% d", & n, & m);

q = (float *) calloc (m, sizeof (float));

/ * Зараз покажчик q показує на початок масиву * /

q [0] = 22.3;

q-= 5;

/ * Тепер початковий елемент масиву має індекс 5, * /

/ * А кінцевий елемент індекс n-5 * /

q [5] = 1.5;

/ * Зрушення індексу не призводить до перерозподілу * /

/ * Масиву в пам'яті і зміниться початковий елемент * /

q [6] = 2.5; / * - це другий елемент * /

q [7] = 3.5; / * - це третій елемент * /

q + = 5;

/ * Тепер початковий елемент знову має індекс 0, * /

/ * А значення елементів q [0], q [1], q [2] рівні * /

/ * Відповідно 1.5, 2.5, 3.5 * /

q + = 2;

/ * Тепер початковий елемент має індекс -2, * /

/ * Наступний -1, потім 0 і т.д. по порядку * /

q [-2] = 8.2;

q [-1] = 4.5;

q-= 2;

/ * Повертаємо початкову індексацію, три перші * /

/ * Елемента масиву q [0], q [1], q [2], мають * /

/ * Значення 8.2, 4.5, 3.5 * /

q -;

/ * Знову змінимо індексацію. * /

/ * Для визволення області пам'яті у якій розміщений * /

/ * Масив q використовується функція free (q), але оскільки * /

/ * Значення покажчика q усунута з посади, то виконання * /

/ * Функції free (q) призведе до непередбачуваних наслідків. * /

/ * Для правильного виконання цієї функції * /

/ * Вказівник q повинен бути повернений в початкове * /

/ * Стан * /

free (+ + q);

/ * Розглянемо можливість зміни індексації і * /

/ * Звільнення пам'яті для двовимірного масиву * /

b = (float **) calloc (m, sizeof (float *));

for (i = 0; i <m; i + +)

b [i] = (float *) calloc (n, sizeof (float));

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

/ * Масиву буде елемент b [0] [0] * /

/ * Виконаємо зрушення індексів так, щоб початковим * /

/ * елементом став елемент b [1] [1] * /

for (i = 0; i <m; i + +) - b [i];

b -;

/ * Тепер привласнимо кожному елементу масиву суму його * /

/ * Індексів * /

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

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

b [i] [j] = (float) (i + j);

/ * Зверніть увагу на початкові значення лічильників * /

/ * Циклів i і j, він починаються з 1 а не з 0 * /

/ * Повернемось до колишньої індексації * /

for (i = 1; i <= m; i + +) + + b [i];

b + +;

/ * Виконаємо звільнення пам'яті * /

for (i = 0; i <m; i + +) free (b [i]);

free (b);

...

...

return 0;

}

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

Приклад:

# Include

# Include

double cos (double);

double sin (double);

double tan (double);

int main ()

{Double (* (* masfun)) (double);

double x = 0.5, y;

int i;

masfun = (double (*(*))( double))

calloc (3, sizeof (double (*(*))( double)));

masfun [0] = cos;

masfun [1] = sin;

masfun [2] = tan;

for (i = 0; i <3; i + +);

{Y = masfun [i] (x);

printf ("\ nx =% gy =% g", x, y);

}

return 0;

}

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

int a [4] [3];

Аналіз подібного опису необхідно проводити в напрямку виконання операцій [], тобто зліва направо. Таким чином, змінна a є масивом з чотирьох елементів, що випливає з першої частини опису a [4]. Кожен елемент a [i] цього масиву в свою чергу є масивом з трьох елементів типу int, що випливає з другої частини опису.

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

Масиву

Стовпець 0

Стовпчик 1

Стовпчик 2

Рядок 0

18

21

5

Рядок 1

6

7

11

Рядок 2

30

52

34

Рядок 3

24

4

67

Ім'я двовимірного масиву без квадратних дужок за ним має значення адреси першого елемента цього масиву, тобто значення адреси першого рядка - одновимірного масиву з трьох елементів. При використанні у виразах тип імені двовимірного масиву перетвориться до типу адреси рядки цього масиву. У нашому прикладі тип імені масиву a у виразах буде приведений до типу адреси масиву з трьох елементів типу int і може використовуватися у всіх виразах, де допускається використання відповідного адреси.

Ім'я двовимірного масиву з одним індексним виразом у квадратних дужках за ним позначає відповідний рядок двовимірного масиву і має значення адреси першого елемента цього рядка. Наприклад, у нашому випадку a [2] є адресою величини типу int, а саме осередку, в якому знаходиться число 30, і може використовуватися скрізь, де допускається використання адреси величини типу int.

Ім'я двовимірного масиву з двома індексними виразами у квадратних дужках за ним позначає відповідний елемент двовимірного масиву і має той же тип. Наприклад, у нашому прикладі a [2] [1] є величиною типу int, а саме осередком, в якій знаходиться число 52, і може використовуватися скрізь, де допускається використання величини типу int.

Відповідно до інтерпретацією опису двовимірного масиву (зліва-направо) елементи останнього розташовуються в пам'яті ЕОМ по рядках.

Ініціалізація двовимірного масиву також проводиться по рядках, наприклад, для того щоб отримати вищеописаний масив a, можна було б провести наступну ініціалізацію

int a [] [3] = {

{18, 21, 5},

{6, 7, 11},

{30, 52, 34},

{24, 4, 67}

};

Тут перший розмір масиву буде визначено компілятором. Слід зазначити, що другий розмір масиву повинен бути завжди вказаний. Це необхідно для того, щоб повідомити компілятору розмір рядка масиву, без якого компілятор не може правильно розмістити двовимірний масив в пам'яті ЕОМ.

Для ініціалізації двовимірного масиву символів можна використовувати спрощений синтаксис ініціалізації рядків:

char s [] [17] = {

"Рядок 1",

"Довга рядок 2",

"Рядок 3"

}

Розмір пам'яті замовлений під кожну рядок у цьому випадку повинен бути рівним довжині найдовшою рядка з урахуванням нуль-символу. При цьому, для частини рядків (рядок 1 і рядок 3) буде виділено зайва кількість пам'яті. Таким чином, зберігання рядків різної довжини в двовимірному масиві символів недостатньо ефективно з точки зору використання пам'яті.

Введення двовимірного масиву здійснюється поелементно за допомогою двох вкладених циклів. Наступний фрагмент програми призначений для введення по рядках двовимірного масиву елементів типу double розміром n рядків на m стовпців

for (i = 0; i <n; i + +)

for (j = 0; j <m; j + +)

{

printf ("a [% d] [% d] =", i, j);

scanf ("% lf", & a [i] [j]);

}

Для введення масиву по стовпцях досить поміняти місцями рядки програми, які є заголовками циклів.

Висновок такого ж двовимірного масиву ілюструє наступний фрагмент:

for (i = 0; i <n; i + +)

{

for (j = 0; j <m; j + +) printf ("% 9.3lf", a [i] [j]);

printf ("\ n");

}

У даному фрагменті після виведення чергового рядка масиву здійснюється перехід на наступний рядок дисплея.

У мові Сі допускається використовувати не тільки двовимірні, а й тривимірні, чотиривимірні і т. д. масиви. Їх використання нічим принципово не відрізняється від використання двовимірних масивів, однак на практиці вони застосовуються значно рідше.

Індексний масив

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

Індекс масиву - ціле число, яке значення типу, що приводиться до цілого, яке вказує на конкретний елемент масиву.

У ряді скриптових мов, наприклад JavaScript, PHP, Ruby застосовуються також асоціативні масиви, в яких змінні не зобов'язані бути однотипними,

і доступ до них не обов'язково здійснюється за індексом.

Загальний опис

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

Приклад статичного масиву на Паскалі -

word Array: array [Word] of Integer; { Статичний, розмір = High (Word) + 1}

multi Array: array [Byte, 1 .. 5] of Char; { Статичний масив, 2 вимірювання }

rang e Array: array [5 .. 20] of String; { Статичний масив, розмір = 16}

Приклад статичного масиву на С / С + + -

int Array [10]; / / Статичний, розмір 10, базовий тип даних - ціле число (int)

double Array [12] [15]; / / Статичний масив, 2 виміру, базовий тип даних - число / / з дробової частиною (double)

Підтримка індексних масивів (свій синтаксис оголошення, функції для роботи з елементами і т. д.) є в більшості високорівневих мов програмування. Максимально допустима розмірність масиву, типи і діапазони значень індексів, обмеження на типи елементів визначаються мовою програмування та / або конкретним транслятором.

У мовах програмування, що допускають оголошення програмістом власних типів, як правило, існує можливість створення типу «масив». У визначенні такого типу може вказуватися розмір, тип елемента, діапазон значень і типи індексів. Надалі можливе визначення змінних створеного типу. Всі такі змінні-масиви мають одну структуру. Деякі мови підтримують для змінних-масивів операції присвоєння (коли однією операцією всіх елементів масиву присвоюються значення відповідних елементів іншого масиву).

Оголошення типу «масив» в Паскалі -

type

T Array Type = array [0 .. 9] of Integer; (* Оголошення типу "масив" *)

var

arr1, arr2, arr3: TArrayType; (* Оголошення трьох змінних-масивів одного типу *)

Специфічні типи масивів

Динамічні масиви

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

Приклад динамічного масиву на Delphi

byte Array: Array of Byte; / / Одновимірний масив

multi Array: Array of Array of string; / / Багатомірний масив

Приклад динамічного масиву на Сі

float * array1; / / Одновимірний масив

int ** array2; / / Багатомірний масив

array1 = (float *) malloc (10 * sizeof (float)); / / виділення 10 блоків по sizeof (float) байт кожен

array2 = (int **) malloc (16 * sizeof (int *)); / / виділення 16 * 8 блоків по sizeof (int) байт кожен

for (i = 0; i <16; i + +)

array2 [i] = (int *) malloc (8 * sizeof (int));

Приклад динамічного масиву на С + +

float * array1; / / Одновимірний масив

int ** array2; / / Багатомірний масив

array1 = new float [10]; / / виділення 10 блоків розміром типу float

array2 = new int * [16]; / / виділення 16 * 8 блоків розміром типу int

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

array2 [i] = new int [8];

Гетерогенні масиви

Гетерогенним називається масив, в різні елементи якого можуть бути безпосередньо записані значення, пов'язані з різним типам даних. Масив, який зберігає покажчики на значення різних типів, не є гетерогенним, так як власне зберігаються в масиві дані відносяться до єдиного типу - типу «покажчик». Гетерогенні масиви зручні як універсальна структура для зберігання наборів даних довільних типів. Відсутність їх підтримки в мові програмування призводить до необхідності реалізації більш складних схем зберігання даних. З іншого боку, реалізація гетерогенності вимагає ускладнення механізму підтримки масивів у транслятор мови. Гетерогенний масив як вбудований тип даних є в мові PHP.

Масиви масивів

Багатовимірні масиви, як правило, реалізовані як одномірні масиви, кожен елемент яких є посиланням на інший одновимірний масив.

Реалізація

Стандартним способом реалізації статичних масивів з одним типом елементів є наступний:

Під масив виділяється безперервний блок пам'яті об'ємом S * m1 * m2 * m3 ... mn, де S - розмір одного елемента, а m1 ... mn - розміри діапазонів індексів (тобто кількість значень, які може приймати відповідний індекс).

При зверненні до елемента масиву A [i1, i2, i3, ... in] адресу відповідного елемента обчислюється як B + S * (i1p * m1 + i2p * m2 + ... + i (n-1) p * mn-1 + inp), де B -

27

база (адреса початку блоку пам'яті масиву), ikp-значення k-го індексу, наведене до цілого з нульовим початковим зміщенням.

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

Перший елемент масиву, в залежності від мови програмування, може мати різний індекс. Розрізняють три основні різновиди масивів: з відліком від нуля (zero-based), з відліком від одиниці (one-based) і з відліком від специфічного значення заданого програмістом (n-based). Відлік індексу елемента масивів з нуля більш характерний для низькорівневих ЯП, однак цей метод був популяризував у мовах більш високого рівня мовою програмування С.

Більш складні типи масивів - динамічні та гетерогенні - реалізуються складніше.

Переваги

легкість обчислення адреси елемента за його індексом (оскільки елементи масиву розташовуються один за іншим)

однаковий час доступу до всіх елементів

малий розмір елементів: вони складаються тільки з інформаційного поля

Недоліки

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

для динамічного і / або гетерогенного масиву - більш низька (у порівнянні зі звичайним статичним) швидкодію і додаткові накладні витрати на підтримку динамічних властивостей і / або гетерогенності.

при роботі з масивом у стилі C (з покажчиками) і при відсутності додаткових засобів контролю - загроза виходу за межі масиву і пошкодження даних

Висновок

На даний момент світова комп'ютерна індустрія розвивається дуже стрімко. Продуктивність систем зростає, а отже зростають можливості обробки великих обсягів даних. Операційні системи класу MS-DOS вже не справляються з таким потоком даних і не можуть цілком використовувати ресурси сучасних комп'ютерів. Тому вона більше ніде широко не використовується. Усі намагаються перейти на більш досконалі ОС, якими є UNIX та Windows. Але через "непопулярність", UNIX мало хто використовує цей ОС. У всьому світі все, починаючи від домогосподарок і закінчуючи корпоративними користувачами, користуються Windows 9x.

У цій роботі ми розглянули основне поняття програмування.

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

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

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

Список літератури

Основна

1.Львовскій М.Б. Методичний посібник «BOOK» з інформатики для 9-11 класів.

2.Гусак А.А. Вища математика. У 2-х т. Т. 2.: Учеб. Посібник для студентів вузів. - Мн.: ТетраСистемс, 1998. - 448 с.

3.Ліходед Н.А. Методи розпаралелювання гнізд циклів: Курс лекцій. - Мн.: БДУ. 2007. - 100 с. Ser314 \ subFaculty \ Каф. Дискриміна. мат. та алгоритми \ КУРСИ ДМА \ 4 курс \ Лиходід \ Лекції \ Розпаралелювання гнізд циклів.

4.Вірт М. Алгоритми + структури даних = програми. - М.: Світ, 1985. - С. 406.

5.Светозарова Г.І., Мельников А.А., Козловський А.В. Практикум з програмування на мові Бейсік: Навчальний посібник для вузів. - М.: Наука, 1988.

Додаткова

1.Істочнікі: Львівський М.Б. Методичний посібник «BOOK» з інформатики для 9-11 класів. Адреса: http://markbook.chat.ru/book/

2.Йенсен К., Вірт Н. Паскаль. Керівництво для користувача і опис мови. - М.: Фінанси і статистика, 1982. - С. 151.

3.Пермінов О. М. Мова програмування Паскаль: Довідник. - М.: Радіо і зв'язок, 1989. - С. 128. - ISBN 5-256-00311-9

4.Для підготовки даної роботи були використані матеріали з сайту http://www.comp-science.ru/

5.Вострікова З.П., Вострикова О.Ю., Туєва С.С. Програмування на мові "Бейсик" для персональних ЕОМ. - М.: Фінанси і статистика, 1993.

Посилання (links):
  • http://markbook.chat.ru/book/
  • Додати в блог або на сайт

    Цей текст може містити помилки.

    Програмування, комп'ютери, інформатика і кібернетика | Курсова
    218.7кб. | скачати


    Схожі роботи:
    Одновимірні і двовимірні масиви
    Масиви в С З
    Масиви в С З 2
    Масиви
    Масиви в СС
    Болотні масиви
    Програмування масиви та рядки
    Масиви у мові Паскаль
    Масиви та покажчики в мові програмування Сі
    © Усі права захищені
    написати до нас