Лабораторна робота
"Масиви і покажчики в мові програмування Сі + +"
Теоретичні відомості
Мета роботи: ознайомитися з основними принципами роботи з одновимірними і двомірними масивами. Освоїти роботу з вказівниками та операціями над покажчиками.
Масиви
Масив складається з кількох елементів одного і того ж типу. Можна вибирати будь-який елемент масиву. Для цього необхідно задати індекс, який вказує відносну позицію елемента. число елементів масиву задається при його оголошенні і надалі не змінюється. Якщо масив оголошений, до будь-якого його елементу можна звернутися наступним чином: вказати ім'я масиву та індекс його елементу в квадратних дужках.
Масиви оголошуються так само, як і змінні. Наприклад:
int a [100];
float c [10] [20];
У першому рядку оголошуємо масив а з 100 елементів цілого типу: а [0], a [1], ..., a [99] (індексація завжди починається з нуля). У другому рядку оголошений двовимірний масив дійсного типу. Двовимірний масив представляється як одновимірний, елементи якого є теж масивами. У перших квадратних дужках вказується кількість рядків у масиві, по-друге - кількість стовпців.
Приклад 1. Задано одновимірний масив S, що складається з десяти елементів дійсного типу. Вивести на екран дисплея значення елементів цього масиву у зворотному порядку.
# Include <stdio.h>
main ()
{Float s [10];
int i;
for (i = 0; i <10; i + +)
scanf ("% f", & s [i]); / * введення елементів масиву * /
for (i = 9; i> = 0; i -)
printf ("% f", s [i]); / * висновок елементів у зворотному порядку * /
}
Приклад 2. Задано двовимірна матриця а, що має п'ять рядків і п'ять стовпців. Визначити номер рядка з найбільшим числом одиниць у цьому рядку.
# Include <stdio.h>
main ()
{Int i, j, p, q = 0, f = 0, a [5] [5];
for (i = 0; i <5; i + +)
for (j = 0; j <5; j + +)
scanf ("% d", & a [i] [j]); / * введення матриці * /
/ * Пошук в матриці а рядки з найбільшим числом одиниць * /
for (i = 0; i <5; i + +)
{P = 0;
for (j = 0; j <5; j + +)
if (f [i] [j] == 1) p + +;
if (q <p) {q = p; f = i;}
}
/ * F - номер рядка з найбільшим числом одиниць, q - число одиниць у f-му рядку * /
printf ("% d% d", f, q);
}
Приклад 3. Переставити місцями елементи головної та побічної діагоналей масиву D (6,6). Отриману матрицю вивести на екран дисплея.
# Include <stdio.h>
main ()
{Int i, j, a, d [6] [6];
for (i = 0; i <6; i + +)
for (j = 0; j <6; j + +)
scanf ("% d", & d [i] [j]); / * введення матриці * /
/ * Перестановка місцями елементів головної та побічної діагоналей * /
for (i = 0; i <5; i + +)
{A = d [i] [i];
d [i] [i] = d [i] [6-i];
d [i] [6-i] = a;
}
for (i = 0; i <6; i + +)
for (j = 0; j <6; j + +)
printf ("% d% c", d [i] [j], (j == 5)? "\ n": "");
/ * Висновок по рядках елементів матриці * /
}
При виведенні елементів матриці по рядках застосована тернарних операція. Сенс цієї операції зводиться до наступного: якщо j = 5 (закінчений висновок елементів по рядку), то курсор переводиться в початок наступного рядка (працює символьна константа "\ n"), в іншому випадку телефон один пробіл. Так як в операторі виведення використовується символьна константа, то застосована специфікація% c.
У висновку цього розділу відзначимо, що масив можна ініціалізувати, тобто присвоїти його елементам початкові значення. Це робиться при оголошенні типу масиву, наприклад: int a [5] = {0, 0, 0, 0, 0};
Це означає, що всі елементи масиву отримують нульове значення.
Двовимірний масив можна ініціалізувати наступним чином:
int a [3] [3] = {{10,20,30},
{40,50,60},
{70,80,90}};
При ініціалізації число елементів можна не вказувати, тому що в цьому випадку воно може бути обчислено за кількістю привласнюються значень (в фігурних дужках), наприклад:
int a [] = {10,20,30,40,50};
Покажчики
Покажчики та одномірні масиви
Покажчик - це змінна, яка містить адресу змінної. Так як покажчик - це адреса деякого об'єкта, то через нього можна звертатися до даного об'єкта.
В СІ існує тісний зв'язок між покажчиками й масивами. Будь-який доступ до елемента масиву, здійснюваний операцією індексування, може бути виконаний за допомогою покажчика.
Декларація
int a [10];
визначає масив а розміру 10, тобто блок з десяти послідовних об'єктів, представлених на малюнку, з іменами a [0], a [1], ..., a [9].
Запис a [i] відсилає нас до i-му елементу масиву. Якщо ра є вказівник, тобто визначений як int * pa;, то в результаті присвоювання
pa = & a [0];
pa буде вказувати на нульовий елемент масиву а; інакше кажучи, ра буде містити адресу елемента a [0] (див. рис.). Тепер присвоювання
x =* pa;
буде копіювати вміст а [0] в х.
Якщо ра вказує на деякий елемент масиву, то ра +1 за визначенням вказує на наступний елемент (див. рис.). Таким чином, якщо ра вказує на a [0], то * (ра +1) є вміст a [1] , ра +1 - адреса a [1], * (ра + i) - вміст a [i].
Оскільки ім'я масиву є не що інше як адресу його початкового елемента, присвоювання
pa = & a [0];
можна також записати в наступному вигляді:
pa = a;
Так як ра - покажчик, то у виразах його можна використовувати з індексом, тобто запис pa [i] еквівалентна запису * (pa + i). Елемент масиву однаково дозволяється зображати і у вигляді покажчика зі зміщенням, і у вигляді імені масиву з індексом.
Між ім'ям масиву і покажчиком, виступаючим в ролі імені масиву, існує одна відмінність. Покажчик - це змінна, тому можна написати pa = a або pa + +. Але ім'я масиву не є змінною, і запис типу a = pa не допускається. Слід також розрізняти вираження * (a +2) і * a +2: * (а +2) - значення третього елемента масиву а; * а +2 - додавання числа 2 до значення першого елемента масиву.
Приклад 4. Вивести значення одновимірного масиву звичайним способом і з використанням покажчиків.
# Include <stdio.h>
int a [6] = {10,20,30,40,50,60};
/ * Оголошення і ініціалізація масиву * /
main ()
{Int i, * p;
for (i = 0; i <6; i + +)
printf ("% d", a [i]); / * висновок масиву звичайним способом * /
for (p = & a [0]; p <= & a [5]; p + +)
printf ("% d", * p) / * висновок масиву з використанням покажчика * /
for (p = & a [0], i = 0; i <6; i + +)
printf ("% d", p [i]); / * ще один варіант з використанням покажчика * /
}
Дамо ще деякі пояснення. Операція р + + збільшує значення покажчика на одиницю. Якщо p = & a [i], то після операції р + + в р міститься адресу елемента a [i +1].
Приклад 5. Знайти середнє арифметичне масиву, що складається з шести елементів, з використанням покажчика.
# Include <stdio.h>
int a [] = {10,20,30,40,50,60}
main ()
{Int i, * p;
float s;
p = a / * вказівник отримує значення адреси нульового елемента масиву * /
for (s = 0, i = 0; i <6; i + +)
s + =* (p + i) / * отримання суми елементів масиву * /
s = s / 6 / * середнє арифметичне масиву * /
printf ("% f", s);
}
Приклад 6. Вирішити завдання, наведену в прикладі 1, з використанням покажчика.
# Include <stdio.h>
main ()
{Float s [10];
int * p, i;
for (i = 0; i <10; i + +)
scanf ("% f", s [i]);
p = & s [9]; / * покажчик отримує значення адреси останнього елемента масиву * /
for (i = 0; i <10; i + +)
printf ("% f", * (pi)); / * висновок елементів у зворотному порядку * /
for (p = & a [9]; p> = & a [0]; p -) / * ще один спосіб виведення елементів у зворотному порядку * /
printf ("/ n% d", * p);
}
Покажчики та двовимірні масиви
Припустимо, що у нас є опису:
int z [4] [2]; / ** /
int pz; / ** /
Тоді pz = z вказує на нульовий стовпець нульової рядка, тобто
pz = & z [0] [0];
Приклад 7. Вивести на екран значення нульового, другого і четвертого елементів масиву.
# Include <stdio.h>
int a [] = (10,20,30,40,50,60) / * оголошення і ініціалізація масиву а * /
main ()
{
for (p = a, i = 0; p + i <= a +4; p + +, i + +)
printf ("% d"; (p + i)); / * висновок на екран значень нульового, другого і четвертого елементів * /
}
У циклі відбувається одночасне збільшення покажчика р і індексу i на одиницю, внаслідок чого на екран після нульового елемента виводиться другий, і потім четвертий. Оскільки елементи двовимірного масиву зберігаються в пам'яті ЕОМ по рядках, то
pz +1 = & z [0] [1], pz +2 = & z [1] [0], pz +3 = & z [1] [1] і т.д.
Двовимірний масив описаний як масив масивів. Якщо z є ім'ям масиву, то які імена чотирьох рядків, кожна з яких є масивом з двох елементів? Ім'я першого рядка z [0], другий - z [1], і т.д. Проте ім'я масиву є також покажчиком на цей масив в тому сенсі, що воно посилається на перший його елемент. Значить:
z [0] = & z [0] [0], z [1] = & z [1] [0], z [2] = & z [2] [0], z [3] = & z [3] [0 ].
Приклад 8. Задано матриця а. Вивести на екран елементи головної діагоналі, першого рядка і значень перших елементів кожного рядка матриці, застосувавши для цього покажчики.
# Include <stdio.h>
int a [3] [3] = {{10,20,30},
{40,50,60},
{70,80,90}};
/ * Оголошення і ініціалізація двовимірного масиву * /
int * pa [3] = {a [0], a [1], a [2]};
/ * Оголошення і ініціалізація покажчика ра на рядки масиву а і присвоєння початкових значень: pa [0] = a [0]; pa [1] = a [1]; pa [2] = a [2] * /
int p = a [0]; / * оголошення покажчика на нульовий елемент нульової рядка масиву а * /
main ()
{Int i;
for (i = 0; i <9; i + = 4)
printf ("% d", * (p + i)); / * висновок на екран елементів головної діагоналі * /
for (i = 0; i <3; i + +)
printf ("% d", * p [i]); / * висновок на екран елементів першого рядка * /
for (i = 0; i <3; i + +)
printf ("% d", pa [i]); / * висновок на екран перших елементів кожного рядка матриці * /
}
Зробимо деякі пояснення для першого оператора циклу. Уявімо матрицю у вигляді одновимірного масиву, записаного по рядках:
a [0] [0], a [0] [1], a [0] [2], a [1] [0], a [1] [1], a [1] [2], a [ 2] [0], a [2] [1], a [2] [2]
Тоді елементи, що стоять на головній діагоналі, займають нульове, четверте і восьме місця, тобто інтервал між важливими нас елементами дорівнює чотирьом, тому мінлива i змінюється з кроком 4. Відповідно з таким же кроком змінюються адреси комірок, вміст яких виводиться на екран.
2. Завдання
Завдання взяти з таблиці відповідно до заданого варіанту. Написати два варіанти програми: без застосування покажчиків і з покажчиками.
Таблиця
№ варіанту | Завдання |
Визначити, чи є задана квадратна матриця А (5,5) симетричної щодо головної діагоналі. | |
Задано матриця У (4,4). Визначити, відсортовані чи всі елементи першого стовпчика у зростаючому порядку. | |
Задано матриця З (5,5). Поміняти місцями максимальний елемент кожного рядка з першим елементом відповідного рядка. | |
Переписати перші елементи кожного рядка матриці D (3,3), які більше 10, в масив В. | |
Задано матриця Q (5,5). Замінити останній нуль в кожному рядку на 5. | |
Задано матриця D (4,4). Визначити максимальний серед позитивних, мінімальний серед негативних і поміняти їх місцями. | |
Задано матриця А (4,4). Замінити перший нуль в кожному стовпці на кількість нулів у цьому стовпці. | |
Задано матриця F (9,3). визначити, чи рівні всі елементи першого стовпчика відповідних елементів головної діагоналі. Якщо ні, то поміняти їх місцями. | |
Задано матриця C (5,5). Отримати вектор В, кожен елемент якого дорівнює кількості нулів, що стоять у стовпці матриці. | |
Задано матриця У (4,4). Якщо в рядку є хоча б одна одиниця, то замінити цей рядок нулями. | |
Задано матриця Q (3,3). Якщо на головній діагоналі стоїть нуль, то відповідний рядок замінити одиницями. | |
Задано матриця D (4,4). Якщо максимальний елемент матриці стоїть на головній діагоналі, то всі елементи головної діагоналі зробити рівними максимальному. | |
Задано матриця З (5,5). Якщо мінімальний елемент коштує в першому рядку, то всі елементи, які стоять в рядку за ним, замінити нулями. | |
Задано матриця А (4,4). Якщо максимальний елемент матриці дорівнює сумі елементів першого рядка, то поміняти місцями перший рядок з тим рядком, де знаходиться максимальний елемент. | |
Задано матриця А (4,4). Якщо максимальний елемент матриці дорівнює сумі елементів першого рядка, то поміняти місцями перший рядок з тим рядком, де знаходиться максимальний елемент. |
Література
Подбельський В.В. Мова Cu + +: Навчальний посібник. - М.: Фінанси і статистика, 1995, - 560 с.
Страуструп Б. Мова програмування Сг + +. - М.: Радіо і зв'язок, 1991. - 352 стор
Собоцінскій В.В. Практичний курс Turbo Cu + +. Основи об'ктно-орієнтованого програмування. - М.: Світ, 1993. - 236 с.
Романов В.Ю. Програмування на мові Cu + +. Практичний підхід. - М.: компьтер, 1993. - 160 с.
Уінер Р. Мова турбо Cu. - М.: Світ, 1991. - 384 с.
Юлін В.А., Булатова І.Р. Запрошення до Cu. - Мн.: Вищ. Шк., 1990, - 224 с.
Котлинського Г.П., Галиновський О.І. Програмування на мові Cu. -Мн.: Вищ. Шк., 1991. - 156 с.