Приклад програми по обробці матриць
Опис матриці та введення даних до неї розглянемо на елементарному прикладі роботи з матриціями:
Завдання: В квадратній матриці з правого боку від побічної діагоналі знайти найбільший елемент і відповідний номер рядка.
# include <iostream.h>
const int M=5, N=5;
void main ()
{ int a[M][N];
int i, j, maxzn, nom;
cout <<”Введіть матрицю \n”;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
cin >>a[i][j]; //Вводимо значення елементів масиву
maxzn=a[0][0];
nom=1;
for (i=0; i<M; i++)
for (j=N-i+1; j<N; j++)
if (maxzn<a[i,j])
{ maxzn=a[i,j];
nom=i; }
cout << “Початкова матриця \n”;
for (i=0; i<M; i++)
{ for (j=0; j<N; j++)
cout <<a[i,j];
cout << “\n”;}
cout << “max елемент=”<<maxzn<<“номер рядка=”<<nom;
}
Важливе місце в цій програмі займає організація внутрішнього циклу. При i=l змінна j приймає значення j=5, при i=2 індекс j буде змінюватись від 4 до 5, і так далі. При i=5 параметр j змінюється від 1 до 5. Такі значення індексів забезпечують перегляд всіх елементів, які розміщені на побічній діагоналі та з правого боку від неї.
В мові С є змінні типа покажчик. Значенням змінної типу покажчик буде адреса в пам’яті деякої змінної.
Враховуючи, що для деяких операцій, пов’язаних з покажчиками, потрібно знати об’єм відведеної пам’яті, опис покажчиків має вигляд:
тип * ім’я-покажчика;
Наприклад:
int*pi; /* покажчик на змінну цілого типу */
char *pc; /* покажчик на змінну символьного типу */
З покажчиком використовують два оператори: „*” та „&”. Оператор „&” – унарний. Він повертає адресу пам’яті, де розташований його операнд.
Унарний оператор * дозволяє звернутись до значення змінної, що розташована за адресою, що задана його операндом.
Операції, що виконуються за допомогою покажчиків, часто називають операціями непрямого доступу, т.ч. ми непрямо отримуємо доступ до змінної через деяку іншу змінну.
Працюючи з покажчиком, постійно використовують операцію & – отримання адреси об’єкту. Для неї існують природні обмеження:
– неможливо визначити адресу непоіменованої константи, тобто не приймаються вирази &3.141593;
– неможливо визначити адресу значення, яке отримане при розрахунку скалярних виразів;
– неможливо визначити адресу змінної, що відноситься до класу пам’яті register;
В якості типу при визначенні покажчика може бути використаний як основний тип, так і похідний. До похідних типів можуть бути віднесені масиви, функції, покажчики, посилання, класи, структури, об’єднання та ін.
Основні типи як завжди визначаються ключовими словами int, float, char, unsigned.
Операції над покажчиками можна сгрупувати наступним чином:
– операції розіменування чи доступу за адресою (*);
– перетворення типів (приведення типів);
– присвоєння;
– отримання (взяття) адреси (&);
– адитивні операції (додавання та віднімання константи);
– інкремент (++) та дикремент (--);
– операції відношення (операції порівняння);
Якщо операція & завжди дає однаковий результат – адрес розміщення в пам’яті, то операція розіменування *покажчик залежить не тільки від адреси, але й від типу. Річ в тому, що при доступі до пам’яті за допомогою розіменування покажчика потрібною буде інформація не тільки про розміщення, але й про розміри ділянки пам’яті, що буде використовуватися. Цю додаткову інформацію компілятор отримує з типу покажчика.
Коли покажчик інкрементується він буде вказувати на область пам’яті, що містить наступний елемент базового типу цього покажчика а при кожному дикрементуванні він буде вказувати на попередню область пам’яті базового типу цього покажчика.
Наприклад. Після виконання p1=p1+9 p1 буде посилатися на дев’ятий елемент базового типу покажчика р1 відносно поточного елемента, на який посилається p1.
Додавати покажчики не можна. Але якщо відняти один покажчик з другого (які вказують на один базовий тип) то різниця вкаже на кількість елементів базового типу, що розподіляють ці два покажчика.