ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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. За допомогою якого ключового слова можна визначити синонім типу?


6