Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
161693.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
188.42 Кб
Скачать

2.2 Модульне програмування

Згодом при проектуванні програм акцент змістився з організації процедур на організацію структур даних. Крім усього іншого це викликано й ростом розмірів програм.

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

1. Надати користувачеві інтерфейс для стека (наприклад, функції push () і pop ()).

2. Гарантувати, що подання стека (наприклад, у вигляді масиву елементів) буде доступно лише через інтерфейс користувача.

3. Забезпечувати ініціалізацію стека перед першим його використанням.

Цілком можливо, що реалізація стека може змінитися, наприклад, якщо використати для зберігання зв'язаний список. Користувач у кожному разі не має безпосереднього доступу до реалізації: v й p - статичні змінні, тобто змінні локальні в тім модулі (файлі), у якому вони описані. Оскільки дані є єдина річ, що хочуть приховувати, поняття приховування даних тривіально розширюється до поняття приховування інформації, тобто імен змінних, констант, функцій і типів, які теж можуть бути локальними в модулі. Хоча С++ і не призначався спеціально для підтримки модульного програмування, класи підтримують концепцію модульності. Крім цього С++, природно, має вже продемонстровані можливості модульності, які є в С, тобто подання модуля як окремої одиниці трансляції.

2.3 Об’єктно-орієнтоване програмування

Проблема полягає в тому, що ми не розрізняємо загальні властивості фігур (наприклад, фігура має кольори, її можна намалювати й т.д.) і властивості конкретної фігури (наприклад, окружність - це така фігура, що має радіус, вона зображується за допомогою функції, що малює дуги й т.д.). Суть об’єктно-орієнтованого програмування в тім, що воно дозволяє виражати ці розходження й використовує їх. Мова, що має конструкції для вираження й використання подібних розходжень, підтримує об’єктно-орієнтоване програмування. Всі інші мови не підтримують його. Ті функції, для яких можна визначити заявлений інтерфейс, але реалізація яких (тобто тіло з операторною частиною) можлива тільки для конкретних фігур, відзначені службовим словом virtual (віртуальні). У Симулі й С++ віртуальність функції означає: "функція може бути визначена пізніше в класі, похідному від даного". Для визначення конкретної фігури варто вказати, насамперед, що це - саме фігура й задати її особливі властивості (включаючи й віртуальні функції. У мові С++ клас circle називається похідним стосовно класу shape, а клас shape називається базовим для класу circle. Можлива інша термінологія, що використає назви "підклас" й "суперклас" для класів circle й shape відповідно. Тепер парадигма програмування формулюється так: визначите, який клас вам необхідний; надайте повний набір операцій для кожного класу; спільність класів визначте явно за допомогою спадкування. Якщо спільність між класами відсутній, цілком достатньо абстракції даних. Наскільки застосовне об’єктно-орієнтоване програмування для даної області додатка.

РОЗДІЛ 3. ОБ’ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ

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

їclass shape

{

point center;

color col;

// ...

public:

point where () { return center; }

void move ( point to ) { center = to; draw(); }

virtual void draw ();

virtual void rotate ( int );

// ...

};

Ті функції, для яких визначаємо заявлений інтерфейс, але реалізація яких (тобто тіло з операторною частиною) можлива тільки для конкретних фігур, відзначені службовим словом vіrtual (віртуальні). У Симуле і С++ віртуальність функції означає: "функція може бути визначена пізніше в класі, похідному від даного". З урахуванням такого визначення класу пишу загальні функції, що працюють з фігурами:

void rotate_all ( shape v [], int size, int angle )

// повернути всі елементи масиву "v" розміру "size"

// на кут рівний "angle"

{

int i = 0;

while ( i<size )

{

v [ i ] . rotate ( angle );

i = i + 1;

}

}

Для визначення конкретної фігури варто вказати, насамперед , що це - саме фігура і задати її особливі властивості (включаючи і віртуальні функції):

class circle : public shape

{

int radius;

public:

void draw () { /* ... */ };

void rotate ( int ) {} // да, поки функція порожня

};

У мові С++ клас cіrcle називається похідним стосовно класу shape, а клас shape називається базовим для класу cіrcle. Можлива інша термінологія, що використовує назви "підклас" і "суперклас" для класів cіrcle і shape відповідно. Тепер парадигма програмування формулюється так: Визначите, який клас вам необхідний; надайте повний набір операцій для кожного класу; спільність класів виразите явне за допомогою спадкування. Якщо спільність між класами відсутня, цілком достатньо абстракції даних. Наскільки застосовне об’єктно-орієнтоване програмування для даної області додатка визначається ступенем спільності між різними типами, що дозволяє використовувати спадкування і віртуальні функції. У деяких областях, таких, наприклад, як інтерактивна графіка, є широкий простір для об’єктно-орієнтованого програмування. В інших областях,

у яких використовуються традиційні арифметичні типи й обчислення над ними, важко знайти застосування для більш розвитих стилів програмування, чим абстракція даних. Цей засіб, що підтримує об’єктно-орієнтоване програмування, мабуть, надлишковий. Перебування спільності серед окремих типів системи являє собою нетривіальний процес. Ступінь такої спільності залежить від способу проектування системи. У процесі проектування виявлення спільності класів повинне бути постійною метою. Вона досягається двома способами: або проектуванням спеціальних класів, використовуваних як "цеглини" при побудові інших, або пошуком схожих класів для виділення їхньої загальної частини в один базовий клас. Отже, ми вказали, яку мінімальну підтримку повинна забезпечувати мова програмування для процедурного програмування, для заховування даних, абстракції даних і об’єктно-орієнтоване програмування.

1. Масиви в мові С

1.1. Поняття масиву

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

2. Алгоритми обробки одновимірних масивів

2.1. Ініціалізація масиву

2.2. Введення - виведення одновимірного масиву

2.3. Перестановка двох елементів масиву

2.4. Обчислення суми елементів масиву

2.5. Підрахунок кількості елементів масиву, що задовольняють заданій умові

2.6. Обчислення добутку елементів масиву

2.7. Пошук елементів, що володіють заданою властивістю

2.8 Пошук у впорядкованому масиві

2.9. Пошук мінімального і максимального елемента масиву та його порядкового номера (індексу)

2.10. Копіювання масивів

2.10 Формування нового масиву

Література

Додаток

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

Задача 1. Обчислення сум, кількостей і добутків елементів масиву

Задача 2. Обчислення сум, кількостей і добутків елементів масиву

1. Масиви в мові С

1.1 Поняття масиву

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

При оголошенні масиву в програмі визначається ім'я масиву , тип його елементів , розмірність і розмір . Розмірність або кількість вимірювань масиву визначається кількістю індексів при зверненні до елементів масиву. Масиви бувають одномірні, двомірні, тривимірні і т.д. . Розмір масиву - Це кількість його елементів за відповідними розмірності. Загальний вигляд оголошення масиву:

<імя_тіпа> <імя_массіва> [K1] [k2] ... [kn];

де k1, k2, ..., kn - кількість елементів масиву - константи або вирази зі по 1, 2, ..., N вимірам. Причому значення індексів можуть змінюватися від 0 до ki - 1 .

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

ВЁ сучасні транслятори мови Сі не контролюють допустимість значень індексів, це повинен робити програміст ;

ВЁ кількість вимірювань масиву не обмежена;

ВЁ в пам'яті елементи масиву розташовуються так, що при переході від елемента до елементу найбільш швидко змінюється самий правий індекс масиву, тобто матриця, наприклад, розташовується в пам'яті по рядках;

ВЁ ім'я масиву є покажчиком - константою на перший елемент масиву;

ВЁ операцій над масивами в Сі немає, тому пересилання елементів одного масиву в інший може бути реалізована тільки поелементно за допомогою циклу;

ВЁ над елементами масиву допускаються ті ж операції що і над простими змінними того ж типу;

ВЁ ввід/вивід значень елементів масиву можна виробляти тільки поелементно;

ВЁ початкові значення елементам масиву можна привласнити при оголошенні масиву.

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

int A [10];// одновимірний масив з 10 цілочисельних величин

float X [20];// одновимірний масив з 20 речовинних величин

int a [5] = {1, 2, 3, 4, 5};// Масив з ініціалізацією його елементів

int c [] = {-1, 2, 0, -4, 5, -3, -5, -6, 1};// масив розмірність якого 6определяется числом ініціюючих елементів

Звернення до елементів одновимірного масиву можуть мати вигляд: A [0], A [1], A [2], ... A [9], A [2 * 3] .

У Сі ++ немає масивів із змінними кордонами. Але, якщо кількість елементів масиву відомо до виконання програми, можна визначити його як константу за допомогою директиви # define , а потім використовувати її в якості межі масиву, наприклад,

# define n 10;

Main ()

{int a [n], b [n];// Оголошення 2-х одновимірних масивів

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

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

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

int n = 20;

int * a = new int [n];

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

Примітка: Обнулення пам'яті при її виділення не відбувається. Ініціалізувати динамічний масив можна.

Звернення до елементу динамічного масиву здійснюється також, як і до елементів звичайного масиву. Наприклад: a [0], a [1], ..., a [9] .

Можна звернутися до елементу масиву іншим способом: * (a +9), * (a + i), тому в змінної - покажчику a зберігається адреса початку масиву. Для отримання адреси, наприклад, 9 - го його елемента до цього адресою додається 9 В· sizeof (int) (9 помножити на В· довжину елемента типу int ), тобто до початкового адресою a додається зсув 9. Потім за допомогою операції * (разадресаціі) виконується вибірка значення з зазначеної області пам'яті.

Після використання масиву виділена динамічна пам'ять звільняється з допомогою опереатора: delete [] Ім'я масиву . Так наприклад, для одновимірного масиву a:

delete [] a; .

Час "життя" динамічного масиву визначається з моменту виділення динамічної пам'яті до моменту її звільнення.