if (q
}
/ * F - номер рядка з найбільшим числом одиниць, q - число одиниць у f-му рядку * /
printf ("% d% d", f, q);
}
Приклад 3. Переставити місцями елементи головної та побічної діагоналей масиву D (6,6). Отриману матрицю вивести на екран дисплея.
# Include
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
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
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
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
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
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. Завдання
Завдання взяти з таблиці відповідно до заданого варіанту. Написати два варіанти програми: без застосування покажчиків і з покажчиками.
Таблиця