WSKAŹNIKI: Definicja: Wskaźnik jest zmienna, która zawiera adres innej zmiennej

20
IKI: a: Wskaźnik jest zmienna, która zawiera adres innej zmiennej będzie zmienną typu int, a wx wskaźnikiem (nie jest ważny w t tworzenia tego skaźnika). Jendoargumentowy operator & dres obiektu, zatem &x jest adresem zmiennej x. Możemy więc px=&x : Komputer rozmieszcza wartości zmiennych w „komórkach” „Komórki” są „numerowane” - adresowane. Wartość x zidentyfik tując zawartość odpowiedniej „komórki” ąc numer „komórki” - wskaźnik e: cza przeniesienie wartości „komórki” x-sa do „komórki” y znacza nadanie zmiennej wx wartości równej adresowi „komórki wartością x”. „Odczytanie” adresu - to wykonanie operacji &x

description

WSKAŹNIKI: Definicja: Wskaźnik jest zmienna, która zawiera adres innej zmiennej Niech x będzie zmienną typu int, a wx wskaźnikiem (nie jest ważny w tej chwili sposób utworzenia tego skaźnika). Jendoargumentowy operator & - PowerPoint PPT Presentation

Transcript of WSKAŹNIKI: Definicja: Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Page 1: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

WSKAŹNIKI:Definicja: Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Niech x będzie zmienną typu int, a wx wskaźnikiem (nie jest ważny w tej chwilisposób utworzenia tego skaźnika). Jendoargumentowy operator &podaje adres obiektu, zatem &x jest adresem zmiennej x. Możemy więc napisac: px=&xPAMIETAJ: Komputer rozmieszcza wartości zmiennych w „komórkach”pamięci. „Komórki” są „numerowane” - adresowane. Wartość x zidentyfikowaćmożemya) odczytując zawartość odpowiedniej „komórki”b) podając numer „komórki” - wskaźniknapisanie:y=x oznacza przeniesienie wartości „komórki” x-sa do „komórki” ywx=&x oznacza nadanie zmiennej wx wartości równej adresowi „komórki z wartością x”. „Odczytanie” adresu - to wykonanie operacji &x

Page 2: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Operator „odwrotny” względem operatora & to *Tak więc jeśli wx jest wskażnikiem zmiennej x,to *wx„odczytuje” zawartość „komórki” o adresie wx - to znaczy, żewartość *wx jest równa x! Zatem jeśli mamy w programiefragmentint x,y;int *wx;wx=&x; to oznacza, że y=x !!!!y=*wx;

PAMIĘTAJ: jeśli wx jest wskażnikiem to zmiennej typu, powiedzmy AAA (o definiowaniu typów mówiliśmy poprzednio)to aby instrukcja y=*wx nie prowadziła do błędów (np. zaokrągleń)to *wx oraz y (y=*wx) powinny być typu AAA

Page 3: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jeśli (jak poprzednio) wx jest wskaźnikiem do x, wx=&x, to wyrażeniey=*wx+1 oznacza y=x+1; wyrażenie printf(``%d\n”,*wx) oznacza to, coprintf(``%d\n”,x). ALE WYRAŻENIE: y=*(wx+1) nie oznacza, że y=x+1!!!bowiem wówczas wx+1 jest adresem kolejnej „komórki” (następnej poadresie zmiennej x), a *(wx+1) jest „zawartością tej (następnej) komórki” !Zawartość ta może nie być przez programistę kontrolowana; będzie ona kontrolowana wtedy, gdy wx wskazuje np. na adres pierwszego elementutablicy.Napisanie*wx=0 oznacza wyzerowanie wartości zmiennej x, czyli x=0Napisanie*wx+=1 to x+=1, zatem zwiększenie x o jedenPodobnie działa (*wx)++ . WAŻNA UWAGA: napisanie *wx++ to nie to samo co (*wx)++, bowiem operacje zawsze wykonywane są od prawej do lewej. Tak więc *wx++ to zwiększenie wskaźnika o jeden, a następnie pobranie wartości komórki odpowiadającej temu (zwiększonemu) wskaźnikowi. (*wx)++ to zwiększenie zmiennej x o jeden.

Page 4: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jeśli wx=&x oraz wy=&y, to operacjawy=wx powoduje, że oba skaźniki: wx i wy będą wskazywały na x;zawarość komórki y nie zmieni się. Zmianę wartości y spowodujey=*wxWSKAŹNIKI JAKO ARGUMENTY FUNKCJIchcemy napisać funkcję (procedurę; w C nie ma rozróżnienia), którazamienia zmienną x na y a y na x. Jeśli napiszemyswap(x,y)int x,y;{ int temp; temp=x; x=y; y=temp;}TO BĘZIE ŹLE!. Pamiętamy, że argumenty funkcji przekazywanesą przez wartość. W momencie wywołania funkcji tworzone są„lokalne” kopie argumentów a ich wartość w programie wywołującym NIE ZMIENIA SIĘ

Page 5: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jednak program wywołujący może przekazywać WSKAŹNIKI doZMIENIANYCH WARTOŚCI ( Jak to było w PASCALU?)piszemy:swap(wx,wy)int *wx,*wy;{int temp;temp=*wx;*wx=*wy;*wy=temp;}A WYWOŁUJEMY:swap(&a,&b) jeśli chcemy zamienić wartościami a z b(Pamiętamy funkcję scanf, wówczas nie podaliśmy uzasadnienia, dlaczegoczytając zmienna x pisaliśmy &x; uzasadnienie takiego zapisu znajdujemyteraz)

Page 6: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Zadanie 13Napisz program „kalkulator”, który oblicza sumę lub różnicę lubiloczyn lub iloraz dwu wczytanych liczb rzeczywistych w zależnosciod wczytanego operatora: + lub - lub * lub / . Obliczanie sumy, różnicyiloczynu i ilorazu MUSI BYĆ zapisane w oddzielnych funkcjach(procedurach). Wynik działania MUSI BYĆ parametrem funkcji,a NIE MOŻE być podstawiony pod nazwę funkcji.Decyzja wyboru działania MUSI być zapisana instrukcja switch

Page 7: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

WSKAŹNIKI I TABLICEJeśli mamy deklarację:int tab[100];to deklaruje ona tablicę o elementach tab[0],...,tab[99]Niech ta będzie wskaźnikiem do obiektów całkowitychint *ta;to wówczas instrukcjata=&tab[0];„ustawia” wskaźnik ta, aby wskazywał na pierwszy (tj. zerowy) elementtablicy. Jeśli x jest całkowite, to wtedy x=*ta „skopiuje” wartośćtab[0] do x. JEŚLI WIĘC ta wskazuje na tab[0], to ta+i wskazuje natab[i]. Zatem x=*(ta+i) jest równoważne x=tab[i].Kompilator zmienia odwołanie do tablicy na wskaźnik do jej początku.Skutkiem tego NAZWA tablicy jest „sama z siebie” wyrażeniem wskaźni-kowym. Ponieważ nazwa tablicy REPREZENTUJE położenie jej ele-mentu zerowego, to instrukcjeta=&tab[0]; oraz ta=tab; SĄ RÓWNOWAŻNE.

Page 8: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Dalej: Jeśli ta=&a[0] to (jak już wiemy) x=*(ta+i) oznacza, żex=a[i], ALE RÓWNIEŻ x=*(tab+i) oznacza x=a[i]! oraz, żeta=&a[i] (wskazanie na i-ty element tablicy) jest równoważne ta+i,tzn. „przesunięciu” wskaźnika!

PODSUMOWANIE: Nazwa tablicy (np. tab) to wskaźnik. Wyrażeniez tablicą i indeksem można zapisać za pomocą wskaźnika i przesunięcia i odwrotnie, nawet w tej samej instrukcji.

Ale istnieje istotna różnica pomiedzy nazwą tablicy a wskaźnikiem.Wskaźnik jest zmienną, a więc operacja np.. ta=a, ta++, ta*=a, itp.ma sens, natomiast instrukcje tab=a, tab++, tab*=a SĄ NIEDOZWOLONE

Page 9: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jeżeli nazwa tablicy to wskaźnik (do pierwszego elementu), a kolejneelementy tablicy wyznaczane są „przesuwaniem” wskaźnika, to deklarując tablice nie zawsze musimy podawać jej rozmiar. Dotyczyto funkcji (i procedur, o procedurach - później). Dla przykładu, funkcjaobliczająca długość łańcucha s:dlugosc(s);char s[]; /*nie podajemy wymiaru, jest on automatycznie dobierany */{ /* przy wywoływaniu */int k; /*deklarujemy zmienną do zliczania długości */ k=0; /*zerujemy zmienną */while(s[k++]) /*a to w istocie znaczy s[k++]!=0, czyli „jeśli s[k++] jest *//*prawdą, to pętla jest wykonywana, pamiętaj o różnicy k++ oraz ++k *//* w pierwszym przypadku najpierw dla k, potem zwiększamy o 1! */ ; /*instrukcja pusta, pętla while jest PUSTA */return(k-1); /*ale po zbadaniu warunku while wartość k zwiększyłasię o 1, musimy to skorygować */}Funkcje dlugosc wywolujemy np. i=dlugosc(lancuch), gdzie lancuch jest typem string

Page 10: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Zadanie 14Funkcję obliczającą długość łańcucha można również zapisać w postaci:dlugosc(s);char *s{ int n;for (n=0; *s!=‘\0’; s++)n++;return(n);}Zadanie polega na DOKŁADNYM opisie „co robią kolejne instrukcje” oraznapisaniu programu głównego, który będzie wywoływał funkcję dlugość.Należy też uzasadnić następujące stwierdzenie:definicje parametrów formalnych funkcji typu:char s[];orazchar *s;są całkowicie równoważne.

Page 11: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Aby mocniej podkreślić związek: wskaźniki<->tablice rozważmy funkcje,która kopiuje pierwszych n znaków łańcucha string na łańcuch substr

fun1(string,substr,n)char string[],substr[];int n;{ int i;for(i=0; i<n; i++)substr[i]=string[i];sub[i]=0;}

fun1(string,substr,n)char *string,*substr;int n;{ while(n--)*subsrt++=*string++; /*CO TO JEST?? */*sub=0;}

Obie funkcje są IDENTYCZNE. W pierwszej (po lewej) operujemy na elemen-tach tablic. W drugiej - na wskaźnikach. Co oznacza while(n--)? Jeśli w programie głównym chcemy wywołać funkcję kopiującą n znakówi „zabezpieczyć” się przed przypadkiem, w którym łańcuch string jest krótszyniż n, to możemy np. zastosować instrukcję: if(!fun1(string,substr,n))printf(“ nie mogę kopiowac\n”); Wytłumacz co te instrukcje znaczą.

Page 12: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Zadanie 15.Funkcja len(string) zwraca długość łańcucha. Posługując się podanymiprzykładami napisz analogiczne dwie funkcje kopiujące„od końca” n elementów łańcucha string na łańcuch substr

Oto funkcja len(s)len(s)char *s;{char *b;b=s;while(*s++);return(s-begin-1);}

Page 13: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

WSKAŹNIKI ZNAKOWE A FUNKCJEStała tekstowa “ala ma kota” jest tablicą znakową. Pamiętaj, że w repre-zentacji wewnętrznej kompilator “dopisuje” znak \0 . Długość tekstujest więc o 1 większa niż sam tekst. Znak \0 jest znakiem końca tekstu.W języku C nie istnieją operatory obsługi tekstów jako całość; nie ma też typu “pascalowskiego” string.

Jeżeli zmienna zdanie zadeklarowana jest jakochar *zdanie;to instrukcjazdanie= “ala ma kota”;przypisuje jej WSKAŹNIK do podanego tekstu. NIE jest to „kopiowanie”tekstu - zaangażowane są jedynie wskaźniki. Ponieważ zagadnienie tojest bardzo ważne dla zrozumienia języka, rozważmy jeszcze przykład:napiszemy funkcje kopiowania tekstu t na tekst s na różne sposoby

nie możemy napisac: char zdanie[13];zdanie= “ala ma kota”; DLACZEGO?

Page 14: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

copy(s,t)char s[],t[];{int i=0;while((s[i]=t[i])!=‘\0’)i++}

copy(s,t)char *s,*t;{int i=0;while((s[i]=t[i])!=‘\0’)i++}

to wersja „klasyczna” to wersja „wskaźnikowa” a to wersja „uproszczona wskaźnikowa”

copy(s,t)char *s,*t;{while((*s++=*t++)!=‘\ 0’);}

Page 15: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jeden z najczęściej czynionych błędów to przypisywanie wskaźników obiektom całkowitym. Pamiętaj:WSKAŹNIKI NIE SĄ (OGÓLNIE) OBIEKTAMI CAŁKOWITYMI

TABLICE WIELOWYMIAROWEnp.int tab[2][10]; definicja tablicy o elementach 00,01,02,03,...09,10,11,...19wywołanie: tab[i][j] gdzie 0<=i<=1;0<=i<=9.INACZEJ NIŻ W PASCALU, gdzie było: tab[i.j]!!! <- ŹLE W C!!Nadawanie wartości początkowej tablicy tab[2][10]:int tab[2][10]={{1,12,14,21,1,3,5,5,8,91},{2,15,21,28,3,5,2,1,1,100}};

Page 16: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

Jeśli tablica dwu (lub więcej) wymiarowa ma być przekazywanafunkcji to w deklaracji parametrów funkcji MUSIMY podać rozmiarkolumn, np. w main mamyfloat tab[3][100];i mamy funkcjef(tabela)to w deklaracji musi być lubfloat f(tabela) float(tabela)float tabela[3][100]; float tabela[][100];{ {ale NIE MOŻE BYĆfloat tabela [][]; !!!

to po prawej stronie może być również:float (*tabela)[100];ale NIE MOŻE BYĆ:float *tabela[100] !!!!

Nawias [] ma WYŻSZY priorytet niż *, a więc ostatnia instrukcja deklarujetabelę 100 wskaźników do float, a nie tabele [][100] !

Page 17: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

przykład funkcji, która z podania roku. miesiąca i dnia (np. 1977 3 13) wyznacza który był to dzień w rokuna począstku programu (zewnętrznie do funkcji) deklarujemystat int dni_miesiac[2][13]={ {0,31,28,31,30,31,30,31,31,3031,30,31}, {0,31,29,31,30,31,30,31,31,3031,30,31} };

dzien_roku(rok,miesiac,dz)int rok,miesiac,dz{int i,j;j=rok%4==0&&rok%100!=0||rok%400==0;/*czyli j=1 jeśli prawa strona jest prawdą (rok przestepny) i 0 jeśli fałsz*/for(i=1;i<month;i++)dz=dz+dni_miesiac[j][i];return(dz);}

Page 18: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

ZADANIE 16do wyboru: a lub ba) napisz funkcje, która na podstawie roku i numeru dnia w rokuwyznacza miesiąc i dzień miesiąca (tj. funkcje „odwrotną” doostatniego przykładu.

b) w szkole są klasy 1a, 1b,1c,2a,2b,3a,3b,3c,4a i 4b. Liczby uczniów w klasach wynoszą kolejno: 25,24,25,29,31,26,24,25,31,30 Zakładając, że spis uczniów w szkole sporządzony jest nastepująconajpiew wszyscy z 1a, numery od 1 do 25; nastepnie z 1b - numery od26 do 49, ..... itd., aż do klasy 4b, napisz program, który określi pod którym numerem w szkole jest np.. uczeń 20 z klasy 3c, itp..

Page 19: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

TABLICE WSKAŹNIKÓWpamiętamy o równoważności: tablica (jednowymiarowa) <-> wskaźnikzatem wskaźniki zebrane w tablicę jednowymiarową odpowiadajątablicy dwuwymiarowej. Jeśli mamy deklaracjeint a[10][10];int *b[10];to oba odwołania do elementów: a[5][5] oraz b[5][5] są poprawne. Różnica pomiędzy nimi jest analogiczna jak w przypadku nieindeksowanychwskaźników i tablic jednowymiarowych. Tablica*b[10] wprowadza 10wskażników; każdy z nich wskazuje na obiekt całkowity, na tablicę o elementach całkowitych. Jednak jedynie a[10][10] jest prawdziwą tablicą1oo-elementową: wszystkie komórki są dostępne w „tradycyjny” („pascalowski”) sposób.

Page 20: WSKAŹNIKI: Definicja:  Wskaźnik jest zmienna, która zawiera adres innej zmiennej

INICJOWANIE WSKAŹNIKÓW.przykład funkcji, która zwraca nazwę miesiąca na podstawie jego numeru (1 - styczeń, 2 - luty, itd.)char *nazwa_miesiaca(n)int n;{static char *name[]={ “zly miesiac”,”styczeń”,”luty”,”marzec”,kwiecień”,”maj”,”czerwiec”,“lipiec”,”wrzesien”,”pazdziernik”,”listopad”,”grudzień”};return((n<1||n>12))?name[0]:name[n]);}

ZADANIE 17Program z zadania 16a zmodyfiukuj tak, aby zamiast numeru miesiacapodawał jego nazwe