Tablice wielowymiarowe Przykład tablica 2-wymiarowa Tak naprawdę nie istnieją w C! Tak naprawdę C i Java dopuszczają tworzenie tablic tablic tablica 2-wymiarowa = tablica (zwykłych) tablic tablica 3-wymiarowa = tablica tablic wymiaru 2 tablica (n+1)-wymiarowa = tablica tablic wymiaru n Każdy wymiar oznaczamy parą nawiasów ([]( []) int a[][][]; 3-wymiarowa tablica liczb całkowitych Inicjalizując używamy zagnieżdżonych list wartości Inicjalizując używamy Rozważmy tablicę o rozmiarze 3x2 1 2 4 6 C pamięta ją w sposób liniowy: 1 2 3 4 5 6 Kompilator zinterpretuje ją jako 3-elementową tablicę tablic 2-elementowych 3 1 2 3 4 5 6 a[1][0] 5 156 157 Przykład /* wypisz.c */ Przykład 3-wymiarowy Program na następnym slajdzie tworzy i przegląda następującą tablicę 3-wymiarową Program na następnym slajdzie tworzy i przegląda int a[][2] = {{1,2, {3,4, {5,6; int i,j; for (i = 0; i < 3; ++i) { printf("* "); for (j = 0; j < 2; ++j) printf("%d ", a[i][j]); putchar('*'); putchar('\n'); * 1 2 ** 3 4 ** 5 6 * a[0] == a[1] == 1 3 5 2 4 6 7 8 9 0 1 2 158 159
Przykład 3D c.d. /* wypisz3d.c */ int a[][3][2] = {{{1,2, {3,4, {5,6, {{7,8, {9,0, {1,2; int i, j, k; for (i = 0; i < 2; ++i) { printf("* "); for (j = 0; j < 3; ++j) { for (k = 0; k <2; ++k) printf("%d ", a[i][j][k]); putchar('*'); putchar('\n'); * 1 2 *3 4 *5 6 ** 7 8 *9 0 *1 2 * 160 Napisy to Napisy łańcuchy znaków Napisy to tablice znaków W języku Java występuje osobny typ/klasa String o większych możliwościach W języku Java występuje osobny typ/klasa String Ostatnim elementem w tablicy reprezentującej napis jest zawsze znak o kodzie 0 null null Ostatnim elementem w tablicy reprezentującej napis Literały napisowe automatycznie uzupełniają napis o terminator w postaci znaku null "Ahoj!" 'A' 'h' 'o' 'j' '!' '\0' 161 Napisy przykład Nagłówek <string.h> /* napisy.c */ #include <string.h> char imie[] = {'R', 'o', 'm', 'a', 'n', '\0'; char nazw[] = "Nowakowski"; printf("imię: %s\n", imie); printf("nazwisko: %s\n", nazw); printf("imię ma: %d znaków\n", strlen(imie)); printf("nazwisko ma: %d znaków\n", strlen(nazw)); Imię: Roman Nazwisko: Nowakowski Imię ma: 5 znaków Nazwisko ma: 10 znaków 162 Zawiera dwie grupy funkcji pozwalające na analizowanie i manipulowanie ciągami znaków funkcje o nazwach str wykonujące operacje na pamięci w bardziej ogólny sposób funkcje o nazwach mem Dostępne grupy operacji kopiowanie i łączenie: strcpy, strcat, memcpy,, porównywanie strcmp, memcmp,, wyszukiwanie strchr, memchr, strrchr, strstr, strtok,, inne: np. strlen, strerror,, 163
Formatowane przetwarzanie napisów /* ilustracja funkcji sprintf/sscanf */ int n = 1; float x = 2.0; char s[] = "ahoj"; char lancuch[bufsiz]; sprintf(lancuch,"%d %f A%s!", n+1, x+2, s+1); puts(lancuch); sscanf(lancuch,"%d %f %s", &n, &x, s); printf("n: %d, x: %f, s: %s\n", n, x, s); 2 4.000000 Ahoj! n: 2, x: 4.000000, s: Ahoj! Formatowane przetwarzanie napisów /* ilustracja funkcji sprintf/sscanf */ int n = 1; Błąd chociaż zadziałało! float x = 2.0; char s[] = "ahoj"; char lancuch[bufsiz]; sprintf(lancuch,"%d %f A%s!", n+1, x+2, s+1); puts(lancuch); sscanf(lancuch,"%d %f %s", &n, &x, s); printf("n: %d, x: %f, s: %s\n", n, x, s); 2 4.000000 Ahoj! n: 2, x: 4.000000, s: Ahoj! 164 165 Tablice mają statyczny rozmiar /* ilustracja funkcji sprintf/sscanf */ int n = 1; 'a' 'h' 'o' 'j' '\0' float x = 2.0; char s[] = "ahoj"; s[5]='x'; char lancuch[bufsiz]; printf("%db, %x, %x\n",sizeof(s),s[4],s[5]); sprintf(lancuch,"%d %f A%s!", n+1, x+2, s+1); sscanf(lancuch,"%d %f %s", &n, &x, s); printf("%db, %x, %x\n",sizeof(s),s[4],s[5]); 'A' 'h' 'o' 'j' '!' '\0' 5B, 0, 58 5B, 21, 0 Struktura Struktury w ANSI C uporządkowany zbiór zmiennych składowych składowych składowe mogą mieć różne typy Do definiowania służy słowo kluczowe struct Do odwoływania się do składowych struktury służy operator. Do odwoływania się do składowych struktury służy Struktury to punkt wyjścia dla pojęcia obiektu składowe to atrybuty obiektu 166 167
Struktury przykład #include <string.h> struct Towar { char nazwa[20]; float cena; ; // Średnik jest tu niezbędny!!! struct Towar t1 = {"Rower", 799.99; struct Towar t2; t2 = t1; t2.cena += 200.0; strcat(t2.nazwa, " Wagant"); printf("%s: %f.2\n", t1.nazwa, t1.cena); printf("%s: %f.2\n", t2.nazwa, t2.cena); Struktury przykład 2 #include <string.h> #define MAX 10 struct Towar { char nazwa[20]; float cena; ; struct Oferta { struct Towar lista[max]; int liczba; ; Rower: 799.99 zł Rower Wagant: 999.99 zł 168 169 Struktury przykład 2 c.d. struct Oferta mo; int i; mo.liczba = 0; /* wstaw pierwszy towar */ strcpy(mo.lista[mo.liczba].nazwa, "Rower"); mo.lista[mo.liczba++].cena = 799.99; /* wstaw drugi towar */ strcpy(mo.lista[mo.liczba].nazwa, "Torba"); mo.lista[mo.liczba++].cena = 29.99; /* wydrukuj listę towarów */ for (i = 0; i < mo.liczba; ++i) printf("%s: %.2f\n", mo.lista[i].nazwa, mo.lista[i].cena); Rower: 799.99 Torba: 29.99 170 Łańcuchy i przypisanie Język C dopuszcza inicjalizację char a[] = "Ahoj przygodo!"; W sytuacji char a[14]; a = "Ahoj przygodo!"; kompilator sygnalizuje błąd.. Dlaczego? Łańcuchy znaków to tablice, a język C nie dopuszcza bezpośredniego przypisywania wartości tablicowych. Należy w takiej sytuacji użyć funkcji strcpy char a[14]; strcpy(a, "Ahoj przygodo!"); 171
Złożone typy danych podsumowanie ANSI C funkcje Deklaracja/inicjalizacja tablicy ustala jednolity typ wszystkich jej elementów oraz niezmienny rozmiar Deklaracja/inicjalizacja tablicy ustala Indeksowanie tablic rozpoczyna się od zera Tablice wielowymiarowe to tablice tablic Napisy (łańcuchy) to tablice znaków; koniec łańcucha wyznacza znak null (o kodzie 0) Do tablic nie można stosować operatora przypisania Struktury pozwalają na łączenie danych różnych typów w całość Do struktur można stosować operator przypisania Struktury i tablice mogą być inicjalizowane za pomocą list elementów ujętych w nawiasy klamrowe Wprowadzenie programowanie proceduralne argumenty i wynik funkcji prototypy funkcji zasięg zmienne automatyczne, statyczne i globalne 172 173 Funkcje w ANSI C wprowadzenie Przykład Rola funkcji pomagają podzielić kod programu na mniejsze, logicznie wydzielone zadania ukrywają szczegóły pewnych operacji tam, gdzie ich znajomość nie jest niezbędna zwiększają przejrzystość kodu programu i ułatwiają wprowadzanie w nim zmian Funkcja podstawowe cechy posiada unikatową nazwę składa się z ciągu instrukcji implementującego dobrze określoną operację/zadanie może być zależna od argumentów i zwracać wynik /* Prosty przykład wykorzystania funkcji */ float avg(int n, int m) { return (n + m) / 2.0; int x,y; printf("podaj pierwszą liczbę: "); scanf("%d", &x); printf("podaj drugą liczbę: "); scanf("%d", &y); printf("średnia: %.2f\n", avg(x,y)); 174 175
Definicja funkcji postać ogólna typ_wyniku nazwa ( lista_parametrów ) { deklaracje instrukcje Lista parametrów jest listą par postaci typ nazwa_parametru oddzielonych przecinkami Jeśli funkcja ma zwracać pewną wartość, to musi ona być zgodna z zadeklarowanym typem_wyniku Uwagi Parametry funkcji pełnią rolę zmiennych lokalnych w kodzie funkcji Parametry funkcji pełnią rolę zmiennych lokalnych Wartość parametrów ustalana jest w momencie wywołania funkcji Wartość parametrów ustalana jest w momencie Do zwracania wyniku funkcji służy instrukcja postaci: return wyrażenie; Do zwracania wyniku funkcji służy instrukcja wyrażenie może być ujęte w nawiasy jeśli funkcja nie ma zwracać wyniku, to aby przekazać sterowanie z powrotem do programu wywołującego można użyć pustego wyrażenia, tzn. instrukcji return ; jeśli w funkcji nie występuje instrukcja return,, to sterowanie wraca do programu wywołującego po napotkaniu zamykającego nawiasu 176 177 Słowo kluczowe void Funkcja main,, ANSI C i void Użyte jako typ wyniku funkcji wskazuje, że funkcja nie zwraca żadnej wartości void f(int x, float y) { Użyte w miejscu listy parametrów funkcji mówi, że funkcja nie akceptuje żadnych argumentów void komunikat(void) { puts("witaj w "); komunikat(); 178 W tradycyjnym C można było napisać: main() { W języku ANSI C powyższe należy zamienić na: int main(void) { ANSI C dopuszcza jeszcze inny formę main: int main(int argc, char *argv[]) { 179