Lokalizacja plików do wykładów
http://members.lycos.co.uk/pkjw84/kw/
w folderze: Programowanie obiektowe IV ZIN
logowanie:
nazwa u\ytkownika 2007/2008
hasło kw
1
Programowanie obiektowe
Wykład 2: Wskaznikowe typy danych
Podstawy typów wskaznikowych
Operatory wskaznikowe
Tablice
Wskazniki a typy tablicowe i napisy
Struktury
2
Programowanie obiektowe
Podstawy typów wskaznikowych
Zmienna typu wskaznikowego (wskaznik) jest zmienną przechowującą
adres do innego obiektu (zmiennej) w pamięci operacyjnej
Wskazniki mają określoną specjalną arytmetykę wskazników, dzięki czemu
mo\na w stosunkowo łatwy sposób operować na adresach w pamięci
operacyjnej
Wskaznik Zmienna
Adres Wartość
3
Programowanie obiektowe
Wskazniki - podstawy
Deklaracja wskaznika:
typ *nazwa;
Przykłady:
int *wsk1;
char *wsk2;
4
Programowanie obiektowe
Operatory wskaznikowe: * oraz &
Jednoargumentowy operator & zwraca adres w pamięci
Operacja:
m = &count;
umieszcza w zmiennej m adres zmiennej count
Załó\my, \e zmienna count zajmuje komórkę pamięci o adresie 2000.
Załó\my, te\ \e jej wartość to 100
W wyniku powy\szego przypisania zmienna m będzie miała wartość
2000, tzn. zmienna m otrzymuje adres zmiennej count
5
Programowanie obiektowe
Operatory wskaznikowe: * oraz &
Jednoargumentowy operator * zwraca wartość zmiennej,
znajdującej się pod adresem następującym po operatorze
Jeśli zmienna m zawiera adres zmiennej count to instrukcja
q = *m;
umieszcza wartość zmiennej count w zmiennej q
Tak więc zmienna q będzie miała wartość 100, gdy\ 100 znajduje się
pod adresem 2000, który jest adresem zapisanym w m
q otrzymuje wartość, znajdującą się pod adresem m
6
Programowanie obiektowe
Wskazniki - podstawy
Zadanie
Napisać program wypisujący na ekranie liczbę 100 z u\yciem
wskaznika na liczbę typu int.
7
Programowanie obiektowe
Wskazniki - podstawy
Sposób 1
#include
using namespace std;
int main() {
int *p, q;
q = 100; /* przypisanie do q wartości 100 */
p = &q; /* przypisanie do p adresu q */
cout << *p; /* wyświetlenie wartości q z u\yciem wskaznika */
return 0;
}
8
Programowanie obiektowe
Wskazniki - podstawy
Sposób 2
#include
using namespace std;
int main()
{
int *p, q;
p = &q; /* pobranie adresu q */
*p = 100; /* przypisanie wartości q z wykorzystaniem wskaznika */
cout << 3 3
3 Wartością zmiennej q jest 3 << q;
3 3
3 3
return 0;
}
9
Programowanie obiektowe
Wskazniki - podstawy
Przykład niepoprawnego wykorzystania wskaznika
int main(void)
{
int *p;
/* niepoprawnie - p jeszcze na nic nie wskazuje! */
*p = 10;
}
10
Programowanie obiektowe
Wskazniki - podstawy
Oprócz operatorów * i & istnieją tylko cztery inne operatory,
które mo\na stosować ze wskaznikami: +, ++, -, --.
Operator ++ zwiększa adres, na który wskazuje wskaznik o jedną długość
typu wskaznika;
np. je\eli p zawiera adres 200 do liczby całkowitej (o długości 2 bajtów),
to instrukcja p++ powoduje, \e p będzie miało adres 202, tzn. 200+(1*2).
Równowa\nie mo\na to zapisać: p+=1;
Je\eli mamy:
int *p;
p=p+200;
to p będzie wskazywało na 200. liczbę całkowitą, występująca za liczbą
wskazywaną poprzednio.
Podobnie działają operatory odejmowania.
11
Programowanie obiektowe
Wskazniki - podstawy
Aby otrzymać wartość o jeden większą od wskazywanej przez wskaznik,
nale\y posłu\yć się konstrukcją:
(*p)++;
(Je\eli zało\ymy, \e p wskazuje na adres 200, pod którym znajduje się
liczba 100 typu int, to po wykonaniu ww. instrukcji p wskazuje na liczbę
101 nadal pod adresem 200).
UWAGA!
Instrukcja:
*p++;
powoduje zwiększenia wskaznika p o 1 (a nie wartości obiektu, na który
wskazuje!!!), tzn. p wskazuje na adres 202 (zakładamy, \e liczba typu int
zajmuje 2 bajty).
12
Programowanie obiektowe
Rzutowanie typów
Aby rzutować zmienną t typu T na inny typ S, poprzedzamy t nazwą
typu S ujętą w nawias.
Przykład
float f;
f=100.2;
cout << (int) f; /*wyświetlenie f jako liczby całkowitej */
13
Programowanie obiektowe
Rzutowanie typów
Ta sama zasada dotyczy rzutowania wskazników
Załó\my, \e mamy:
int *iptr;
float *fptr;
Aby przypisać wskaznik do liczby całkowitej iptr wskaznikowi do liczby
zmiennoprzecinkowej fptr, piszemy:
fptr=(float *) iptr;
14
Programowanie obiektowe
Wskazniki a typy tablicowe
Język C/C++ w sposób wyjątkowy łączy wskazniki i tablice
W wyniku deklaracji zmiennej tablicowej, środowisko języka C/C++
tworzy wskaznik na początek tej tablicy. Miejsca na pozostałe
elementy tablicy są zajmowane w zale\ności od rozmiaru tablicy.
Tablica zajmuje spójny obszar pamięci operacyjnej
Tak więc do tablic mo\emy odnosić się w sposób tradycyjny, tzn.
przy pomocy nazwy zmiennej z indeksem tablicy: tab[i] lub
stosując arytmetykę wskazników
Takie traktowanie tablic jest szczególnie przydatne dla tzw. tablic
otwartych i łańcuchów znaków - bez wstępnego określenia ich
długości
Takich cech nie ma większość innych języków programowania
15
Programowanie obiektowe
Wskazniki i tablice
Niech:
int sample[10];
Mo\na utworzyć wskaznik do pierwszego elementu, u\ywając nazwy
sample
Poni\szy fragment programu przypisuje zmiennej p adres
pierwszego elementu tablicy sample:
int *p;
int sample[10];
p = sample;
Równowa\ne są równie\ odwołania:
sample[i] oraz *(sample+i)
16
Programowanie obiektowe
Wskazniki i tablice
Nazwa tablicy bez indeksu jest wskaznikiem do początku
tablicy
Przeanalizujmy poni\szy przykład
#include
using namespace std;
int main() {
int a[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *p;
p = a; /* przypisanie p adresu początkowego tablicy a */
/* wypisanie pierwszych trzech elementów tablicy a z u\yciem p */
cout << *p << *(p+1) << *(p+2);
/* to samo z wykorzystaniem a */
cout << a[0] << a[1] << a[2];
return 0;
}
17
Programowanie obiektowe
Wskazniki i tablice
Zadanie
Jaka wartość zostanie wypisana na ekranie?
int temp[5] = {10, 19, 23, 8, 9};
int *p;
p = temp;
Cout << *(p+3);
Odpowiedz: 8
18
Programowanie obiektowe
Wskazniki i tablice
Zadanie
Napisać program wczytujący napis jako łańcuch znaków. Następnie
program powinien odszukać pierwszy ciąg spacji w łańcuchu,
po czym wyświetlić pozostałą część napisu.
Wykorzystać zmienne wskaznikowe.
19
Programowanie obiektowe
Wskazniki i tablice
#include
using namespace std;
int main(void)
{
char str[80], *p;
cout << "Wprowadz lancuch znakow: ";
gets(str);
p = str;
while(*p && *p!=' ') p++;
while(*p && *p==' ') p++;
cout << p;
getchar();
return 0; Program 2.1
}
20
Programowanie obiektowe
Wskazniki wielokrotne
Mo\liwe jest, aby wskaznik wskazywał na inny wskaznik
(tzw. wielokrotne odwołanie niejawne).
Wskaznik Wskaznik
Zmienna
do wskaznika
Adres Wartość
Adres
Aby zadeklarować wskaznik do wskaznika, nale\y przed
nazwą wskaznika umieścić dodatkową gwiazdkę:
char **mp;
char **mp;
21
Programowanie obiektowe
Wskazniki wielokrotne
Aby dostać się do wartości wskazywanej niejawnie przez
wskaznik do wskaznika, nale\y zastosować operator *
dwukrotnie:
char **mp, *p, ch;
p=&ch; // pobranie adresu ch
mp=&p; // pobranie adresu p
/* przypisanie ch wartości A z wykorzystaniem wielokrotnego
odwołania niejawnego */
**mp= A ;
22
Programowanie obiektowe
Arytmetyka wskazników
Przeanalizuj i wyjaśnij poni\szy kod:
int x=1, y, z[10];
int *ip, *iq;
// ip wskazuje na x
ip = &x;
y = *ip;
// y=1
*ip = 0; // x=0
// x=1
*ip += 1;
y = *ip+2;
// y=3
ip = &z[0]; // ip wskazuje na z[0]
iq = ip;
// iq wskazuje na z[0]
23
Programowanie obiektowe
Arytmetyka wskazników
Przykład operacji dla typu prostego:
int *px;
px += 2;
px = (adres wskazywany przez px) + (2 * rozmiar obiektu
wskazywanego przez px);
np. dla px równego 3000 i rozmiaru 4 (dla int):
3000 + 2 * 4 = 3008;
3012
3008
3004
3000
pa
Przykład dla tablicy:
int a[4];
a[0] a[1] a[2] a[3]
int *pa;
pa = a; /* lub pa=&a[0]; */
pa ++; /*pa wskazuje na a[1] */
pa = pa+2; /*pa wskazuje na a[3] */
pa --; /*pa wskazuje na a[2] */
24
Programowanie obiektowe
Wprowadzenie do języka C++
Dynamiczny przydział pamięci (alokacja):
operator new
np.
int *point;
point = new int;
*point = 999;
25
Programowanie obiektowe
Wprowadzenie do języka C++
Dynamiczne zwolnienie pamięci:
operator delete
np.
delete point;
usuwanie tablicy zaalokowanej dynamicznie:
/* new tab[2]; */
delete [ ] tab;
26
Programowanie obiektowe
Tablice sekwencyjne
W językach programowania przez tablicę rozumie się ciąg wartości
(np. liczb, znaków, innych typów prawidłowych dla kompilatora),
będących tego samego typu,
Pojedyncza zmienna w tablicy nazywana jest elementem tablicy,
Do wszystkich zmiennych w tablicy odwołujemy się poprzez tę samą
nazwę wykorzystując indeks elementu tablicy,
Indeks tablicy budowany jest na podstawie typu wyliczeniowego -
najczęściej są to liczby naturalne z zerem (0) włącznie,
Są języki programowania (np. Pascal), w których indeksy mogą być znakami
ASCII lub własnymi typami wyliczeniowymi,
W języku C/C++ domyślnym indeksem tablicy są liczby naturalne
z zerem
27
Programowanie obiektowe
Deklarowanie tablic jednowymiarowych (wektorów)
W języku C/C++ tablice jednowymiarowe deklarujemy według schematu:
typ_elementów nazwa_tablicy [rozmiar]
ka\dy z elementów tablicy dostęp do ka\dego
rozmiar podawany jest
jest typu typ_elementów z elementów tablicy
jako liczba naturalna w otoczeniu
jest realizowany
nawiasów kwadratowych
poprzez jej nazwę
Zmienne i stałe typu tablicowego deklarujemy w części
deklaracyjnej programu C/C++ jest liczony od zera do wartości
rozmiar-1
28
Programowanie obiektowe
Tablice jednowymiarowe
Przykład: deklaracja pięciopozycyjnej tablicy liczb całkowitych:
int tab[5];
Po wykonaniu powy\szej deklaracji powstaje w pamięci
operacyjnej następująca struktura danych:
tab[0] tab[1] tab[2] tab[3] tab[4]
spójny obszar pamięci operacyjnej
najmłodszy adres najstarszy adres
29
Programowanie obiektowe
Tablice jednowymiarowe
Wypełnienie tablicy z wykorzystanie pętli for :
int tab[5];
int j;
for (j=0; j<5; j++)
{
tab [ j ] = j; /* podstawienie wartości do elementu tablicy */
}
Po wykonaniu powy\szych działań otrzymujemy:
tab[0] tab[1] tab[2] tab[3] tab[4]
0 1 2 3 4
30
Programowanie obiektowe
Tablice jednowymiarowe
Przykład: Wczytanie elementów do tablicy i wypisanie ich na ekranie:
#include
using namespace std;
int moja_tab[5];
int j;
int main( ) {
for (j=0; j<5; j++)
{
/*wczytanie elementu do tablicy*/
cout << endl << "Wprowadz element na pozycje " << j << endl;
cin >> moja_tab[j];
/* wypisanie elementu z opisem i nową linią*/
cout << "moja_tab[" << j << "] = " << moja_tab[j];
}
getchar();
Program 2.2
return 0;
}
31
Programowanie obiektowe
Inicjowanie wartości elementów tablic
Tablicę mo\na zainicjować przy pomocy pętli, np.: for
Mo\na równie\ wczytać wartości elementów przy pomocy funkcji
scanf
Zainicjowanie wartości tablicy w postaci wyliczenia listy wartości:
typ_elementów nazwa_tablicy [rozmiar] = {lista_wartości}
Przykład:
char znaki[5] = { A , B , C , D , E }
znaki[0] znaki[1] znaki[2] znaki[3] znaki[4]
A B C D E
32
Programowanie obiektowe
Inicjowanie wartości elementów tablic
Nie nale\y polegać na wartościach inicjalizacyjnych tablic. Mo\e to być
ró\nie realizowane dla poszczególnych środowisk języka C i dla ró\nych
systemów operacyjnych. Dlatego te\ w dobrym zwyczaju le\y jawne
wypełnienie tablicy wartościami początkowymi, na przykład z
wykorzystaniem pętli for :
int tab[100];
int j;
for (j=0; j<100; j++)
{
tab[ j ] = 0; /* wyzerowanie tablicy */
}
tab[0] tab[1] tab[2] tab[99]
......................
Po wykonaniu zerowania:
0 0 0 0
33
Programowanie obiektowe
Wykorzystywanie tablic otwartych
Je\eli z góry nie zakładamy ile elementów ma mieć tablica, to
mo\emy u\yć deklaracji tzw. tablicy otwartej:
typ_elementów nazwa_tablicy [ ] = {lista_wartości}
Rozmiar tablicy nie jest podawany wprost.
Faktyczny rozmiar tablicy jest wyliczany przez
środowisko języka C na podstawie liczby elementów
zamieszczonych na liście wartości wprowadzanych do tablicy
Przykłady:
int całkowite[ ] = {1, 4, 6, -8, 3, -56, 19, 27, -13};
float rzeczywiste[ ] = {-12.23, 45.0, 1.4};
unsigned int naturalne[ ] = {0, 2, 8, 9, 23, 90, 100, 234};
Program 2.3
34
Programowanie obiektowe
Przepisywanie zawartości z tablicy do innej tablicy
Aby przepisać zawartość jednej tablicy do innej tablicy musimy
przepisać kolejno jej poszczególne elementy
DOZWOLONY SPOSÓB PRZEPISYWANIA WARTOŚCI:
int zródło[5] = {0, 1, 2, 3, 4}
int wynik[5];
int i;
for (i=0; i<5; i++)
{
wynik[i] = zródło[i]; /*przepisywanie pojedynczych elementów*/
}
NIEDOZWOLONY SPOSÓB:
wynik = zródło; /*nieprawidłowa próba u\ycia nazwy całej tablicy*/
35
Programowanie obiektowe
Przykłady wykorzystania tablic jednowymiarowych
Wyliczenie wartości średniej elementów tablicy
Program 2.4
Wykorzystanie nieskończonej pętli for
Program 2.5
36
Programowanie obiektowe
Tablice wielowymiarowe
W języku C tablice wielowymiarowe deklarujemy według schematu:
typ_elementów nazwa_tablicy [wymiar1]...[wymiarN]
ka\dy z elementów tablicy
dostęp do ka\dego
ka\dy z wymiarów podawany jest
jest typu typ_elementów
z elementów tablicy
jako liczba naturalna w
jest realizowany
nawiasach kwadratowych
poprzez jej nazwę
Przykład: deklaracja dwuwymiarowej tablicy (macierzy) liczb rzeczywistych:
float macierz [4][3];
indeks
indeks
kolumny
wiersza
37
Programowanie obiektowe
Inicjowanie wartości elementów macierzy
Przy pomocy podwójnej pętli for :
0 1 2
float macierz_R[4][3]
0.0 0.0 0.0
0
int i, j;
0.0 0.0 0.0
for(i=0; i<4; i++) { 1
for (j=0; j<3; j++) {
0.0 0.0
0.0
2
macierz_R[i][j] = 0.0;
0.0 0.0
0.0
3
}
}
38
Programowanie obiektowe
Inicjowanie wartości elementów macierzy
Jawnie ustalając listę wartości:
float macierz_R[4][3]=
{
0.0 0.0 0.0
0
0.0, 0.0, 0.0,
0.2 1.23 2.12
1
0.2, 1.23, 2.12,
3.45 7.23
1.12
2
1.12, 3.45, 7.23,
5.0 8.7
3.2
3.2, 5.0, 8.7 3
};
39
Programowanie obiektowe
Inicjowanie wartości elementów macierzy
Selektywnie wstawianie wartości do tablicy:
12.5
0
macierz_R[2][2] = 1.0;
1
macierz_R[0][2] = 12.5;
1.0
macierz_R[3][1] = 4.78;
2
4.78
3
40
Programowanie obiektowe
Przykład wykorzystania tablicy dwuwymiarowej
W poni\szym przykładzie do macierzy liczb całkowitych wstawiana jest, a
następnie wypisywana wartość iloczynu indeksów wierszy i kolumn
poszczególnych elementów macierzy:
#include
using namespace std;
int macierz[4][5]; Wynik zadziałania programu:
int i,j;
int main() { 0 0 0 0 0
for(i=0; i<4; i++) 0 1 2 3 4
for(j=0; j<5; j++) 0 2 4 6 8
macierz[i][j] = i*j; 0 3 6 9 12
for(i=0; i<4; i++) {
for(j=0; j<5; j++)
cout << macierz[i][j];
cout << endl;
}
Program 2.6
getchar();
return 0;
}
41
Programowanie obiektowe
Typy rekordowe - struktury
Do tej pory poznaliśmy ju\ typy tablicowe, które są zło\onymi
typami danych
Charakterystyczne dla tablicy jest to, \e ka\dy element jest tego
samego typu; mogą to być na przykład tablice liczb całkowitych,
rzeczywistych, znaków ASCII itd.
Nie mo\emy mieć natomiast tablicy, w której występują elementy
ró\nych typów
Nowe mo\liwości w tym zakresie stwarzają tzw. struktury
Struktura jest konglomeratem typów danych i składa się z kilku
związanych zmiennych, nazywanych składowymi
W przeciwieństwie do tablic, gdzie wszystkie elementy są tego
samego typu, ka\da składowa struktury mo\e mieć własny typ,
ró\ny od typów innych składowych
42
Programowanie obiektowe
Struktury
Przykład: dane osobowe
Imię tekst do 25 znaków
Nazwisko tekst do 35 znaków
PESEL tekst 11 znakowy
Wiek unsigned int
Wzrost unsigned int
Płeć char
Składowe stanowią jedną, logiczną całość
43
Programowanie obiektowe
Struktury
Schemat definicji typu strukturowego:
struct nazwa_rekordu {
Typ1 pole1;
Typ2 pole2;
Typ3 pole3;
Pola w strukturze mogą
mieć ró\ne typy danych
& & & &
& & & ...
TypN poleN;
} nazwa_zmiennej1, nazwa_zmiennej2, & ;
44
Programowanie obiektowe
Struktury
Zdefiniujmy trzy zmienne strukturowe przechowujące dane
osobowe:
struct osoba {
Polami struktury mogą
char imie[25];
być tablice
char nazwisko[35];
char PESEL[11];
Albo zmienne typu
unsigned int wiek;
prostego
unsigned int wzrost;
char plec;
} Osoba1, Osoba2, Osoba3;
Trzy zmienne
strukturowe
45
Programowanie obiektowe
Struktury
A zatem mamy trzy zmienne strukturowe o nazwach: Osoba1,
Osoba2, Osoba3, które będą przechowywały informacje o
trzech ró\nych osobach
Zapiszemy dane Osoby1:
Osoba1.imie = Franciszek ;
Osoba1.nazwisko = Abacki ;
Osoba1.PESEL = 54061201254 ;
Osoba1.wiek = 49;
Osoba1.wzrost = 175;
Osoba1.plec = M ;
Uwaga na KROPK jest bardzo wa\na !!!!!!
Oddziela nazwę zmiennej strukturowej od nazwy jej pola
46
Programowanie obiektowe
Struktury zagnie\d\one w strukturach
Załó\my, \e chcemy dodatkowo przechowywać dane
adresowe dla ka\dej osoby. Definicja struktury dla adresu
mo\e być następująca:
Struct dane_adresowe {
Char ulica[40];
Char dom[4], lokal[4];
Char kod_p[6];
Char miejscowość[30];
};
W jaki sposób dołączyć dane_adresowe do definicji struktury
dla danych osobowych?
47
Programowanie obiektowe
Struktury zagnie\d\one w strukturach
Po prostu jako jedno z pól struktury nale\y zdefiniować pole
zdefiniowane jako dane_adresowe:
struct osoba {
Pole strukturowe,
char imie[25];
zagnie\d\one wewnątrz
char nazwisko[35];
struktury
char PESEL[11];
Struktura dane_adresowe
unsigned int wiek;
została zdefiniowana
unsigned int wzrost;
wcześniej
char plec;
struct dane_adresowe adres;
} Osoba1, Osoba2, Osoba3;
48
Programowanie obiektowe
Struktury zagnie\d\one w strukturach
Jak zapisać informacje o tym, \e Osoba1 mieszka w
Warszawie, Osoba2 w Krakowie, a Osoba3 w Olsztynie?
Mo\na to zrobić tak, jak przedstawiono poni\ej:
Osoba1.adres.miejscowość= Warszawa ;
Osoba2.adres.miejscowość= Kraków ;
Osoba3.adres.miejscowość= Olsztyn ;
Mo\na równie\ wczytać dowolną nazwę z klawiatury,np.:
gets(Osoba3.adres.miejscowość);
Kolejne kropki wskazują na kolejne poziomy
zagnie\d\eń struktury
49
Programowanie obiektowe
Wskazniki do struktur
Mo\emy definiować równie\ wskazniki do struktur, np.:
struct osoba *wsk_osoba
Wówczas do pól struktury dostajemy się wykorzystując
zamiast kropki tzw. operator strzałkowy, np.:
wsk_osoba -> imie = Anna ;
Pozostałe reguły pracy ze zmiennymi strukturowymi nie
ulegają zmianie
Przykład u\ycia wskazników do struktur
Program 2.7
50
Programowanie obiektowe
51
Programowanie obiektowe
Wyszukiwarka
Podobne podstrony:
PO W4 IV ZIN
PO W3 IV ZIN
PO W3 II ZIN
PO W1 2 II ZIN
PO W3 II ZIN
sprawdzian wiadomosci z jezyka angielskiego po klasie iv
PO W7 8 II ZIN
PO W4 II ZIN
Wędrówka po Helladzie ( księgi IV V ) Pauzaniasz
Learning Italian Ebook cz IV (po angielsku)
PO W 5 6 II ZIN
w2 ruch po okr
Ilustrowany przewodnik po zabytkach kultury na Ukrainie T IV
Rozgrzewka po kwadracie – cz 2
więcej podobnych podstron