Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tema_1._Strukturi_ta_ob_jednannja.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
202 Кб
Скачать
☆

Структури та функції

Над структурами можливі наступні операції:

·         Присвоєння,

·         Взяття адреси за допомогою &,

·         Здійснення доступу до її елементів.

Присвоєння використовується при передачі структури в функцію за значенням і повернення структури за значенням. Структури не можна порівнювати. Ініціалізувати структуру можна списком константних значень її елементів; автоматичну структуру також можна ініціалізувати присвоюванням.

Щоб краще познайомитися зі структурами, напишемо декілька функцій, які маніпулюють time і chronos. Виникає питання: а як передавати функцій названі об'єкти? Існує, принаймні, три підходи: передавати компоненти окремо, передавати всю структуру цілком і передавати покажчик на структуру. Кожен підхід має свої плюси і мінуси. Перша функція, maketime, отримує два цілих значення та повертає структуру time.

/ * Maketime: формує час по компонентах hour і minutes * / time maketime (int hour, int minutes) { time temp; temp.hour = hour; temp.minutes = minutes; return temp; }

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

chronos timer;

timer.begin = maketime (0, 0); timer.end = maketime (12, 5);

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

/ * Addtime: додавання часу * / time addtime (time tm1, time tm2) { tm1.minutes + = tm2.minutes; tm1.hour + = tm2.hour + tm1.minutes/60; tm1.minutes% = 60; return tm1; }

Тут обидва аргументи і повертається значення - структури. В якості іншого прикладу наведемо функцію tinchronos, яка перевіряє: чи знаходиться даний момент часу всередині нашого інтервалу.

/ * Tinchronos: повертає 1, якщо t в c, і 0 у противному випадку * / int tinchronos (struct time t, struct chronos c) { return t.hour> = c.begin.hour & & T.hour <c.end.hour & & T.minutes> = c.begin.minutes & & T.minutes <c.end.minutes; }

 

Покажчики на структури

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

імя_структурного_тіпа * імя_указателя_на_структуру;

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

time * pt;

повідомляє, що pt - це покажчик на структуру типу struct time. Якщо pt вказує на структуру time, то * pt - це сама структура, а (* pt). Hour і (* pt). Minutes - її елементи. Використовуючи покажчик pt, ми могли б написати

time origin, * pt; pt = &origin; printf ("origin: (% d,% d) \ n", (* pt). hour, (* pt). minutes);

Дужки в (* pt). Hour необхідні, оскільки пріоритет операції «." Вище, ніж пріоритет операції разименованія «*». Вираз * pt.hour буде проінтерпретувати як * (pt.hour), що невірно, оскільки pt.hour не є покажчиком. Покажчики на структури використовуються дуже часто, тому для доступу до її елементів була придумана операція «звернення до елементу структури за вказівником», скорочено «стрілка» з формою запису «->». Якщо t - покажчик на структуру, то t-> елемент-структури є її окремий елемент. Тому printf можна переписати у вигляді printf ("origin: (% d,% d) \ n", pt-> hour, pt-> minutes); Операції. і -> левоассоціатівни, тобто виконуються зліва направо. Таким чином, при наявності оголошення

chronos ch, * cht = &ch;

наступні чотири вираження будуть еквівалентні:

ch.begin.hour cht-> begin.hour (Ch.begin). Hour (Cht -> begin). Hour

Операції доступу до елементів структури. і -> разом з операторами виклику функції () та індексації масиву [] займають найвище положення в ієрархії пріоритетів та виконуються раніше будь-яких інших операторів. Наприклад, якщо задано оголошення

struct { int len; char * str; } * P; то + + P-> len

збільшить на 1 значення елемента структури len, а не покажчик p, оскільки в цьому виразі як би неявно присутні дужки: + + (p-> len). Щоб змінити порядок виконання операцій, потрібні явні дужки. Так, у (+ + р) -> len, перш ніж узяти значення len, програма збільшить покажчик p. В (р ++)-> len покажчик p збільшиться після того, як буде взято значення len (в останньому випадку дужки не обов'язкові).

За тими ж правилами * p-> str позначає вміст об'єкта, на який вказує str; * p-> str + + збільшить покажчик str після отримання значення об'єкта, на який він вказував (як і в вираженні * s + +), (* p-> str ) + + збільшить значення об'єкта, на який вказує str; * p + + -> str збільшить p після отримання того, на що вказує str.

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

struct List { int dat; List * next; };

Якщо структури містяться один в одному, то використовують предоб'явленіе структури.

Наприклад

struct B; struct A {B b;}; struct B {A a;};

Розглянемо приклад програми створює такий список і виводить його вміст на консоль.

# Include <stdio.h> struct List { int dat; List * next; }; void main () { int i; List * p, * heap = new List; for (p = heap, i = 0; i <10; i + +) { p-> dat = i; p = p-> next = new List; } for (p = heap, i = 0; i <10; i + +) { printf ("% d", p-> dat); p = p-> next; } }

Тут ми описали два покажчики: heap - для вказівки початку списку, p - для пересування за списком; і просту змінну, як лічильник циклу. На відміну від масиву, наш список буде "розкиданий" по пам'яті, оскільки оператор new виділяє перші вільні блоки пам'яті, але це неважливо, оскільки ми пересуваємося за списком, використовуючи збережені в самому списку адреси:

p = p-> next;.

 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]