Ініціалізація структур
При визначенні структурних змінних можна ініціалізувати їхні поля. Ця можливість подібна ініціалізації масиву й слідує тим же правилам:
ім'я_шаблона ім'я_змінної_структури = {значення1., значення2, . . .};
Компілятор присвоює значення1 першій змінній в структурі, значення2 - другій змінній й т.д., і тут необхідно додержуватися деяких правил:
1. значення, що присвоюються, повинні співпадати по типу з відповідними полями структури;
2. можна оголошувати кількість значень, що присвоюються, меншу, ніж кілкість полів. Компілятор присвоїть нулі іншим полям структури;
3. список ініціалізації послідовно присвоює значення полям структури, вкладених структур і масивів.
Наприклад:
struct date
{ іnt day, month, year;
} d[5] = { {1, 3, 1980),
{5, 1, 1990},
{1, 1, 1983}
};
/* Проініціалізовані перші три елементи масиву */
struct person bguіr[20]={
{"Бурба","Дмитро", "Леонідович", 75., 185, 15, 1, 1980},
{"Таболич", "Юрій", "Олександрович", 70., 180, 25, 8, 1983}};
/* Проініціалізовані 2 елементи масиву структур */
Об'єднання
Об’єднання подібне структурі, але в кожен момент часу може використовуватись (або є активним) тільки один з його компонентів. Тип об’єднання може задаватися записом виду
union МІТКА {
опис компонента а1;
опис компонента а2;
…………………….
опис компонента аn;
};
Для кожного з цих компонентів виділяється одна і та ж область пам’яті, тобто вони перекриваються. Хоча доступ до цієї області пам’яті можливий через використання будь-якого з компонентів. Компонент для цієї мети повинен вибиратися так, щоб отриманий результат не був беззмістовним.
Як вже зазначалось, об’єднання подібні структурам. Доступ до компонент об’єднання відбувається тим самим способом, що і для структур.
Об’єднання застосовуються:
для мінімізації об’єму пам’яті, що використовується, якщо в кожний момент часу тільки один об’єкт з багатьох є активним;
для інтерпретації основного представлення об’єкта одного типу, так ніби цьому об’єкту був присвоєний другий тип.
Роль об’єднання аналогічна ролі опису еквівалентності (equivalence) в Фортрані. Компоненти в об’єднанні взаємозв’язані точно так, як два об’єкта, зв’язані відношенням еквівалентності в Фортрані.
В якості прикладу визначення об’єкта типу union розглянемо об’єднання shape, яке визначається наступним чином:
struct position {
int x; // 2 байти
int y; // 2 байти
};
union {
float radius; // коло 4 байти
float a[2]; // прямокутник 4*2=8 байт
int b[3]; // трикутник 2*3=6 байт
struct position p; // координата точки 2+2=4 байти
} shape;
Розмір об’єднання shape дорівнює не суммі всіх байтів, як у випадку структури, а розміру найбільшого поля (компоненти), тобто 8 байт.
В цьому прикладі є сенс використовувати тільки той компонент, який отримав останнім своє значення.
Приклади програм з використанням структур
/* Приклад: створити масив даних про студентів групи. Записати ім’я, прізвище, рік народження кожного студента, оцінки по п’яти екзаменах. Визначити средній бал за сесію і відсортувати список по сумі балів. */
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
struct student // Шаблон структури
{ char name[20]; // Ім’я
char fam[30]; // Прізвище
int year; // Вік
int mark[5]; // Оцінки
int average; // Сума балів
};
student students[30]; // Массив даних по групі
student buffer; // Додаткова структура
int records; // Кількість студентів в групі
int i, j ; // Допоміжні змінні
void main ( )
{ records = 0 ; // Спочатку записів немає
do // Заповняєм масив структур
{ cout << "Студент № " << records+1 << endl;
cout << "Введіть прізвище "; fflush(stdin) ;
cin >> students [records].fam;
cout << "Введіть ім’я ";
cin >> students [records].name;
cout << "Введіть вік ";
cin >> students [records].year;
for(i = 0; i < 5; i++)
{ cout << " Введіть оцінку по екзамену № " << i+1 << endl;
cin >> students[records].mark[i];
}
records++;
cout << "Прининити работу? [1/0] ";
cin >> i;
} while( i ) ;
for(i = 0; i < records; i++) // Підрахуєм суму балів
{ students [ i ].average = 0;
for (j=0; j < 5; j++)
students[i].average += students[i].mark[j ];
}
for (i = 0; i < records-1; i++) // Відсортуєм
for (j = i; j < records; j++) // по сумі балів
if (students[i].average > students[j].average)
{ buffer = mass[i]; // Перестановка елементів
mass[i] = mass[j]; // структури, особливість
mass[j] = buffer; // мови C/C++
}
for (i = 0; i < records; i++) // Виводимо результат
{ cout << "\n студент " << students[i].name << “\t" << students [i].fam ;
cout << " Вік " << students [i].year;
cout << " Сер. бал " << students[i].average;
}
}
// Приклад: ініціалізація масиву структур, ввід елементів структури.
#include <iostream.h>
void main ()
{ struct complex {double r, i; }cmplx[2] [3]=
{1,2,3,4,5,6,7,8,9,10,11,12);
int i, j;
for(i = 0; i<2; i++)
{ for (j=0; j < 3; j++)
cout << cmplx[i] [j].r << " " << сmр1х[I][j].i. << “ ";
cout << endl;
}
struct comp{double r,i;}cmp[2][3]=
// {{1,2}, {3,4}, {5,б) {7,8}, {9,10}, {11,2}}; !!! -- error
// { {{1,2},{3,4}, {5,б} {7,8}, {9,10}, {11,2}} }; !!! -- error
{ {{11,21), {31, 41}, {51,61}}, {{71,81}, {.91,101}, {111,121}} };
for (i =0; i<2; i++)
{ for (j =0; j<2; j++)
cout << cmp[i][j].r << " " << cmp[i][j].i << " ";
cout << endl;
}
}
/* Приклад: ввести масив структур зі списком студентів і оцінками. Розсортувати масив структур в алфавітному порядку прізвищ, переміщаючи вказівники на структури. */
#include <conio.h>
#include <iostream.h>
#include <string.h>
typedef struct_student
{ char fio[80]; int mark[5]; } student;
void main ()
{ int i, j, k, size;
student. st[100], * stp[100], *tmp;
do { cout << endl << "Введіть кількість студентів: ";
cin >> size;
} while (size > 100);
for (i=0; i<size; i++)
{ fflush (stdin);
cout << " \n Введіть ПІП студента: "; //- вводимо дані
cin >> st[i].fio;
cout << "\n Введіть його оцінки: ";
for (j = 0; j<5; j++) cin >> st[i].mark[j];
stp[i] = &st[i]; // Зберігаєм вказівник на структуру
}
for (i=0; i<size-l; i++)
for (j=i+1; j<size; j++)
if( strcmp(stp[i]->fio.stp[j]->fio)>0)
{ tmp=stp[i]; stp[i]=stp[j]; stp[j]=tmp; }
cout << '' \n Результат виконання:'';
for (i=0; i<size; i++)
{ cout << endl << endl << stp[i]->fio << “ Його оцінки: ";
for (j=0; j<5; j++) cout << stp[i] -> mark[j] << “ “;
}
}
/*Приклад: ввести масив структур. Розсортувати його в алфавітному порядку прізвищ, які входять в структуру, перемiщаючи самі структури.*/
#include <stdio.h>
#include <iostream.h>
int strcmp(char *sl, char *s2);
struct st{ char name[80]; int age; };
void main ()
{ struct st m[100], t;
int i, j, k;
cout<< endl << "k-?";
cin >> k;
for(i = 0; i < k; i++) {fflush(stdin); cin >> m[i].name >> m[i].age; }
// Сортуємо "бульбашкою"
for (i = 0; i < k-l; i++)
for(j = i+l; j < k; j++)
if (strcmp(m[i]).name, m[j].name) > 0)
{ t=m[i]; m[i] = m[j]; m[j] = t; }
// Виводимо результат *
cout << " Sorted:" << endl;
for (i = 0; i < k; i++)
{ cout << m[i].name << "years " <<.m[i].age << endl; }
int strcmp(char *s1, char *s2)
{ for( ; *s1 == *s2; sl++, s2++)
if ( !*s1 ) return 0;
return *s1 - *s2;
}
/* Приклад: при використанні вказівників для вводу даних з плаваючою крапкою в змінній типу структура можуть бути помилки на етапі виконання. Для їх усунення до використання вказівника необхідно при виконанні програми ввести значення фіктивної змінної з плаваючою крапкою:
якщо забрати scanf("%f",&x); то;
// Abnormal program termination
// floating point formats not linked */
#include<stdio.h>
struct mas { int a[5];
float b[5];
} *pl, *p2, *p;
struct res { int maxi, mini;
float maxf, minf;
} *p3;
void main ( )
{ int i, j = 2; float x;
struct mas s, e;
struct res d;
p3 = &d; p1 = &s; p2 = &e; p = p2;
puts (“\n a-?”); scanf(“%f”, &x); //-----!!!!!!!!!
while ( j )
{ j --;
puts ("\n a-?") ;
for (i=0; i<5; i++)
{ scanf ("%d",&(p->a[i]) );
printf(" %d ", p -> a[i]) ;
}
puts ("\n b-?");
for (i=0; i<5; i++)
{ scanf ("%f",&p->b[i] );
printf(" %f ", p -> b[i]) ;
}
p=p1;
}
}
/* Приклад: в цій програмі показуються різні способи доступу до елементів структури. */
#include <conio.h>
#include <stdio.h>
#include <iostream.h>
struct st { char priz[10];
float f; int k;
};
void main ( )
{ st s[3]; int i;
for(i=0; i<3; i++)
cin >> (char*) &s[i]; // Ввiд priz
for(i=0; i<3; i++)
cout << endl << (char*) &s[i]; // Вивід priz
void *p_st = s; // Вказівник без типу
for(i=0; i<3; i++)
{ cout << endl << (char*)p_st; // Вивід, використовуючи вказівник
(( st *)p_st)++;
}
p_st = s;
for(i=0; i<3; i++)
{ cout << (char*)p_st; // Вивід, використовуючи вказівник
(( st *)p_st)++;
} }
/* Приклад: способи доступу до елементів структури, які використовуються у C/C++. */
#include <iostream.h>
struct dt { double r, i; };
struct fio { char f[l0];};
struct std ( dt d;
fio fn;
std *p;
};
void main ( )
{ dt *pd, x; fio *pf;
// std z = {l,2,"qwertn} ,*ps = &z; ps -> p = ps;
std z = {l,2,"qwert"},*ps; ps -> p = ps = &z;
double *pi; pi = &(z.d.r);
cout << “---“<< z.d.r << " " << z.d.i << " n << z.fn.f << " ";
cout << “***" << ps ->d.r << " “ << (*ps) .d.i << " ” << ps -> p-> fn.f << " " << *pi;
cout << endl; x=z.d;
pd=&z.d; cout << " +++” << pd -> r << “ “ << (*pd).i << “ “;
cout << endl;
}
/* Приклад: допустимі способи вводу стрічок і елементів структур. Вивід компонентів структури на екран. */
#include <stdio.h>
#include <iostream.h>
void main(void)
{ char pr, t[11], st[5];
struct x{char a[16], b[16], c[16]; } z, *pz;
pz=&z;
cout << "&z= " << &z << "&z.a= " << &z.a <<
"&z.b= " << &z.b << “ &z.c=" << &z.c << endl;
cout << "&pr= " << &pr << "&st= " << &st << " &t= " << &t << endl;
while(1)
{ cout << "Bвід 3-х стрічок";
сin >> st[0] ;
cout << "&st[0] (s) = "<< &st[0] << "&st[0] (p) ="
<< &st[0] << "pr(c)= " << pr;
cout << endl;
cin >> st;
cout << " st(s) = " << st << "st(p) = " << st << "pr(c) = " << pr << endl;
cin >> &st;
cout << "&st(s)= " << &st << "st(s) = " <<
st << " pr(c) = " << pr << endl;
cout << "&t(s) =" << &t << " t(p) = " << t << "pr(c) = " << pr << endl;
fflush (stdin) ;
switch(pr=getchar())
{ case 'q': return;
case ' r': cin >> z.a ;
cin >> z.b >> pz->c;
cout << "z.a(s)= " << z.a << " &z.a[0](p)= " << &z.a[0] << endl;
cout <<"z.b(s)= " << z.b << " &z.b[0]= " << &z.b[0] << endl;
cout << "&pz->c(s) = " << &pz ->c << " &pz->c(p)= " << &pz->c;
cout << endl;
cout << "&st[0] (s)= " << &st[0] << "&st[0] (p) = "
<< &st[0] << endl;
cout << "st(s)= "<< st << " st(p)= " << st << endl;
cout << " &st (s)=" << &st << " st(s) = "
<< st << " pr(c)- " << pr << endl;
cout << "&t(s) == " << &t << "t(p) = " << t << endl; break;
default: cout << "error:pr = q or r-?"; break;
}
}
}
/* Приклад: ввести масив структур. Розсортувати їх в алфавітному порядку стрічок, які входять в структури, і вивести елементи структур на екран. */
#include <stdio.h>
#include <iostream.h>
struct stud(char r[64]; int a, b , c;};
void main ( )
{ struct stud s[10], t, tl, t2;
int strcomp(struct stud, struct stud);
int i, j, k;
do{ cout << "k-?"; cin >> k;
for(i=0; i<k; i++)
{cin >> t.r >> t.a >> t.b >> t.c ; s[i]=t;}
for(i=0; i<k; i++)
for(j=i+1; j<k; j++)
if (strcomp (s[i], s[j] )>0) { t=s[i] ; s[i]=s[j] ; s[j]=t; }
for(i=0; i<k; i++) { t = s[i];
cout << t.r << " " << t.a << " " << t.b <<" " << t.c << endl;}
cout << " quit - 0 "; cin >> i ;
} while(i);
}
int strcomp(struct stud s1, struct stud s2)
{ char *cl,*c2; cl=sl.r; c2=s2.r;
cout << "&sl=" << &sl << " &s2=" << &s2 « "&sl.c="
<< &sl.c << "&s2.c= " << &s2.c << endl;
for( ; *cl == *c2; cl++, c2++) if( !*c2 ) return 0;
return *cl - *c2; }
// Можнa i так
int strcomp(struct stud si,struct stud s2)
{ int i;
cout << "&sl= " << &sl << "&s2= " << &s2 <<
"&sl.c= " << &sl.c << "&s2.c= " «&s2.c << endl;
for(i=0; sl.r[i} == s2.r[i]; i++) if (s2.r[i] == ‘\0’) return 0;
return sl.r[i]-s2.r[i];
} /*
або
/* int strcomp(struct stud s1, struct stud s2)
{ cout << "&sl= " << &sl << "&s2= " << &s2 << "&sl.c= "
<< &sl.c << “&s2.с=” << &s2.c << endl;
for(;*sl.r == *s2.r; sl.r++, s2.r++ ) // Не можна нарощувати константу
if (*s2.r == '\0’) return (0);
return *sl.r - *s2.r;
} */
/* Приклад: Демонстрація масивів структур, ініціалізація елементів і їх використання. */
#include <iostream.h>
#include <conio.h>
#define L 15
struct fio(char fam[L],name[L];}; // прізвище, імя
struct man{struct fio f; // f - елемент типу fio
char dol[L]; // посада
int year; // рік народження
double zar; } ; // зарплата
void main( )
{ struct man arr[2] = { "Позняк", "Андрій", "асистент", 1975,33000, "Поплавський","Степан","доцент",1960,45000};
struct man *ptr; // вказівник на cтруктуру
cout << " ARR: адрес arr[0]:" << &arr[0] << " arr[l] : " << &arr[1] << endl;
cout << " FAM: адрес arr[0]:" << arr[0].f.fam << " arr[l]: "
<< arr[l].f.fam << endl;
ptr = arr; // ptr містить адресу arr[0]
cout << " PTR: адрес arr[0] :"<< ptr << " arr[l]: " << ptr+1 << endl;
cout << "ptr->zar =" << ptr->zar <<:"(*ptr).zar = "<< (*ptr).zar << endl;
ptr ++;
// ptr містить адресу arr[l], адреса збільшується на 57 байт, на довжину структури
ptr->zar++; // Зарплата тепер 45001
cout << "ptr -> zar = " << ptr->zar << " (*ptr) .zar = " << (*ptr).zar << endl;
}