МІНІСТЕРСТВО ОСВІТИ I НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
Національний університет "Львівська політехніка"
Кафедра САПР
/
СТРУКТУРИ ТА ОБ’ЄДНАННЯ В МОВІ ПРОГРАМУВАННЯ СІ
Лабораторна робота №5
з курсу: “ Проблемно-орієнтоване програмування ”
Прийняв:
Загарюк Р.В.
ЛЬВІВ - 2012 р.
1. МЕТА РОБОТИ
Мета роботи - навчитися використовувати структури та об’єднання для програмування на мові С.
2. ТЕОРЕТИЧНІ ВІДОМОСТІ
Структури
Структура - це набір з однієї або більше змінних, можливо різних типів, згрупованих під одним ім'ям для зручності обробки. (У деяких мовах, наприклад Паскаль, структури називаються “записами”).
Розглянемо приклад. Уявіть собі, що на календарі сьогодні 1 січня 2009 року. Дата складається з складових таких, як день, рік та назва місяця. Ці три змінні можна об’єднати в одну структуру вигляду:
struct DATE {
int day;
int year;
char mon_name[4];
};
Опис структури, що складається з взятого в фігурні дужки списку полів, починається з ключового слова struct. Після слова struct пишеться ім'я, так звана Мітка структури (тут це DATE). Ім’я може бути відсутнє. Така мітка іменує структури цього виду і може використовуватися надалі як скорочений запис детального опису. Елементи або змінні, згадані в структурі, називаються членами (полями, компонентами). Мітки і члени структур можуть мати такі ж імена, що і звичайні змінні (тобто ті, що не є членами структур), оскільки їх імена завжди можна розрізнити по контексту. Звичайно однакові імена присвоюють тільки тісно пов'язаним об'єктам.
Точно так само, як у разі будь-якого іншого базового типу, за правою фігурною дужкою, що закриває список членів, може записуватись список змінних.
Оператор
struct { } x, y, z; // описує struct { }
синтаксично аналогічний
int x, y, z; // описує int
в тому сенсі, що кожен з операторів описує x, y та z в якості змінних відповідних типів і приводить до виділення для них пам’яті.
Опис структури, за яким не має списку змінних, не приводить до виділення пам'яті (немає змінної); він тільки визначає шаблон або форму структури. Але, якщо в такому опису є мітка, то ця мітка може бути використана пізніше при визначенні фактичних примірників структур. Наприклад, якщо дано приведений вище опис Date, то struct DATE d; визначає змінну d як структура типу Date.
Операція вказівника на член структури "." зв'язує ім'я структури та ім'я члена. Наприклад:
d.day = 1;
d.year = 2000;
d.mon_name = “січ”;
Структури можуть бути вкладеними. Над змінною структури можна виконати операції взяття адреси змінної та присвоєння її вказівнику.
struct DATE d1, *d2; //оголошено змінну типу DATE d1,та вказівник на тип DATE d2
d2 = &d1; // &d1 - взяття адреси змінної d1 та присвоєння його змінній d2
Розглянемо детальніше функцію void print_date(struct DATE * d). Як видно з оголошення функції, як формальний параметр використано вказівник на структуру. В такому випадку для звертання до полів структури використовується оператор “->”. Для наочної різниці між звертанням змінної типу DATE та вказівником на змінну типу DATE наведено таблицю 1.
Таблиця 1.
struct DATE d;
struct DATE d,*d1;
d1 = &d;
d.date = 1;
d.year = 2000;
strcpy(d.mon_name, “січ”);
d1->date = 1;
d1->year = 2000;
strcpy(d1->mon_name, “січ”);
Структури можна об'єднувати в масив. Тоді запис struct DATE d[5]; відображає масив з п’яти елементів типу DATE. Доступ до полів структури відбувається наступним чином:
d[0].year;
d[0].date;
Розмір структури можна взнати використавши стандартну операцію. Справа в тому що в мові "C" передбачена унарна операція sizeof, яка виконується під час компіляції, дозволяючи обчислити розмір будь-якого об’єкта. Вираз
sizeof (object)
видає ціле число, що дорівнює розміру вказаного об’єкта. (Розмір визначається в неспецифіцикованних одиницях "байти", які мають той же розмір, що і змінні типу char). Об’єкт може бути фактичною змінною, масивом і структурою, або іменем основного типу, як int або double, або іменем похідного типу, як структура. В нашому випадку
int size;
struct DATE d;
size = sizeof(d);
Структури широко використовуються при побудові різноманітних дерев та списків.
Доступ до компонентів структури
Доступ до полів структури здійснюється за допомогою оператора "." при безпосередній роботі зі структурою або "->" - при використанні вказівників на структуру. Ці оператори (. і ->) називаються селекторами членів класу. Загальний синтаксис для доступу до компонентів структури наступний:
ім'я_змінної_структури . член_даних ;
ім'я_вказівника -> ім'я_поля;
(*ім'я_вказівника) . ім'я_поля;
Структура не може містити в собі змінні свого типу, тобто наступне оголошення шаблона буде неправильним:
struct man { char *fam;
char *name;
struct man any; };
Однак структура може включати елементи, що є вказівниками на оголошений тип цієї ж структури:
struct man { char *fam;
char *name;
struct man *p_man; };
Можна визначити вказівник на оголошений тип структури й проініціалізувати його. Наприклад:
struct man group[20], studl, *pl, *p2;
pl=&studl;
p2=group; // або p2=Sgroup [0];
Ініціалізація структур
При визначенні структурних змінних можна ініціалізувати їхні поля. Ця можливість подібна ініціалізації масиву й слідує тим же правилам:
ім'я_шаблона ім'я_змінної_структури = {значення1., значення2, . . .};
Компілятор присвоює значення1 першій змінній в структурі, значення2 - другій змінній й т.д., і тут необхідно додержуватися деяких правил:
1. значення, що присвоюються, повинні співпадати по типу з відповідними полями структури;
2. можна оголошувати кількість значень, що присвоюються, меншу, ніж кілкість полів. Компілятор присвоїть нулі іншим полям структури;
3. список ініціалізації послідовно присвоює значення полям структури, вкладених структур і масивів.
Об'єднання
Об’єднання подібне структурі, але в кожен момент часу може використовуватись (або є активним) тільки один з його компонентів. Тип об’єднання може задаватися записом виду
union МІТКА {
опис компонента а1;
опис компонента а2;
…………………….
опис компонента аn;
};
Для кожного з цих компонентів виділяється одна і та ж область пам’яті, тобто вони перекриваються. Хоча доступ до цієї області пам’яті можливий через використання будь-якого з компонентів. Компонент для цієї мети повинен вибиратися так, щоб отриманий результат не був беззмістовним.
Як вже зазначалось, об’єднання подібні структурам. Доступ до компонент об’єднання відбувається тим самим способом, що і для структур.
Об’єднання застосовуються:
для мінімізації об’єму пам’яті, що використовується, якщо в кожний момент часу тільки один об’єкт з багатьох є активним;
для інтерпретації основного представлення об’єкта одного типу, так ніби цьому об’єкту був присвоєний другий тип.
ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
Варіант №16
У вхідному файлі записаний текст:
A swarm of bees in May
Is worth a load hey;
A swarm of bees in June
Is worth a silver spoon;
A swarm of bees in July
Is hot a worth a fly.
Скласти програму, що визначить кількість назв місяців і виведе їх на друк.
Текст програми:
#include<stdio.h>
#include<string.h>
#include<conio.h>
#define N 60
#define Q 200
#define NROWS 60
struct MISYAC{ // Опис структури для назв місяців
char misyac[10];
};
int main ()
{
FILE *m; // Оголошення 2-х вказівниів для роботи з файлами
FILE *v;
struct MISYAC d[13];
int i=0,j,k1=0,k2,l=0,t,num=0;
char mas[Q],temp[N];
m=fopen("D:\\misac.txt","r"); // Присвоєння вказівникам адреси початку файлів
v=fopen("D:\\virsh.txt","r"); // призначенх для читання
// Доки не закінчиться файл з назвами місяців
// записуємо назви місяців з файлу в структуру
while(!feof(m))
{
if(i<12)
{
fscanf(m,"%s ",&(d[i].misyac));
i++;
}
}
// Записуєм віршик в масив mas[i] доки не закінчиться файл
for (i=0;!feof(v);i++)
fscanf(v,"%c",&mas[i]);
printf("%s\n",mas); // Виводимо віршик на екран
l=strlen(mas); //Рахуєм кількість символів у масиві mas
for (i=0;i<l;i++)
// З масиву mas виділяємо по слову і заносимо в temp
if (mas[i]==' ' || mas[i]=='\n' || mas[i]==';' || mas[i]=='.')
{
k2=i; // фіксуєм кінець слова
for(j=k1,t=0;j<k2;j++,t++)
temp[t]=mas[j];
temp[t]='\0'; // Дописуєм ознаку кінц рядка
// Перевіряєм записане в temp слово із місяцями в структурі
for (j=0;j<12;j++)
if (!strcmp(temp,d[j].misyac))
{
num++; // Рахуєм кількість місяців
printf("\n%s",temp); // Виводимо цей місяць на екран
}
k1=k2+1; // Кінець слова стає початком наступного з сувом на 1
}
printf("\n\nKilkist misyaciv = %d",num); // Виводимо кількість місяців на екран
fclose(v); //закриваємо файли
fclose(m);
getch();
return 0;
}
Результати обчислень:
/
Рис.1 – Виконання програми
/
Рис.2 – Файли, необхідні для роботи програми із: а) назвами місяців; б) віршиком.
ВИСНОВОК
На даній лабораторній роботі я повторила набуті знання про використання структури та об’єднання для програмування на мові С.