Progr

Programowanie

nie

w jęz

w ję yku C

zyku C

© 2009

Grzegorz Łukawski & Maciej Lasota

Politechnika Świętokrzyska w Kielcach

Wykład nr 4:

 Tablice

 Struktury

 Unie

 Własne typy danych

Tablice w języku C

Tablica to grupa takich samych, uporządkowanych elementów danych, umieszczona w jednym spójnym obszarze pamięci operacyjnej.

● Indeksy tablic zawsze liczone są od zera (jak w asemblerze)!

● Kompilator nie sprawdza zakresu indeksów!

● Jako indeks tablicy może być użyta liczba całkowita – można to obejść przez rzutowanie dowolnego typu na typ całkowity.

UWAGA!

Ponieważ indeksy tablic zawsze liczone są od zera, pierwszy element tablicy n-elementowej ma indeks 0, a ostatni n-1.

Tablice

Inicjalizacja przy deklaracji tablicy:

int tab1[30];

// 0 lub ?

int tab2[] = {5, 10, 15};

float t[32] = {0.1, 0.2, 0.3, 0.4};

// Pozostałe?

int tablica[20];

// 0..19

int i;long suma=0;

for(i=0;i < 20;i++) {

printf(”Podaj element %d:”,i);

scanf(”%d”,&tablica[i]);

}

for(i=0;i < 20;i++)

suma = suma + tablica[i];

printf(”Suma: %ld\n”,suma);

Tablice – wielkość tablic Operator sizeof() zwraca całkowitą liczbę bajtów zajmowaną przez tablicę:

int tablica[20];

double dane[4];

printf(”tablica - %dB\n”, sizeof(tablica));

// 20 * sizeof(int) = 20 * 4 = 80

printf(”dane - %dB\n”, sizeof(dane));

// 4 * sizeof(double) = 4 * 8 = 32

Porównywanie i kopiowanie tablic int t1[20]; int t2[20];

if( t1 == t2 )

puts(”Takie same”);

Porównywanie tablic:

int tab1[30],tab2[30];

int rozne;

(…)

rozne = 0;

for(int i=0;i < 30;i++)

if(tab1[i] != tab2[i]) rozne = 1;

Kopiowanie tablic:

int tab1[30],tab2[30];

(…)

for(int i=0;i < 30;i++)

tab1[i] = tab2[i];

Tablice wielowymiarowe

typ nazwa[wymiar1][wymiar2];

int tab2w[3][5] = {

{1,2,3,4,5},

{6,6,6,6,6},

{7,7,7,7,7}

};

printf(”%d”, tab2w[0][0]);

tab2w[2][4] = 0;

UWAGA!

W tablicach wielowymiarowych, analogicznie do tablic jednowymiarowych, indeksy liczone są od zera dla ka żdego z wymiarów.

Tablice znakowe

Tablica znakowa (złożona z elementów typu char) służy do przechowywania ciągów znaków. Traktowana jest przez kompilator języka C w szczególny sposób...

0

1

2

3

4

5

'T' 'e' 'k' 's' 't'

0

84

101 107 115 116

0

char tekst1[] = {'T','e','k','s','t',0}; char tekst2[] = ”Tekst”;

Tablice znakowe zachowują się (prawie) jak zwykłe tablice. Na każdym znaku z osobna można wykonywać dowolne operacje – również arytmetyczne.

Tablice znakowe – funkcje standardowe Tablicy znakowej nie można wprost porównywać ani kopiować!

● Można napisać własną funkcję, lub...

● ...skorzystać z jednej z funkcji standardowych.

#include <string.h>

int strcmp(t1,t2);

Porównuje dwa ciągi znaków, zwraca 0 (gdy takie same), wartość <0 (t1<t2), lub >0 (t1>t2).

int strncmp(t1,t2,n);

J.w. ale porównuje co najwyżej „n” znaków.

strcpy(to,from);

Kopiuje ciąg znaków z „from” do „to” wliczając znak 0.

strncpy(to,from,n);

Kopiuje co najwyżej „n” znaków,

jeżeli „from” ma mniej znaków niż „n”, uzupełnia znakami 0.

Tablice znakowe – funkcje standardowe strcat(to,from);

Dopisuje „from” do końca „to”.

strncat(to,from,n);

Jak wyżej, ale dopisuje co najwyżej „n” znaków.

strlen(t);

Zwraca długość ciągu (nie wliczając znaku 0).

char t1[] = ”Mam na imię ”;

char t2[256];

strcpy(t2, t1);

strcat(t2, ”Stefan”);

puts(t2);

printf(”Długość = %d\n”, strlen(t2));

Tablice znakowe – funkcje standardowe puts(tekst);

Wyświetla „tekst” na ekranie, dodając znak końca lini „\n”.

printf(”Mam na imię %s\n”, imie);

Ciąg „%s” zastępowany jest ciągiem znaków.

gets(tekst);

Wczytuje ciąg znaków, aż do naciśnięcia klawisza Enter (Niebezpieczna – funkcja nie otrzymuje informacji o ilości miejsca na znaki!).

fgets(tekst, dlugosc, stdin);

Jak wyżej, ale wczyta co najwyżej „dlugosc” znaków – funkcja znacznie bezpieczniejsza niż gets()!

UWAGA!

Żadna z funkcji standardowych nie tworzy miejsca na wczytywane/kopiowane znaki. Programista musi zapewnić odpowiednią ilość miejsca w pamięci!

Struktury

Struktura to obiekt złożony z kilku zmiennych, możliwe że różnych typów, zgrupowanych pod jedną wspólną nazwą. Każda składowa struktury ma swój identyfikator (nazwę pola).

struct {

char nazwa[32];

float cena;

short ilosc;

} poz, *wpoz;

poz.cena = 0.5;

wpoz->cena = 0.5;

x = poz.ilosc / 2;

wpoz->ilosc = 1000;

strcpy(poz.nazwa, ”CD-R”);

puts(wpoz->nazwa);

Typ strukturalny

struct element {

char nazwa[32];

struct punkt {

float cena;

int x, y;

long ilosc;

} p1, p2;

};

struct element pozycja;

struct element *wpozycja;

Wartości początkowe – analogicznie jak dla zmiennych lokalnych/globalnych innych rodzajów i typów!

struct element pozycja = {”Monitor LCD”, 499.99, 100};

Tablica struktur

struct element oferta[] = {

{”Monitor LCD”, 499.99, 100},

{”Klawiatura”, 19.99, 250},

{”Kabel 220V”, 8.50, 133}

};

for(int n=0;n < 3;n++) {

printf(”Nazwa: %s\n”, oferta[n].nazwa); printf(”Cena: %f\n”, oferta[n].cena); printf(”Ilość: %d\n”, oferta[n].ilosc);

}

Struktury zagnieżdżone

struct transport {

float waga;

struct element towar;

} t1, t2;

t1.waga = 155;

t1.towar.cena = 4.99;

puts(t2.towar.nazwa);

Dla zmiennych wskaźnikowych:

struct transport *wt;

wt->waga = 10.25;

wt->towar.ilosc = 1;

Struktury wskazujące na same siebie struct el_li {

char nazwa[32];

float cena;

long ilosc;

struct el_li *next;

};

Jest to przykład klasycznej listy jednokierunkowej – każdy element zawiera wskaźnik na kolejny element tego samego typu.

Unie

Unia to rodzaj zmiennej, która w jednym wspólnym obszarze pamięci może przechowywać obiekty różnych typów i rozmiarów.

union zmienne {

long w_long;

double w_double;

short w_short;

} z;

Wielkość uni odpowiada wielkości największego jej pola: sizeof(z) = 8;

// sizeof(double) = 8

Odwołanie do pól uni – analogicznie jak do struktur: z.w_long = 1000;

x = z.w_short;

Wartość początkowa uni musi dotyczyć jej pierwszego pola (typu).

Unie i struktury

Elementem składowym uni może być struktura i vice versa.

Odwołanie do pól zagnieżdżonych uni /struktur następuje identycznie jak dla struktur.

Przykład – rejestr EAX procesora 80x86 reprezentowany przez unię: union rejestr_eax {

eax

long eax;

short ax;

ax

struct {

char al, ah;

ah

al

} b;

} eax;

32b (4B)

eax.b.al = 0x10;

eax.b.ah = 0x20;

x = eax.ax;

// x = 0x2010

Definicja własnych typów danych typedef istniejący_typ nowy_typ;

typedef unsigned long ULong;

(…)

ULong licznik = 5;

ULong tabela[32];

typedef char String[64];

typedef struct {

String s1 = "ABCD";

int szer, wys;

puts(s1);

char kolor;

} Prostokat;

(…)

Prostokat pr = {10,10,0};

Document Outline

  • Slajd 1
  • Slajd 2
  • Slajd 3
  • Slajd 4
  • Slajd 5
  • Slajd 6
  • Slajd 7
  • Slajd 8
  • Slajd 9
  • Slajd 10
  • Slajd 11
  • Slajd 12
  • Slajd 13
  • Slajd 14
  • Slajd 15
  • Slajd 16
  • Slajd 17
  • Slajd 18