Масиви структур
Розширимо програму “книжка”, щоб вона могла обробляти 10 книг.
#include <iostream.h>
#define maxnazva 41 /*максимальна довжина заголовка*/
#define maxavtor 31 /*максимальна довжина імені автора*/
#define maxbk 10 /*максималька кількість книг*/
struct book {
char nazva[maxnazva];
char avtor[maxavtor];
float cina;
};
main()
{
struct book libry[maxbk];
int c=0;
int i;
сout<<“введіть назву книги\n”;
cin.get(odna.nazva,maxnazva); cin.get();
while (c< maxbk && gets(libry[c].nazva)!=null
&& libry[c].nazva[0]!=’\0’)
{
cout<<“введіть автора\n”;
cin.get(odna.avtor,maxavtor); cin.get();
cout<<“введіть ціну\n”;
cin>>odna.cina;
while (getch()!=‘\n’)
continue;/*знищення стрічки вводу*/
if (c< maxbk)
cout<<“введіть наступну книгу\n”;
}
cout<<“тепер виведемо список книг.\n”;
for (I=0;I<c;I++)
cout<<libry[i].avtor<< libry[i].nazva<< libry[i].cina;
return 0;
}
Спочатку розглянемо опис масиву структур і доступ до окремих елементів.
Опис масиву структур подібний до опису будь-якого іншого масиву.
struct book libry[maxbk];
Тут описується масив libry з елементами maxbk. Кожний елемент цього масиву є структурою book. Таким чином, libry[0] -одна структура типу book, libry[1]- друга структура і т.д. Це показано на рисунку
nazva avtor cina
Libry[0] | libry[0].nazva | libry[0].avtor | libry[0].cina | |
Libry[1] | libry[1].nazva | libry[1].avtor | libry[1].cina | |
Libry[2] | libry[2].nazva | libry[2].avtor | libry[2].cina | |
. | . | . | ||
. | . | . | ||
. | . | . | ||
Libry[9] | libry[9].nazva | libry[9].avtor | libry[9].cina |
Рис.Масиви структур.
Для ідентифікації елементів масиву структур застосовується теж правило, що і для ідентифікації окремих структур: після імені структури йде крапка, а потім ім’я єлемента.
libry[0].nazva /*елемент структури cina зв’язаний з першим елементом масиву*/
libry[9].cina /*елемент структури cina зв’язаний з десятим елементом масиву*/
Треба звернути увагу на те, що індекс масиву приєднаний до імені libry, а не до закінчення повного імені.
libry[0].nazva /*правильно*/
libry.cina[9] /*неправильно*/
Пояснемо, що означає запис libry[2].cina[4]. Це п’ятий символ елемента cina (частина cina[4])елемента типу book ,описаного третьою структурою (libry[2]).
В програмі рядок while (c< maxbk && gets(libry[c].nazva)!=null
&& libry[c].nazva[0]!=’\0’) трактується так:
gets(libry[c].nazva)-задає зчитування стрічки назви книги. Коли ця функція захоче читати після символа кінця файла, вираз приймає значення null.Вираз libry[c].nazva[0]!=’\0’ перевіряє чи не перший символ стрічки нульовим. Це би означало, що стрічка пуста. Рядок while (getch()!=‘\n’) continue;/*знищення стрічки вводу*/ компенсує недоліки функції scanf() і переводить введений результат на нову стрічку.
2. Вкладені структури.
Інколи необхідно створити структури, яка містить іншу (вкладену) структуру. Складемо програму-“облік друзів”.
#include <iostream.h>
#define l 20
struct names{ /*перший шаблон*/
char im[l];
char prizv[l];
};
struct harakter { /*другий шаблон*/
struct names druzi; /*вкладена структура*/
char bludo[l];
char robota[l];
float zarob;
};
main()
{
struct harakter x1{ /*ініціалізація змінної*/
{“Іван” ,“Петренко”}, “вареники”, “інженер”,30250.00
};
сout<<x1.druzi.im;
сout<< x1.druzi.prizv;
сout<< x1.robota;
сout<< x1.bludo;
сout<< x1.zarob;
return 0;
}
Доступ до елементів вкладених структур здійснюється так: спочатку записується назва зовнішньої структури, потім внутрішньої, а тоді вказуємо поле.
3. Вказівники на структури.
Існує, принаймні, три причини використання вказівників на структури:
- вказівниками легче керувати;
- структура не може передаватись функції в якості аргумента, але це можливо для вказівника;
- в деяких оголошеннях даних використовуються структури, які містять вказівники на інші структури.
Оголошення вказівника на структуру:
struct book *dn;
Спочатку йде службове слово struct ,потім назва структури book , зірочка і ім’я вказівника. Це оголошення не створює нову структуру, але дозволяє використовувати вказівник dn для позначення будь-якої існуючої структури типу book.
Вказівник ініціалізується таким чином, що вказує на структуру.
dn=&x1;
Розглянемо приклад:
#include <iostream.h>
#define l 20
struct names{ /*перший шаблон*/
char im[l];
char prizv[l];
};
struct harakter { /*другий шаблон*/
struct names druzi; /*вкладена структура*/
char bludo[l];
char robota[l];
float zarob;
};
main()
{
struct harakter x1[2]{{ /*ініціалізація змінної*/
{“Іван” ,“Петренко”}, “вареники”, “інженер”,30250.00},
{“Петро”,”Іващенко”},”борщ”,”лікар”,40325.00}};
struct harakter *x2;
x2=&x1[0]; /*вказує на структуру*/
cout<<“заробіток:\n”<<x2->zarob);
x2++; /*вказує на наступну структуру*/
cout<<“заробіток:\n”<<(*x2).zarob);
cout<<“улюблена страва n”<<x2->druzi.prizv<<x2->bludo);
return 0;}
Вказівник х2 вказує на елемент х1[0].Можна використати цей вказівник для отримання значення елемента х1[0].
1.за допомогою нової операції ->.Ця операція ск ладається з дефіса(-) і символа “більше”(>). Іншими словами, вказівник структури з операцією -> має такий самий зміст, які ім’я структури, після якого застосовується операція “крапка”.
2.якщо х2= =&x1[0],то і *x2= =x1[0], оскільки & і * є еквівалентними операціями. Тому можлива заміна
х1[0].zarob= =(*x2).zarob
Дужки необхідні, оскільки приоритет операції “крапка” вище, ніж приоритет операції “зірочка”.
Приклад. Створити та вивести на екран базу даних з 5 студентів. Полями кожного студента є: прізвище; ім’я; день, місяць та рік народження, адреса (дані вводяться з клавіатури)
#include<iostream.h>
#include<conio.h>
struct person
{
char fam[15],name[15];
int day,month,year;
char address[50];
};
//-----------------------------------------
void input(person *stud, int n)
{
for (int i=0;i<n;i++)
{
cout<<"\tЗапис "<<i+1<<":\n";
cout<<"Прiзвище - ";cin>>stud[i].fam;
cout<<"Iм'я - "; cin>>stud[i].name;
cout<<"День народж. - "; cin>>stud[i].day;
cout<<"Мiсяць - "; cin>>stud[i].month;
cout<<"Рiк - "; cin>>stud[i].year;
cout<<"Адреса - "; cin>>stud[i].address;
}
}
//-----------------------------------------
void output(person *stud, int n)
{
for (int i=0;i<n;i++)
{
cout<<"\tЗапис "<<i+1<<":\n";
cout<<stud[i].fam<<" "
<<stud[i].name<<"\t"
<<stud[i].day<<"."
<<stud[i].month<<"."
<<stud[i].year<<"\t"
<<stud[i].address<<endl;
}
}
//-----------------------------------------
void main()
{
clrscr();
person *student = new person[5];
input(student,5);
output(student,5);
delete [ ]student;
getch();
}
Тема. Об’єднання. Робота з елементами об’єднань.
План.
1. Об’єднання.
2. Робота з елементами об’єднань.
Опис об'єднань у мові C++ нагадує опис структур, але їхнє призначення інше. Об'єднання слугують для зберігання (послідовного, не одночасного) в деякій ділянці оперативної пам'яті комп'ютера даних різних типів. Потреба в цьому виникає, наприклад, під час створення таблиці з даними різних типів. Об'єднання можна описати так:
union <назва типу об'єднання>
{
<тип поля 1> <назва поля 1>;
<тип поля п> <назва поля п>;
}
Усі правила, які розглядалися для опису та використання структур, діють і для об'єднань.
Іншими словами, об'єднання - це змінна, яка може містити (в різні моменти часу) об'єкти різних типів і розмірів. Всі вимоги щодо розмірів і вирівнювання виконує компілятор. Об'єднання дозволяють берегти різнорідні дані в одній і тій же області пам'яті без включення в програму машинно-залежної інформації. Ці засоби аналогічні варіантним записам в Паскалі. Прикладом використовування об'єднань міг би послужити сам компілятор, завідуючий таблицею символів, якщо припустити, що константа може мати тип int, float або бути покажчиком на символ і мати тип char *. Значення кожної конкретної константи повинне зберігатися в змінній відповідного цій константі типу. Працювати з таблицею символів завжди зручніше, якщо значення займають однакову за об'ємом пам'ять і запам'ятовуються в одному і тому ж місці незалежно від свого типу. Мета введення в програму об'єднання - мати змінну, яка б на законних підставах берегла в собі значення декількох типів. Наведемо приклад об'єднання.
union u_tag {
int ival;
float fval;
char *sval;
} u;
Змінна u буде достатньо великої, щоб в ній помістилася будь-яка змінна з вказаних трьох типів: точний її розмір залежить від реалізації. Значення одного з цих трьох типів може бути присвоєно змінній u і далі використано у виразах, якщо це правомірно, тобто якщо тип узятого нею значення співпадає з типом останнього присвоєного їй значення. В тому випадку, якщо щось запам'ятало як значення одного типу, а витягується як значення іншого типу, результат залежить від реалізації.
Об'єднання можуть входити в структури і масиви, і навпаки. Запис доступу до елемента об'єднання, що знаходиться в структурі
(як і структури, що знаходиться в об'єднанні), така ж, як і для вкладених структур. Наприклад, в масиві структур
struct {
char *name;
int flags;
int utype;
union {
int ival;
float fval;
char *sval;
} u;
} symtab[NSYM];
до ival звертаються таким чином: symtab[i].u.ival
а до першого символу рядка sval можна звернутися будь-яким з наступних двох способів:
*symtab[i].u.sval
або symtab[i].u.sval[0]
Фактично об'єднання - це структура, всі елементи якої мають нульовий зсув щодо її базової адреси і розмір якої дозволяє поміститися в ній найбільшому її елементу а вирівнювання цієї структури задовольняє всім типам об'єднання. Операції, застосовні до структур, годяться і для об'єднань, тобто законні присвоєння об'єднання і копіювання його як єдиного цілого узяття адреси від об'єднання і доступ до окремих його елементів.
2. Робота з елементами об’єднань.
Розглянемо приклад.Для участі у конференції потрібно заповнити заявку: прізвище, ім'я, адресу, а також зазначати, чи треба бронювати номер у готелі. Якщо житло непотрібне, то записати свій контактний телефон, інакше -зазначити назву готелю. Створити програму, яка б давала змогу ввести отримані дані у базу даних конференції.
// Конференція
#include <iostream.h>
#include <conio.h>
union gotel_tel
{
char gotel[20];
char tel[7];
};
struct konfer
{
char name[15], surname[15], adres[15];
int br; // 1 - треба бронювати номер, 2 - ні
gotel_tel bron;
};
void main()
{
intn = 1;
konfer z;
while (n== 1)
{
cout<<"\n Введіть прізвище, ім'я та адресу\n";
сіn>>z.name >>>z.surname >> z.adres;
cout<<"\n Треба житло? 1 - так, 0 - ні";
сіn>>z.br;
if (z.br)
{
cout << "\n Уведіть назву готелю\п";
сіп>> z.bron.gotel;
}
else
{
cout<<"\n Уведіть номер телефону\n";
сіn>> z.bron.tel;
}
cout<<"\n Наступна заявка? 1 - так, 0 - ні";
сіn >>n;
}
}
Тема. Списки , стеки та черги в мові С++.
План.
1. Поняття про список.
2. Стек.
3. Черги.
Дата добавления: 2015-08-26; просмотров: 951;