• Nie Znaleziono Wyników

struct MOUSE_EVENT {

N/A
N/A
Protected

Academic year: 2021

Share "struct MOUSE_EVENT { "

Copied!
8
0
0

Pełen tekst

(1)

Wprowadzenie do programowania w języku C — struktury. pola bitowe, unie

Struktury czyli rekordy w C/C++

Struktury (rekordy) są złożonymi zmiennymi, składającymi się z elementów różnych typów zwanych polami, taką grupę pól można traktować jako jeden obiekt a nie zestaw obiektów oddzielnych.

struct MOUSE_EVENT {

int x, y; /* Pozycja kursora myszki na ekranie */

unsigned char buttons; /* Informacja o stanie przycisku */

int double_click; /* Czy podwójne klikni ęcie ? */

};

struct WINDOW_INFO {

int x, y; /* Pozycja lewego górnego naro żnika okna */

int w, h; /* w – szeroko ść okna, h – wysokość okna */

int frame_type; /* Typ wzorca ramki */

char * title; /* Wska źnik do obszaru tytułu okna */

};

Odwoływanie się do pól struktur — hipotetyczna funkcja obsługi

void process_mouse_event( struct MOUSE_EVENT me ) {

. . .

if( me.buttons & M_LEFT_BUTTON_PRESSED ) if( me.double_click )

find_object_on_pos( me.x, me.y );

. . . }

Odwoływanie się do pól struktur, wskaźniki — hipotetyczna funkcja obsługi

void process_mouse_event( struct MOUSE_EVENT * me ) {

. . .

if( me->buttons & M_LEFT_BUTTON_PRESSED ) /* zamiast (*me).buttons */

if( me->double_click )

find_object_on_pos( me->x, me->y );

. . . }

Struktury mogą być zagnieżdżane

struct EVENT {

int event_kind; /* Kod rodzaju zdarzenia */

struct MOUSE_EVENT mouse_ev; /* Rekord opisu zdarzenia dot. myszki */

struct KEYBD_EVENT keybd_ev; /* Rekord opisu zdarzenia dot. klawiatury */

};

. . .

struct EVENT ev;

. . .

if( ev.kind == FROM_MOUSE ) if( ev.mouse_ev.duble_click )

find_object_on_pos( ev.mouse_ev.x, ev.mouse_ev.y );

. . .

(2)

Wprowadzenie do programowania w języku C — struktury. pola bitowe, unie

Deklarowanie struktur, specyfikacja typedef

Alternatywne sposoby deklaracji zmiennych strukturalnych struct POINT

{

int x, y;

} p1, p2, p3;

struct POINT {

int x, y;

};

struct POINT p1, p2, p3;

POINT to etykieta struktury, w języku C nie jest to nazwa typu (w C++ tak).

Deklaracja struktury może nie zawierać etykiety, lecz to mało użyteczna rzecz.

struct {

int x, y, radius;

} c1, c2, c3;

Aby skrócić zapis można używać deklaracji typedef:

typedef struct { int x, y, radius } CIRCLE;

typedef struct MOUSE_EVENT MOUSE_EVENT_STRUCT;

. . .

CIRCLE c1, c2, c3;

MOUSE_EVENT_STRUCT ev, * ev_ptr = NULL;

Aby uniknąć zastanawiania się nad nazwami:

struct _POINT_3D {

int x, y, z;

};

typedef struct _POINT_3D POINT_3D;

Składowa struktury (pole) nie może być tego samego typu co właśnie deklarowana struktura ale może być wskaźnikiem:

struct A ( struct A a ); /* B łąd */ struct A ( struct A * a ); /* OK */

Ogólnie, w przypadku wskaźników można użyć niekompletnej deklaracji:

struct A; /* Niekompletna deklaracja */

struct B { struct A * pa; };

Pola bitowe

struct EVENT_TYPE {

unsigned char from_mouse : 1;

unsigned char from_keybd : 1;

unsigned char from_timer : 1;

} event_source;

. . .

event_source.from_mouse = 1;

event_source.from_keybd = event_source.from_timer = 0;

. . .

if( event_source.from_mouse )

. . .

(3)

Wprowadzenie do programowania w języku C — struktury. pola bitowe, unie

Pola bitowe zachowują się jak małe zmienne całkowite. Mogą być deklarowane tylko w strukturach, uniach i klasach (C++). Nie wolno pobierać adresu pola bitowego: &event_source.from_mouse jest niedozwolone. Ogólnie, deklaracja pola bitowego przyjmuje postać:

specyfikator-typu <identyfikator-pola-bitowego> : szerokość-pola

gdzie specyfikator-typu to char, unsigned char, int lub unsigned int.

Specyfikacja szerokość-pola musi wystapić, nie może ona przekraczać rozmiaru typu określonego przez specyfikator-typu.

struct BIT_FIELDS {

int i : 2;

unsigned int j : 2;

int : 3;

int k : 1;

} a;

a.i = 3 —— a.i == -1 ( bin: 11 ) a.i = 6 —— a.i == -2 ( bin: 10 )

a.k = 0 —— a.k == 0 ( bin: 0 ) a.k = 1 —— a.k == -1 ( bin: 1 )

0 1 2 3 4 5 6 7

1 1 0 0 0 0 0 1

k

nieu¿ywane

j i

Pola bitowe są rozwiązaniem mocno zależnym od implementacji. Zatem mogą one zachowywać się inaczej po zmianie środowiska systemowego lub nawet tylko kompilatora. Ograniczają one przeno ś no ść kodu ź ród ł owego.

Unie

Unia jest zmienna, która w różnych momentach może zawierać obiekty różnych typów i rozmiarów. W damym momencie tylko jeden obiekt jest „aktywny”.

Wszystkie składowe unii są pamiętane w tym samym miejscu pamięci, rozmiar unii jest równy rozmiarowi największej składowej.

union EVENT_INFO {

struct MOUSE_EVENT mouse_ev; /* Rekord opisu zdarzenia dot. myszki */

struct KEYBD_EVENT keybd_ev; /* Rekord opisu zdarzenia dot. klawiatury */

struct TIMER_EVENT timer_ev; /* Rekord opisu zdarzenia dot. klawiatury */

};

struct EVENT {

unsigned char from_mouse : 1; /* 1 gdy zdarzenie pochodzi od myszki */

unsigned char from_keybd : 1; /* 1 gdy zdarzenie pochodzi od klawiat. */

unsigned char from_timer : 1; /* 1 gdy zdarzenie pochodzi od timera */

union EVENT_INFO ei; /* Unia zdarze ń -- 3 in 1 */

} event;

. . .

get_event_info( &event );

. . .

if( event.from_mouse )

if( event.ei.mouse_ev.double_click )

find_object_on_pos( event.ei.mouse_ev.x, event.ei.mouse_ev.y );

. . .

(4)

Wprowadzenie do programowania w języku C — dynamiczne struktury danych

Dynamiczny przydział pamięci

void * malloc( size_t size );

Rezultatem funkcji malloc jest wskaźnik do obszaru pamięci przeznaczonego dla obiektu o rozmiarze size. Rezultatem jest NULL jeżeli polecenie nie może być zrealizowane. Obszar nie jest inicjowany.

void * calloc( size_t nitems, size_t size );

Rezultatem funkcji calloc jest wskaźnik do obszaru pamięci przeznaczonego dla nitems obiektów o rozmiarze size. Rezultatem jest NULL jeżeli polecenie nie może być zrealizowane. Obszar jest inicjowany zerami.

void * realloc( void * ptr, size_t size );

Funkcja dokonuje próby zmiany rozmiaru bloku wskazywanego przez ptr, który był poprzednio przydzielony wywołaniem funkcji calloc lub malloc. Zawartość wskazywanego obszaru pozostaje niezmieniona. Jeżeli nowy rozmiar jest większy od poprzednio przydzielonego, dodatkowe bajty mają nieokreśloną wartość.

Jeżeli nowy rozmiar jest mniejszy, bajty z różnicowego obszaru są zwalniane.

Jeżeli ptr == NULL to funkcja działa jak malloc. Rezultatem funkcji jest wskaźnik na obszar pamięci o nowym rozmiarze (może być ulokowany w pamięci w innej lokalizacji niż poprzednio). Rezultatem jest NULL w przypadku błędu lub próby przydziału bloku o zerowym rozmiarze.

void free( void * ptr );

Zwalnia obszar pamięci wskazywany przez ptr. Parametr musi być wskaźnikiem do obszaru pamięci przydzielonego uprzednio przez malloc, calloc lub realloc.

int n = 300;

char * s;

. . .

if( ( s = ( char * )malloc( n * sizeof( char ) ) ) != NULL ) {

strcpy( s, "Dynamicznie przydzielony napis" );

for( i = 0; s[ i ] != ‘\0’; i++ ) putchar( s[ i ] );

. . . free( s ) }

Alternatywne konstrukcje lecz calloc zeruje pamięć a malloc nie

s = (char *)malloc(n*sizeof(char)) s = (char *)calloc(n,sizeof(char))

int queue_len = 32;

struct EVENT * queue;

. . .

if( (queue=(struct EVENT *)calloc(queue_len,sizeof(struct EVENT)))!= NULL ) set_application_queue( queue );

. . .

free( queue );

(5)

Wprowadzenie do programowania w języku C — dynamiczne struktury danych

Rekurencyjne struktury danych

Jednokierunkowa lista inwersyjna. Program przykładowy wczytuje linie tekstu z stdin, magazynuje je w liście, następnie wyświetla w odwrotnej kolejności.

Wprowadzanie kończy naciśnięcie znaku odpowiadającego znacznikowi końca pliku (^Z — Dos/Windows, ^D — Unix).

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define MAX_LEN 128

struct _NAME {

char name[ MAX_LEN ]; /* Pole do przechowywania napisu */

struct _NAME * prev; /* Odsy łacz do poprzedniego elementu listy */

};

typedef struct _NAME NAME;

int main() {

NAME * last = NULL; /* Wska źnik na koniec tworzonej listy */

NAME * work = NULL; /* Wska źnik pomocniczy */

char buffer[ MAX_LEN ]; /* Bufor odczytywanej linii */

/* Czytaj linie dopóki nie wprowadzono znaku konca pliku (^Z lub ^D) */

while( gets( buffer ) != NULL ) {

if( ( work = ( NAME * )malloc( sizeof( NAME ) ) )!= NULL ) {

strcpy( work->name, buffer ); /* Zapami ętaj linię w el-cie listy */

work->prev = last; /* Do łącz element do listy */

last = work; /* Teraz nowy element jest ostatni */

} }

. . .

/* Wykorzystanie napisów zgromadzonych w li ście */

for( work = last; work != NULL; work = work->prev ) printf( "\n%s", work->name );

/* Zwolnienie pami ęci przydzielonej elementom listy*/

while( last != NULL ) {

work = last;

last = last->prev;

free( work );

}

return 0;

}

(6)

Wprowadzenie do programowania w języku C — dynamiczne struktury danych

NAME * last = NULL;

NAME * work = NULL;

work

last

work

last last = work;

work

last work->prev = last;

work = ( NAME * )malloc( sizeof( NAME ) ) work

last

work->prev = last; work

last

last = work; work

last

work = ( NAME * )malloc( sizeof( NAME ) );

work

last

Przydzia³ pamiêci dla nowego elementu

Ustalenie odsy³acza do poprzedniego elementu

Do³¹czenie elementu do listy

Przydzia³ pamiêci dla kolejnego elementu

Ustalenie odsy³acza do poprzedniego elementu

Do³¹czenie elementu do listy

WskaŸniki przed rozpoczêciem tworzenia listy

(7)

Wprowadzenie do programowania w języku C — dynamiczne struktury danych

Lista dwukierunkowa — program przykładowy, temat jak poprzednio

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define MAX_LEN 80

typedef struct _NAME {

char name[ MAX_LEN ]; /* Pole do przechowywania napisu */

struct _NAME * next; /* Odsy łacz do następnego elementu listy */

struct _NAME * prev; /* Odsy łacz do poprzedniego elementu listy */

} NAME;

int main() {

NAME * first = NULL, * last = NULL; /* Pocz ątek i koniec listy */

NAME * work;

char buffer[ MAX_LEN ];

while( gets( buffer ) != NULL ) {

if( ( work = ( NAME * )malloc( sizeof( name ) ) )!= NULL ) {

strcpy( work->name, buffer );

if( first == NULL ) /* Czy lista jest pusta? */

{

work->next = work->prev = NULL; /* Nie ma poprz. i nast ępnego */

first = last = work; /* Pocz ątek == koniec */

} else {

work->next = NULL; /* Nie ma nastepnego – to ostatni element */

work->prev = last; /* Ostatni elem. staje si ę poprz. dla nowego */

last->next = work; /* Nowy element staje si ę następnym dla ostat.*/

last = work; /* Teraz nowy element staje si ę ostatnim */

}/* if-else */

}/* if */

}/* while */

/* Maszerujemy po li ście – od początku do końca */

for( work = first; work != NULL; work = work->next ) printf( "\n%s", work->name );

/* Maszerujemy po li ście – od końca do początku*/

for( work = last; work != NULL; work = work->prev ) printf( "\n%s", work->name );

/* Zwolnienie pami ęci przydzielonej elementom listy*/

while( first != NULL ) /* Zwolnienie pami ęci */

{

work = first;

first = first->next;

free( work );

}

return 0;

}

(8)

Wprowadzenie do programowania w języku C — dynamiczne struktury danych

NAME * first = NULL;

NAME * last = NULL;

NAME * work = NULL;

work last

work

first work = ( NAME * )malloc( sizeof( NAME ) )

work

first

last

work->next = work->prev = NULL;

work

first

first = last = work; work

first

work = ( NAME * )malloc( sizeof( NAME ) );

work

first

Przydzia³ pamiêci dla nowego elementu

Ustalenie odsy³acza do nastêpnego/poprzedniego elementu

Do³¹czenie elementu do listy

Przydzia³ pamiêci dla kolejnego elementu

Do³¹czenie elementu do listy WskaŸniki przed rozpoczêciem tworzenia listy

first

last last

work->next = NULL; work->prev = last;

last->next = work;

last = work;

last

last

Cytaty

Powiązane dokumenty

Natomiast z mecenatu nad zespołami artystycznymi KUL i Studium Nauczycielskiego i Rada Okręgowa będzie musiała zrezygnować, ponieważ zespoły te od dłuższego czasu

Mówiąc najprościej, Gellner stara się wyjaśnić dwa zdumiewające zjawiska współczesności: błyskawiczny i pokojowy zanik komunistycznego imperium wraz z ideologią

Koszty wejścia 0,00% Wpływ kosztów, które inwestor ponosi przy rozpoczynaniu inwestycji Koszty wyjścia 0,00% Wpływ kosztów wyjścia

Kościół (Kościoły) jest (są) nośnikami pamięci także jako instytucje - w ich strukturze odbijają się bowiem nawarstwienia kolejnych wieków.. W dzisiejszym kształcie

 gdy rozmiar tablicy będzie znany dopiero podczas wykonania programu a nie podczas jego kompilacji.  gdy rozmiar tablicy jest

Stanowiło rzadką, w pewnym sensie dziś już niemożliwą, instytucję humanistyki, gdzie kształciły się umiejętności, których nie sposób nabyć poprzez rodzaj

- ściśle rosnąca wtedy i tylko wtedy, gdy jej pochodna jest nieujemna oraz między każdymi dwoma punktami przedziału P znajduje się punkt, w którym pochodna ' f jest dodatnia, -

Pomimo swojego fizycznego, a zatem empirycznego wymiaru, jest ono mocno uwarunkowane historycznie i kulturowo, stąd analizy kontrastywne ukazują znaczne różnice w sposobach