Skip to content

4. Struktury

majsylw edited this page Feb 20, 2020 · 4 revisions

Tablice pozwalają przechowywać wiele wartości, ale wszystkie muszą być tego samego typu. Jeżeli chcemy przechowywać dane dotyczące jednego obiektu, ale będące różnych typów, możemy wykorzystać strukturę. I o tym jest dzisiejsza lekcja.

Definiownie struktur

W celu korzystania ze struktury należy zdefiniować jej składowe:

struct [etykieta struktury]{
    definicja składowej;
    definicja składowej;
    ...
    definicja składowej;
};

Przykładowa definicja struktury reprezentującej punkt na płaszczyźnie 2D będzie prezentować się następująco:

struct PunktXY{
    float x;
    float y;
};

Definicja struktury określa układ składowych w strukturze. Musimy pamietać, że samo zdefiniowanie struktury nie jest równoznaczne z utworzeniem zmiennej strukturalnej. Zmienne typu strukturalnego są deklarowane analogicznie jak zmienne typów podstawowych, to znaczy za pomocą konstrukcji

struct PunktXY a, b;

Strukturę można inicjalizować, umieszczając po definicji listę wartości początkowych, czyli dla naszego punktu będzie to:

struct PunktXY a = {3.20, 2.00};

Możemy definiować struktury zawierające inne struktury. Przykładowo informacje o trójkącie można przechowywać w strukturze zdefiniowanej następująco

struct triangle {
    struct PunktXY A;
    struct PunktXY B;
    struct PunktXY C;
};

W powyższym przykładzie trzy pola można zastąpić tablicą struktur.

struct trojkat {
    struct PunktXY wierzcholki[3];
};

Podobnie można zdefiniować strukturę opisującą wielokąt posługując się wskaźnikiem na pierwszy element tablicy struktur oraz rozmiarem tej tablicy (wyrażającym liczbę wierzchołków).

struct wielokat {
    int n;
    struct PunktXY * wierzcholki;
};

Operacje na strukturach

Aby uzyskać dostęp do elementów składowych struktury korzystamy z operatora . (kropka), co wygląda następująco nazwaZmiennejStrukturalnej.nazwaSkładowej.

Ze względu na to, że struktury mogą mieć duży rozmiar, korzystne może być posługiwanie się wskaźnikami na struktury. Wiąże się to także z odpowiednim przekazywaniem struktur do funkcji (czyli przez wskaźnik). Dostęp do struktur wskazywanych przez wskaźnik uzyskuje się operatorem ->.

wskaźnikNaStrukturę->nazwaSkładowej
(*wskaźnikNaStrukturę).nazwaSkładowej

Zastosujmy poznane operatory na przykładzie struktury Polynomial przechowującej stopień wielomianu jako liczbę całkowitą oraz wskaźnik na pierwszy element tablicy przechowującej jego współczynniki.

#include <stdio.h>
#include <stdlib.h>

struct Polynomial{
    int degree; //stopien wielomianu
    double *coefficients; //wskaznik na tablice wspolczynnikow
};

// tworzymy nowa zmienna typu Polynomial z tablica wspolczynnikow o odpowiednim rozmiarze
struct Polynomial * newPolynomial(int n);

// drukujemy wielomian na ekranie
void printPolynomial(struct Polynomial *wielomian);

void deletePolynimial(struct Polynomial ** wielomian_coef);

void setPolynomial(struct Polynomial *, double *);

int main()
{
    //deklaracja zmiennych a typu Polynomial
    struct Polynomial * a = newPolynomial(5);
    //drukowanie na ekranie zawartosci zmiennej - tablica powinna byc wypelniona zerami
    printPolynomial(a);
    printf("\n");

    double tablica[] = {6,3,8,1,2,3};
    setPolynomial(a, tablica);

    printPolynomial(a);
    printf("\n");

    //usuwamy wypelniona tablice wspolczynnikow (zwalniamy pamiec)
    deletePolynimial(&(a->coefficients));
    //zwalniamy pamiec dla wskaznika na strukture Polynomial
    free(a);
    return 0;
}

// tworzymy nowa zmienna typu Polynomial z tablica wspolczynnikow o odpowiednim rozmiarze
struct Polynomial * newPolynomial(int n){
    struct Polynomial *wielomian = malloc(sizeof(struct Polynomial));

    // przypisujemy wartosci polom struktury wielomian
    wielomian->degree = n;
    wielomian->coefficients = malloc((n+1) * sizeof(*(wielomian->coefficients)));//bo potrzebujemy n+1 wspolczynnikow, np dla wielomianu stopnia 2 mamy a,b i c -> ax^2+bx+c (3 wspolczynniki)

    int i;
    for(i = 0; i <= n; ++i){ // wypelniamy tabele wspolczynnikow zerami
        wielomian->coefficients[i] = 0;
    }
    return wielomian;
};

// drukujemy wielomian na ekranie
void printPolynomial(struct Polynomial *wielomian){
    if(wielomian != NULL){//sprawdzamy czy w ogóle nasz wskaznik przekazany jako argument funkcji wskazuje na jakiekolwiek miejsce w pamieci
        int i;
        printf("f(x) = ");
        for(i = wielomian->degree; i > -1; --i){
            printf("%+.2lfx^%d", wielomian->coefficients[i], i);
        }
    } else{
        printf("\nWskaznik jest pusty!\n");
    }
};

void deletePolynimial(struct Polynomial ** wielomian_coef){
    if(wielomian_coef != NULL){
        free(wielomian_coef); // zwalniamy pamiec
        wielomian_coef = NULL; // ustawiamy wskaznik 'w nicosc'
    }
};

void setPolynomial(struct Polynomial * wielomian, double *tab){
    int i;
    for(i = 0; i <= wielomian->degree; ++i){ // wypelniamy tabele wspolczynnikow
        wielomian->coefficients[i] = tab[i];
    }
}

Słowo kluczowe typedef

typedef jest słowem kluczowe, które służy do definiowania typów pochodnych.

typedef stara_nazwa  nowa_nazwa;
typedef int mojInt;
typedef int* WskNaInt;
typedef struct PunktXY punkt;

punkt a = {3.20, 2.00}; //inicjalizacja struktury PunktXY wykorzystując zdefiniowany typ pochodny

Jak można dostrzec na powyższym przykładzie, słowo kluczowe typedef pozwala nam uniknąć ciągłej potrzeby wypisywania struct nazwa_struktury nazwa_zmiennej w przypadku deklaracji zmiennej strukturalnej.

Struktury cykliczne

Polem struktury nie może być ta sama struktura, ale może być wskaźnik na taką strukturę. Tego typu struktury nazywamy strukturami cyklicznymi. Przykładem takich struktur są lista (np. jednokierunkowa) oraz drzewo (np. binarne).

Clone this wiki locally