Jerzy F. Kotowski1 Informatyka I Wykład 11 STRUKTURY I UNIE
Jerzy F. Kotowski2 STRUKTURY - składnia struct etykieta { pole1; pole2; ……… }; Jest to definicja typu struct - słowo kluczowe etykieta - nazwa typu, tag name, label pole1, pole2 - składowe struktury umieszczane jedna po drugiej Rozmiaru struktury najlepiej nie liczyć na piechotę - operator sizeof }; - średnik niezbędny przy składni C++
Jerzy F. Kotowski3 STRUKTURY - przykład struct student { char Nazwisko[20]; char Wydzial[20]; int semestr_studiow; float stypendium; struct student *kolega; struct data data_ur; struct data data_rozp; }x,y,grupa[30]; Jest to równoczesna definicja i deklaracja obiektów x, y i grupa grupa - tablica struktur struct student *kolega - adres do obiektu swojego typu struct data - zdefiniowana wcześniej, na przykład tak: struct data { int day, month, year, y_day; char mon_name[4]; };
Jerzy F. Kotowski4 Operator składowych struktur To jest to:. Priorytet: 15 Przykłady użycia: printf(%s,x.Nazwisko);// &(x.Nazwisko[0]) y.semestr_studiow = 7; grupa[11].kolega = &x; grupa[1].kolega = grupa; // &grupa[0] grupa[7].kolega = grupa+5; // &grupa[5] x.data_ur.day = 10; y.data_rozp.year = 1998; strcpy(grupa[2].Nazwisko,Ela);// kopiowanie grupa[2].Nazwisko[0] = A;// Ela - Ala
Jerzy F. Kotowski5 Trochę ciekawostek struct student egzamin[100]; - deklaracja poza definicją. W C++ wystarczy: student egzamin[100]; int v = sizeof(struct student); - jedyny rozsądny sposób na określenie rozmiaru struktury. Uniezależnia nas od komputera i modelu pamięci. y = x; - operator podstawiania kopiuje obiekty składnik po składniku memcpy( &y, &x, sizeof(struct student)); - alternatywna technika wykorzystująca funkcję z biblioteki mem.h void *memcpy(void *dest, const void *src, size_t n); To jest prototyp funkcji memcpy. Funkcja zwraca dest. memcpy( egzamin, grupa, 30*sizeof(struct student));
Jerzy F. Kotowski6 struct student st1,st2 = {Kotowski, Elektronika, 7, 500.0, &st1, {1, 2, 1981, 32, FEB}, {1, 10, 2001,-1, OCT}}; Inicjalizacja TYLKO obiektu st2. &st1 - st1 zostało zadeklarowane wcześniej bo komputer analizuje linie programu od lewej do prawej. Podwójna struktura nawiasowa do liczenia numeru dnia w roku najlepiej mieć osobną procedurę i nie robić tego własnymi rękoma: int day_of_year(int day, int month, int year); Inicjalizacja wartości początkowych
Jerzy F. Kotowski7 int days[2][13] = {{0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31}}; int day_of_year(int day, int month, int year) { int y=!(year%4) && year%100 || !(year%400); while(--month) day += days[y][month];// day - input return day; } Przykład wywołania: if(st2.data_rozp.y_day<0) st2.data_rozp.y_day = day_of_year(st2.data_rozp.day, st2.data_rozp.month, st2.data_rozp.year);// RATUNKU!! Definicja funkcji day_of_year
Jerzy F. Kotowski8 int days[2][13] = {{0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31}}; int day_of_year(struct data x)// struct data już znana { int y=!(x.year%4) && x.year%100 || !(x.year%400); while(--x.month) x.day += days[y][x.month]; return x.day; } Przykład wywołania: st2.data_rozp.y_day = day_of_year(st2.data_rozp); Redefinicja funkcji day_of_year
Jerzy F. Kotowski9 Mamy rok i numer dnia w roku. Trzeba podać: numer miesiąca i numer dnia w miesiącu. Propozycja: podajemy adresy numeru miesiąca i numeru dnia w miesiącu. void day_month(int y_day, int year, int *p_d, int *p_m) { int m=1, y=!(year%4) && year%100 || !(year%400); while(y_day>days[y][m]) y_day -= days[y][m++]; *p_d = y_day; *p_m = m.; } Przykład wywołania: int month, day; day_month(100, 2001, &day, &month); Definicja funkcji day_month
Jerzy F. Kotowski10 Inny sposób rozwiązania: funkcja może zwrócić strukturę. struct data day_month(int y_day, int year) { struct data x; int m=1, y=!(year%4) && year%100 || !(year%400); while(y_day>days[y][m]) y_day -= days[y][m++]; x.day = y_day; x.month = m.; return x; } Przykład wywołania: struct data xx = day_month(100, 2001); Redefinicja funkcji day_month
Jerzy F. Kotowski11 Inna ważna struktura struct complex { float Re, Im; }; Przykład wykorzystania: struct complex x, *p; x.Re = 1; x.Im = -1;x=1-j Sprzężenie l. zespolonej: x.Im *= -1; lub x.Im = -x.Im; Operator wskazania na składową Jednym z większych błędów w C jest posłu- giwanie się nieustawio- nymi wskaźnikami p - globalny: NULL p - automatyczny: ??? Ustawiamy wskaźnik: p = &x; (*p).Re = 1; Nawiasy są niezbędne *p.Re *(p.Re) (*p).Re p -> Re 15
Jerzy F. Kotowski12 void suma(struct complex *p, struct complex *q, struct complex *r) { r->Re = p->Re + q->Re; r->Im = p->Im + q->Im; } Przykład wykorzystania: struct complex x = {1.5, 2.0}, y = {-2, 0}, z; suma(&x, &y, &z); Inny przykład: struct student st1, st2; st1.kolega = &st2; // Coś się dzieje st1.kolega -> data_ur.year = 1982; Przykłady wykorzystania
Jerzy F. Kotowski13 UNIE - składnia union etykieta { pole1; pole2; ……… }; Jest to definicja typu union - słowo kluczowe etykieta - nazwa typu, tag name, label pole1, pole2 - składowe unii umieszczane jedna obok drugiej Rozmiar unii to rozmiar największego składnika. Najlepiej nie liczyć na piechotę. }; - średnik niezbędny przy składni C++
Jerzy F. Kotowski14 UNIE - komentarz union Elektronika { int x,y; char s[4]; }; x s[0]s[1] y s[2]s[3] union ICT { double x; char s[6]; struct complex y; }; y.Re s y.Im x
Jerzy F. Kotowski15 union FIELD { int x; unsigned char s[2]; }pole; unsigned char low_byte(int x) { pole.x = x; return pole.s[0]; } unsigned char high_byte(int x) { pole.x = x; return pole.s[1]; } UNIE - przykłady Przykład wykorzystania: unsigned char low,high; int x; scanf(%d,&x); low = low_byte(x); high = high_byte(x); KONIEC! inf_11_1