Wykład 11.

Transkrypt

Wykład 11.
Tablice i wskaźniki
Elwira Wachowicz
[email protected]
29 maja 2013
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
1 / 12
/* binar.c -- wyświetla liczbę w systemie dwójkowym */
#include <stdio.h>
void do_binar(int);
int main(void)
{
int liczba;
printf("podaj liczbę całkowitą (q kończy program): \n");
while ( scanf("%d", &liczba) == 1 )
{
printf("W systemie dwójkowym: ");
do_binar(liczba);
putchar(’\n’);
printf("podaj liczbę całkowitą (q kończy program): \n");
}
return 0;
}
void do_binar(int n)
{
int r;
/* funkcja rekurencyjna
*/
r = n % 2;
if ( n >= 2)
do_binar( n / 2 );
putchar(’0’ + r);
return;
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
podaj liczbę całkowitą (q kończy program):
9
W systemie dwójkowym: 1001
podaj liczbę całkowitą (q kończy program):
255
W systemie dwójkowym: 11111111
podaj liczbę całkowitą (q kończy program):
1024
W systemie dwójkowym: 10000000000
podaj liczbę całkowitą (q kończy program):
q
29 maja 2013
2 / 12
Tablice
Tablica:
ciąg wartości tego samego typu (np. dziesięciu znaków lub piętnastu liczb typu int)
przechowywanych obok siebie. Cała tablica nosi jedną nazwę, a dostęp do
poszczególnych elementów uzyskujemy przez podanie indeksu, który zawsze jest liczbą
naturalną.
float dlugi[20] – 20-elementowa tablica o nazwie dlugi
dlugi[0] – wartość pierwszego elementu tablicy dlugi
...
dlugi[19] – wartość dwudziestego elementu tablicy dlugi
Przypisywanie wartości:
dlugi[5] = 32.54;
dlugi[6] = 1.2e+21;
int nianie[22];
char aktorzy[26];
long duzy[500];
/* tablica z 22. liczbami typu int
*/
/* tablica przechowująca 26 znaków
*/
/* tablica z 500. liczbami typu long int */
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
3 / 12
/* wyniki.c -- wykorzystuje pętle do przetwarzania tablicy */
#include <stdio.h>
#define ROZMIAR 10
#define PAR
72
int main(void)
{
int index, wynik[ROZMIAR];
int suma = 0;
float srednia;
printf("Podaj %d wyników gry w golfa:\n", ROZMIAR);
for (index = 0; index < ROZMIAR; index++)
scanf("%d", &wynik[index]);
/* wczytanie 10 wyników
*/
printf("Odczytane wyniki to:\n");
for (index = 0; index < ROZMIAR; index++)
printf("%5d", wynik[index]);
/* wyświetlenie wczytanych wyników */
printf("\n");
for (index = 0; index < ROZMIAR; index++)
suma += wynik[index];
/* i ich zsumowanie
*/
srednia = (float) suma / ROZMIAR;
printf("Suma wyników = %d, średnia = %.2f.\n", suma, srednia);
printf("Oznacza to handicap w wysokości %.0f.\n", srednia - PAR);
}
Podaj 10 wyników gry w golfa:
102 98 112 108 105 103 99 101 96 102 100
Odczytane wyniki to:
102
98 112 108 105 103
99 101
Suma wyników = 1026, średnia = 102.60.
Oznacza to handicap w wysokości 31.
Elwira Wachowicz ([email protected])
96
102
Tablice i wskaźniki
29 maja 2013
4 / 12
Zmienne lub tablice automatyczne
Zmienna lub tablica automatyczna:
to zmienna lub tablica zadeklarowana wewnątrz funkcji. Zmienna
zadeklarowana wewnątrz istnieje tylko w czasie działania funkcji – po
zakończeniu działania funkcji pamięć przeznaczona na zmienną jest
zwalniana.
int main(void)
{
int potegi[8] = {1, 2, 4, 8, 16, 32, 64, 128};
...
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
5 / 12
Zmienne i tablice zewnętrzne
Zmienna lub tablica zewnętrzna:
to zmienna lub tablica zadeklarowana poza jakąkolwiek funkcją.
Są znane wszystkim funkcjom, które występują po ich deklaracji w
pliku źródłowym.
Istnieją przez cały czas działania programu.
Są standardowo inicjalizowane i przyjmują wartość 0.
int raport;
int wilki[5] = {12, 10, 8, 9, 6};
int jedzenie(int);
int main(void)
{
...
}
int jedzenie(int n)
{
...
} Wachowicz ([email protected])
Elwira
Tablice i wskaźniki
29 maja 2013
6 / 12
Zmienne i tablice statyczne
Zmienne i tablice statyczne:
definiuje się wewnątrz funkcji korzystając ze słowa kluczowego static. Są
lokalne wewnątrz funkcji, ale zachowują swoje wartości między
wywołaniami funkcji i otrzymują wartość początkową 0.
int konto(intn, int m)
{
static int fasola[2] = {343, 332};
...
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
7 / 12
/* brak_dan.c -- niezainicjalizowane tablice */
#include <stdio.h>
#define ROZMIAR 4
int zewntab[ROZMIAR];
/* niezainicjalizowana tablica zewnętrzna */
int main(void)
{
static int statab[ROZMIAR]; /* niezainicjalizowana tablica statyczna */
int autab[ROZMIAR];
/* niezainicjalizowana tablica automatyczna */
int i;
printf("%2s%10s%10s%10s\n",
"i","zewntab","statab","autab");
for (i = 0; i < ROZMIAR; i++)
printf("%2d%10d%10d%10d\n", i, zewntab[i],
statab[i], autab[i]);
return 0;
}
i
0
1
2
3
zewntab
0
0
0
0
statab
0
0
0
0
autab
0
0
4195344
0
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
8 / 12
/* troche_dan.c -- częściowo zainicjalizowane tablice */
#include <stdio.h>
#define ROZMIAR 4
int zewntab[ROZMIAR] = {1956, 1966};
int main(void)
{
static int statab[ROZMIAR] = {-50, -90};
int autab[ROZMIAR] = {492, 567};
int i;
printf("%2s%10s%10s%10s\n",
"i","zewntab","statab","autab");
for (i = 0; i < ROZMIAR; i++)
printf("%2d%10d%10d%10d\n", i, zewntab[i],
statab[i], autab[i]);
return 0;
}
i
0
1
2
3
zewntab
1956
1966
0
0
statab
-50
-90
0
0
Elwira Wachowicz ([email protected])
autab
492
567
0
0
Tablice i wskaźniki
29 maja 2013
9 / 12
Przypisywanie wartości do tablic
Przypisywanie wartości następuje element po elemencie!
/* nieprawidlowe przypisania */
#define ROZMIAR 5
int main(void)
{
int byki[ROZMIAR] = {5, 3, 2, 8};
int jaki[ROZMIAR];
/* w porządku
jaki = byki;
jaki[ROZMIAR] = byki[ROZMIAR];
jaki[ROZMIAR] = {5, 3, 2, 8};
*/
/* niedozwolone
/* nieprawidlowa
/* niedopuszczalna
*/
*/
*/
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
10 / 12
Wskaźniki
Wskaźnik:
zmienna, której wartość jest adresem w pamięci.
wsk = &ach;
/* przypisuje zmiennej wsk adrese zmiennej ach */
Mówimy: wsk wskazuje na ach
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
11 / 12
Operator dereferencji (pośredniości): *
wsk = &ach;
wart = *wsk;
/* przypisuje zmiennej wsk adrese zmiennej ach */
/* znajduje wartość, na którą wskazuje wsk
*/
Powyższe dwie instrukcje są równoważne:
wart = ach;
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
12 / 12
Deklarowanie wskaźników
Prawidłowa deklaracja wskaźnika:
int * pi;
char * pc;
float * pf, * pq;
/* pi jest wskaźnikiem do zmiennej całkowitej
*/
/* pc jest wskaźnikiem do zmiennej znakowej
*/
/* pf i pg są wskaźnikami do zmiennej typu float */
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
13 / 12
/* zamien.c -- zamiana z wykorzystaniem wskaźników
#include <stdio.h>
void zamiana(int * u, int * v);
int main(void)
{
int x = 5, y = 10;
*/
printf("Początkowo x = %d, a y = %d.\n", x, y);
zamiana(&x, &y);
/* wysyłanie adresów do funkcji */
printf("A teraz x = %d, a y = %d.\n", x, y);
return 0;
}
void zamiana(int * u, int * v)
{
int temp;
temp = *u;
*u = *v;
*v = temp;
/* temp otrzymuje wartość, na którą wskazuje u */
}
Dostajemy:
Początkowo x = 5, a y = 10.
A teraz x = 10, a y = 5.
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
14 / 12
Operatory związane ze wskaźnikami – podsumowanie
Operator adresu &: pozwala uzyskać adres zmiennej, której nazwa po nim występuje.
Przykład:
&siostra jest adresem zmiennej siostra.
Operator deferencji *: zwraca wartość przechowywaną pod adresem wskazanym przez zmienną
wskaźnikową.
Przykład:
siostra = 22;
wsk = &siostra;
wart = * wsk;
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
15 / 12
/* wsk_dod.c -- dodawanie do wskaźników
#include <stdio.h>
#define ROZMIAR 4
int main(void)
{
short daty[ROZMIAR], * ptc, index;
double oplaty[ROZMIAR], * ptz;
*/
ptc = daty;
/* przypisuje adres tablicy wskaźnikowej
ptz = oplaty;
printf("%25s %10s\n", "short", "double");
for (index = 0; index < ROZMIAR; index++)
printf("wskaźniki + %d: %10p %10p\n",
index, ptc + index, ptz + index);
return 0;
*/
}
Dostajemy:
wskaźniki
wskaźniki
wskaźniki
wskaźniki
+
+
+
+
0:
1:
2:
3:
short
0x7fff1f922f40
0x7fff1f922f42
0x7fff1f922f44
0x7fff1f922f46
Elwira Wachowicz ([email protected])
double
0x7fff1f922f20
0x7fff1f922f28
0x7fff1f922f30
0x7fff1f922f38
Tablice i wskaźniki
29 maja 2013
16 / 12
wskaźniki
wskaźniki
wskaźniki
wskaźniki
+
+
+
+
0:
1:
2:
3:
short
0x7fff1f922f40
0x7fff1f922f42
0x7fff1f922f44
0x7fff1f922f46
Elwira Wachowicz ([email protected])
double
0x7fff1f922f20
0x7fff1f922f28
0x7fff1f922f30
0x7fff1f922f38
Tablice i wskaźniki
29 maja 2013
17 / 12
Wskaźniki do tablic
Nazwa tablicy jest zarazem adresem jej pierwszego elementu: domek == &domek[0]
Wartością wskaźnika jest adres wskazywanego elementu – sposób reprezentacji zależy od
platformy sprzętowej. PC: adresowanie bajtowe. Adres dużego obiektu, to adres
pierwszego bajtu.
Zastosowanie do wskaźnika operatora *, daje wartość wskazywanego obiektu.
Dodanie 1 do wskaźnika zwiększa jego wartość o rozmiar (w bajtach) wskazywanego
obiektu.
daty + 2 == &daty[2]
*(daty + 2) == daty[2]
*daty + 2
/* ten sam adres */
/* ta sama wartość */
/* 2 dodane do wartości 1. elementu */
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
18 / 12
/* dni_m.c -- wykorzystuje zapis wskaźnikowy */
#include <stdio.h>
#define MIESIACE 12
int main(void)
{
int dni[MIESIACE] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int index;
for (index = 0; index < MIESIACE; index++)
printf("Miesiąc %d ma %d dni.\n", index + 1,
*(dni + index));
// równoważne dni(index)
return 0;
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
19 / 12
Tablice wielowymiarowe
int M[4][5] – dwuwymiarowa macierz zmiennych całkowitych o 4 wierszach i 5
kolumnach.
Inicjalizacja tablicy dwuwymiarowej:
int M[4][5] = {
{10, 5, -3, 17, 82},
{ 9, 0, 0, 8, -7},
{32, 20, 1, 0, 14},
{ 0, 0, 8, 7, 6}
};
int M[4][5] = { 10,
20,
5, -3, 17, 82,
1, 0, 14, 0,
9,
0,
0,
8,
0,
7,
8, -7,
6};
32,
int macierz[4][3] = { [0][0] = 1, [1][1] = 5, [2][2] = 9};
Macierz trójwymiarowa:
int pudelko[10][20][30];
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
20 / 12
/* podwtab.c -- podwaja elementy tablicy
#include <stdio.h>
void podwoj(int tab[], int rozmiar);
int main(void)
{
int smieci[3][4] = {
{2, 4, 5, 8},
{3, 5, 6, 9},
{12, 10, 8, 6}
};
int i, j; \begin{columns}
*/
for(i = 0; i < 3; i++)
podwoj(smieci[i], 4);
4
6
24
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
printf("%5d", smieci[i][j]);
putchar(’\n’);
}
return 0;
}
void podwoj(int tab[], int rozmiar)
{
int i;
/* lub int * tab
8
10
20
10
12
16
16
18
12
*/
for(i = 0; i < rozmiar; i++)
tab[i] *= 2;
}
Elwira Wachowicz ([email protected])
Tablice i wskaźniki
29 maja 2013
21 / 12

Podobne dokumenty