ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 22.12.2021
Просмотров: 113
Скачиваний: 3
Лекція 8
Структури в Сі.
Структури в Сі відносяться до найбільш важливих і гнучких типів даних. Структура є множиною змінних – однієї або декількох, згрупованих під одним ім’ям. Кожна змінна структури має своє ім’я і визначення. Більше того, кожна із змінних може містити свою форму даних.
Структура є корисною в будь-якому випадку, коли декілька змінних потрібно розглядати як одне ціле. Структури можуть містити в собі інші структури, а також масиви. Можна створити цілий масив структур. Структуру потрібно оголосити, а потім її використовувати.
Загальною формою оператора визначення структури є
Struct ім’я {
Тип змінної ім’я змінної;
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _
тип змінної ім’я змінної;
};
Ім’я – це початкова назва, під якою дана конструкція буде відома С. Для кожної змінної відводиться окремий рядок. Наприклад, структура має три змінні
Struct circle {
int radius;
int xcoord;
int ycoord;
};
Ці три змінні містять радіус круга і координати його центру. В структурі потрібно вказати, яка змінна їй належить. Це робиться за допомогою операції-точки, тобто точки, яка розділяє частини імені структури.
Розглянемо приклад:
Struct circle {
int radius;
int xcoord;
int ycoord;
} Mycircle;
My circle.radius = 15;
Тут створюється екземпляр, який має назву Mycircle, структури з ім’ям circle. Останній оператор присвоює значення 15 змінній circle, яка належить до Mycircle.
Зверніть увагу, що крапка з комою після } перед рядком, який задає ім’я екземпляра не ставиться.
Якщо потрібно, можна створити декілька екземплярів структур одночасно, написавши:
Struct circle Mycircle, Yourcircle , Ourcircle;
Той же принцип працює і при створенні екземплярів відразу після визначення структури.
Struct circle {
int radius;
int xcoord;
int ycoord;
} Mycircle, Yourcircle , Ourcircle;
Для цього можливо переміщувати весь вміст одного екземпляра в інший, наприклад:
Yourcircle = Mycircle;
Альтернативним засобом оголошення і роботи зі структурою є використання ключового слова typedef, яке дозволяє економити час при наборі програми. Ці рядки еквівалентні попередньому:
typedef Struct circle {
int radius;
int xcoord;
int ycoord;
} circle;
Щоб створити екземпляр структури, використовується оператор:
circle Mycircle;
Різниця в тому, що тепер ви не напишете ключеве слово struct. Все останнє таке ж, як і раніше. Це були прості структури, складні структури, це, наприклад, масив структур-можливо, найкорисніша із усіх конструкцій.
Крім того структура може містити масиви і масив може містити структури.
Розглянемо приклади програм, які показують, як використовувати структури.
Приклад 1. Оголошується структура computer і змінна pibm muny computer. Всі описи і визначення подані перед рядком main(). Далі буде показано, що в цьому випадку змінна pibm є глобальною. Рядки pibm.model, pibm.mem, pibm.sp викликають звернення до відповідних елементів структури pibm типу computer, яким раніше були присвоєні значення.
# include<stdio.h>
struct computer { int mem; /* оголошення структури типу computer із 3-ох
int sp; елементів: mem, sp, model*/
char model [20];};
struct computer pibm={512, 10, “ПЭВМ” }; /*ініціалізація змінної pibm типу
computer*/
main()
{printf(“ персональна ЕОМ % s \n \n”, pibm.model);
printf(“ об’єм операційної пам’яті-- %d Кбайт \n”, pibm.mem);
printf(“ потужність-- %d млн. опер. в секунду \n”,pibm.sp);
}
Результати роботи програми мають вигляд:
Персональна ЕОМ
--/--/--/--
--/--/--/--
об’єм оперативної пам’яті-512 Кбайт
потужність-10 млн. операцій в секунду.
Унарна операція & дозволяє отримати адресу структури. Припустимо, що задано оголошення
Struct date { int d, m, y;} day;
Тут day – структура типу date, яка має три елементи: d, m i y. Рядок виду
struct date *db; встановлює той факт, що db – це покажчик на структуру типу date. Тепер для вибору елементів d, m, y структури необхідно використовувати конструкції: (*db).b, (*db).m, (*db).y. Дійсно, db – адреса структури, *db – сама структура. Круглі дужки тут необхідні, тому що крапка (.) має більш вищий, чим зірочка (*), пріоритет. Для аналогічних випадків в мові Сі є ще одна додаткова операція -> (два символа А15 і D16). Вона теж вибирає елемент структури і дозволяє представити розглянуті вище конструкції в більш простому вигляді: db->d, db->m, db->y.
Поля і об’єднання.
Поля і об’єднання є особливим різновидом структур. Поле – це послідовність сусідніх двійкових розрядів (біт) всереді одного цілого значення. Воно може мати тип signed int або unsigned int і займати від 1 до 16 біт. Поля розміщуються в машинному слові в направленні від молодших до старших розрядів. Наприклад структура
struct prim {int a:2; unsigned b:3; int:5;
int c:1; unsigned d:5; } i, j;
забезпечує розміщення, показане на рисунку.
Розряди машинного слова
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|||
d |
C |
Не використовуються |
b |
а |
|
Структура поля.
В полях типу signed крайній лівий біт є знаковим. Наприклад, таке поле шириною 1 біт може зберігати значення -1 і 0, тому що будь-яка ненулева величина буде інтерпретуватись як 1.
Поля використовуються для упакування значень декількох змінних в одне масивне слово з метою економії пам’яті. В оголошенні полів найбільш часто використовується модифікатор unsigned. Вони не можуть бути масивами і не мають адрес, тому для них не можна примінити унарну операцію &.
Використання полів розглянемо на прикладі такої програми:
# include <stdio.h>
struct { unsigned a:1;
unsigned b:1;
unsigned y:1;
unsigned c:2;} /*оголошення змінної f, яка містить три однорозрядних і одне двох розрядне поле (число, за двокрапкою – розмір поля*/
main ( )
{ int i;
printf (“розмір f=%d байта \n”, sizeof (f));
f.a=f.b=1; /* в поля f.a і f.b записуються одиниці*/
for ( i=0; i<2; i++)
{
f.y = f.a && f.b; /*вираховується кон’юнкція f.y змінних f.a і f.b */
printf (“ цикл %d; f.y = %d\n ”, i, f.y );
f.b=0; /* в поле f.b записується нуль */
}
f.c=f.a+ !f.b; /* арифметичне додавання значення f.a (воно дорівнює 1)
і заперечення значення f.b (заперечення нуля теж дорівнює
одиниці); в результаті f.c=2 */
printf ( “f.c = %d”, f. с );
}
Oголошення виду unsigned a:1 визначає однобітове поле а; в нього можна записати тільки одне із двух значень: нуль або одиницю.
Оголошення unsigned с:2; визначає двухбітове поле с; в нього вже можна записати одне із 4-х значень: 0, 1, 2 або 3. Функція sizeof(f) дозволяє визначити розмір в байтах одної структури f. Аналогічно з її допомогою можна знаходити і розміри других об’єктів (змінних, масивів і т.д.)
Звернення до любого поля здійснюється так, як до елемента структури. Наприклад: f.а – звернення до однобітового поля а.
Результати роботи програми мають вигляд:
Розмір f=2 байта
Цикл 0; f.y=1
Цикл 1; f.y=0
f.с=2
Об’єднання – це деяка змінна, яка може зберігати (в різний час) об’єкти різних типів і розміру. В результаті з’являється можливість роботи в одній і тій же області пам’яті з даними різного виду. Для опису об‘єднання використовується ключове слово Union(об’єднання), а відповідний синтаксис співпадає з синтаксисом структур.
Програма демонструє і пояснює використання об’єднаннь
#include<stdio.h>
union r {int ir; float fr; char;} z; /* оголошення об’єднання z типу r; змінна z
достатньо велика, щоб зберігати найбільш великий з трьох
приведених типів (тут union – ключове слово об’єднання) */
main() {
printf (“ розмір z=%d байта \n ”, sizeof(z));
printf (“ введіть значення z.ir \n ”); scanf (“ %d ”, &z.ir );
printf (“ значення ir=%d\ n ”, z.ir);
printf (“ введіть значення z.fr \n ”); scanf (“ %f ”, &z.fr );
printf (“ значення fr=%f\n ”, z.fr );
printf (“ введіть значення z.cr \n ”); scanf ( “ %ls ”, &z.cr);
printf(“значення cr=%c\n”, z.cr);
}
В функції scanf(“%ls”, &z.cr); задана специфікація перетворення %ls. Якщо використати звичну для одного символа специфікацію %с, то в програму завжди буде заноситись керуючий символ, який відповідає клавіші „Введення”. Ця клавіша натискувалась раніше для введення значення змінної z.fr
Результати роботи програми
Розмір z=4 байта
Введіть значення z.ir
7
значення ir=7
введіть значення z.fr
8.3456678
значення fr=8.3456678
введіть значення z.cr
p
значення cr=p
В мові Сі можна вводити імена для нових типів даних за допомогою ключового слова typedef (визначити тип). Наприклад, опис typedef int іnteger; робить слово integer синонімом int. Тепер його можна використовувати в оголошеннях типа, так же як int.
/* Приклад визначення типу */
#include<stdio.h>
typedef float REAL; /* ім’я REAL робиться синонімом float (тепер в
описах відповідного типу можна
використовувати і float, і REAL) */
main()
{
REAL a;
printf(“ввести значення a\n”);
scanf(“%f”, &a);
printf(“a=%f”, a);
}
Результати роботи програми:
Ввести значення а
9.4567
а=9.456700
7. Дайте визначення структури. Що називається ярликом структури?
8. Яке призначення операції-крапки?
9. В чому різниця використання Typedef i Struct при визначенні структури?
10. Як звернутися до елемента масиву, який входить в структуру? До структури, яка є елементом масиву?
11. Що потрібно для включення структури в структуру більшого розміру?
12. В чому різниця між максимальною довжиною і поточною довжиною рядка? Як С визначає поточну довжину? Яка функція визначає поточну довжину?
13. Де знаходяться прототипи функцій обробки рядків?
14. Яка функція використовується для копіювання перших n символів із одного рядка в інший?
15. В чому різниця між функціями strchr() i strrchr()?
16. Що таке поле? Для чого воно використовується?
17. Що таке об‘єднання? Які функції вона виконує в мові Сі? Поясніть на прикладі.
18. За допомогою якого ключового слова можна визначити синонім типу?