c cxx w09

background image

Podstawy programowania

Podstawy programowania

w j

w języku C++

ęzyku C++

Tablice a zmienne wskaźnikowe

Część dziewiąta

Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa.

Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne.

Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione.

Roman Simiński

roman.siminski@us.edu.pl
www.us.edu.pl/~siminski

Autor

Kontakt

background image

Nazwa tablicy jako wskaźnik na jej początek

Nazwa tablicy jako wskaźnik na jej początek

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

2

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Nazwa tablicy jest interpretowana jako ustalony wskaźnik na jej początek
(pierwszy element).

int tab[ 10 ];

0

1

2

3

4

5

tab

6

7

8

9

10 elementów

Pierwszy element: tab[ 0 ]

background image

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

3

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

int tab[ 10 ];
int * p;
. . .

p = tab

;

0

1

2

3

4

5

tab

6

7

8

9

10 elementów

Pierwszy element: tab[ 0 ]

p

Przypisanie:

Jest równoznaczne z:

p = tab;

p = &tab[ 0 ];

background image

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

4

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

tab[ 0 ] = 5;
tab[ 1 ] = 1;
tab[ 2 ] = 10;
. . .
tab[ i ] = 22;

0

1

2

3

i

tab

8

9

p + 0

*p = 5
*( p + 1 ) = 1
*( p + 2 ) = 10
. . .
*( p + i ) = 22

p + 1

p + 2

p + 3

p + i

p

Odwołania równoważne

background image

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

5

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Nazwa tablicy z
indeksem

0

1

2

3

i

tab

8

9

Wska nik z

ź

przesuni ciem

ę

p

Odwołania równoważne

Odwołanie:

tab[ i ]

Odwołanie:

*( p + i )

background image

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Nazwa tablicy jako wskaźnik na jej początek, cd. ...

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

6

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Wyrażenie p + i jest wyrażeniem wskaźnikowym, wskazuje ono na obiekt oddalony
o i obiektów danego typu od p.

Wartość dodawana do wskaźnika jest skalowana rozmiarem typu obiektu
wskazywanego
.

Każde odwołanie:

Oraz

tab[ i ];

można zapisać tak:

*( tab + i )

Każde odwołanie:

*( p + i )

można zapisać tak:

p[ i ];

background image

Uwaga, wskaźnik to nie tablica!

Uwaga, wskaźnik to nie tablica!

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

7

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

int tab[ 10 ];
int * p = tab;

0

1

2

3

4

5

tab

6

7

8

9

10 elementów

p

Nazwa tablicy

int tab[ 10 ]

obszar danych + wskaźnika na jego początek

int * p = tab

wskaźnik zakotwiczony o początek tablicy

Czy to jest to samo? Nie!

background image

Nazwa tablicy to

Nazwa tablicy to

ustalony

ustalony

wskaźnik na jej początek

wskaźnik na jej początek

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

8

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Nazwa tablicy jest ustalonym (niemodyfikowalnym) wskaźnikiem na pierwszy jej
element. Nazw tablic nie wolno modyfikować! Zwykłe wskaźniki można.

int tab[ 10 ];
int * p = tab;

tab = p;
tab++;

p = tab + 8;
p++;

OK

Źle

background image

Ciekawostka

Ciekawostka

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

9

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Wiemy, że odwołanie:

tab[ i ]

można zapisać tak:

*( tab + i )

Wiemy również, że dodawanie jest przemienne, zatem każde odwołanie:

*( tab + i )

można zapisać tak:

*( i + tab )

Czy zatem odwołanie:

*( i + tab )

można zapisać tak:

i[ tab ]

?

Oraz, że odwołanie

*( tab + i )

można zapisać tak:

tab[ i ]

background image

Ciekawostka, cd. ...

Ciekawostka, cd. ...

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

10

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Tak, można, dla kompilatora nie ma to większego znaczenia.

char napis[] = "j zyk c";

ę

. . .

cout << napis << endl;

0[ napis ] = 'J'

;

// Zamiast napis[ 0 ]

6[ napis ] = 'C'

;

// Zamiast napis[ 6 ]


cout << napis << endl;

język c
Język C

background image

Dlaczego nie wolno przypisywać tablic, posługując się ich nazwami?

Dlaczego nie wolno przypisywać tablic, posługując się ich nazwami?

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

11

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

int a[ 10 ];
int b[ 10 ];

b = a

; // Nie wolno przypisywać do siebie tablic!

Gdyby przypisywanie było możliwe...

0

1

2

3

4

5

a

6

7

8

9

0

1

2

3

4

5

b

6

7

8

9

To po wykonaniu tej linii:

b = a

;

gubimy obszar danych tablicy b!

0

1

2

3

4

5

a

6

7

8

9

0

1

2

3

4

5

b

6

7

8

9

Gdyby przypisywanie było możliwe...

background image

Arytmetyka na wskaźnikach — podsumowanie

Arytmetyka na wskaźnikach — podsumowanie

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

12

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Dozwolone operacje wskaźnikowe to:

przypisywanie wskaźników do obiektów tego samego typu,

przypisywanie wskaźników do obiektów innego typu po konwersji,

dodawanie lub odejmowanie wskaźnika i liczby całkowitej,

odejmowanie lub porównanie dwóch wskaźników związanych z ta samą tablicą,

przypisanie wskaźnikowi wartości zero (lub wskazania puste NULL) lub
porównanie ze wskazaniem pustym.

background image

Wskaźniki w akcji — metamorfoza funkcji put_string

Wskaźniki w akcji — metamorfoza funkcji put_string

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

13

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string( char s[] )
{
int i;
for( i = 0; s[ i ] != '\0'; i++ )
putchar( s[ i ] );
}

Wersja pierwotna

char napis[] = "J zyk C i C++";

ę

put_string( napis );

background image

Wskaźniki w akcji — metamorfoza funkcji put_string

Wskaźniki w akcji — metamorfoza funkcji put_string

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

14

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0'; s++ )
putchar( *s );
}

Eliminujemy zmienną i

char napis[ 80 ] = "C++";

put_string( napis );

Jak to działa... ?

background image

Wywołanie funkcji put_string

Wywołanie funkcji put_string

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

15

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2(

char * s

)

{
for( ; *s != '\0'; s++ )
putchar( *s );
}

Kopiowanie parametru aktualnego napis do parametru s

char napis[ 80 ] = "C++";

put_string( napis )

;

C

+

+

\0

napis

s

background image

Parametr s jest kopią wskaźnika napis

Parametr s jest kopią wskaźnika napis

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

16

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2(

char * s

)

{
for( ; *s != '\0'; s++ )
putchar( *s );
}

Kopiowanie parametru aktualnego napis do parametru s

char napis[ 80 ] = "C++";

put_string( napis )

;

C

+

+

\0

napis

s

background image

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

17

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ;

*s != '\0'

; s++ )

putchar( *s );
}

Parametr s wskazuje na pierwszy element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

background image

Znak wskazywany przez s wyprowadzamy jest do stdout

Znak wskazywany przez s wyprowadzamy jest do stdout

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

18

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0'; s++ )

putchar( *s )

;

}

Parametr s wskazuje na pierwszy element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C

background image

Wskaźnik s przesuwamy na następny znak

Wskaźnik s przesuwamy na następny znak

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

19

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0';

s++

)

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C

background image

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

20

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ;

*s != '\0'

; s++ )

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C

background image

Znak wskazywany przez s wyprowadzamy jest do stdout

Znak wskazywany przez s wyprowadzamy jest do stdout

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

21

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0'; s++ )

putchar( *s )

;

}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C+

background image

Wskaźnik s przesuwamy na następny znak

Wskaźnik s przesuwamy na następny znak

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

22

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0';

s++

)

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C+

background image

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

23

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ;

*s != '\0'

; s++ )

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C+

background image

Znak wskazywany przez s wyprowadzamy jest do stdout

Znak wskazywany przez s wyprowadzamy jest do stdout

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

24

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0'; s++ )

putchar( *s )

;

}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C++

background image

Wskaźnik s przesuwamy na następny znak

Wskaźnik s przesuwamy na następny znak

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

25

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ; *s != '\0';

s++

)

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C++

background image

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Czy obiekt wskazywany przez s jest znacznikiem końca napisu?

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

26

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string2( char * s )
{
for( ;

*s != '\0'

; s++ )

putchar( *s );
}

Parametr s wskazuje na kolejny element tablicy napis

char napis[ 80 ] = "C++";

put_string( napis );

C

+

+

\0

napis

s

C++

background image

Wskaźniki w akcji — metamorfoza funkcji

Wskaźniki w akcji — metamorfoza funkcji

put_string,

put_string,

wersja 3 i 4

wersja 3 i 4

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

27

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void put_string3( char * s )
{
for( ; *s != '\0' ;

putchar( *s++ )

)

;
}

„Kompresja” iteracji for


++

*s

Najpierw pobierz znak
wskazywany przez s, użyj
go.

Potem zwiększ o jeden wartość
wskaźnika s — będzie on wtedy
wskazywał na następny element tablicy.

void put_string4( char * s )
{
while( *s )
putchar( *s++ );
}

Iteracja while nie jest taka zła...
Znak '\0' to bajt o wartości 0

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

28

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char s1[ 80 ] = "Język C";
char s2[ 20 ];
. . .
strcpy( s2, s1 );

0

1

2

3

4

5

J

ę

z

y

k

. . .

79

C

\ 0

6

0

1

2

3

4

5

J

ę

z

y

k

. . .

19

C

\ 0

6

i++

. . .

s1

s2

s

d

void strcpy( char d[], char s[] )
{
int i;
for( i = 0; s[ i ] != '\0'; i++ )
d[ i ] = s[ i ];
d[ i ] = '\0';
}

Wersja początkowa

Przypomnienie jak to działa

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

29

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void strcpy1( char * d, char * s )
{
while( *s != '\0' )
{
*d = *s;
d++;
s++;
}
*d = '\0';
}

Odwołania wskaźnikowe

To właściwie nie wiele zmienia,

poza wyeliminowaniem

zmiennej i

void strcpy2( char * d, char * s )
{
while( *s != '\0' )
*d++ = *s++;
*d = '\0';
}

„Kompresja” — krok pierwszy

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

30

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void strcpy3( char * d, char * s )
{
while( ( *d++ = *s++ ) != '\0' )
;
}

„Kompresja” — krok drugi


!= '\0'

(

=

)

*d++

*s++

Wartością tego wyrażenia jest znak
(bajt) przepisany z obszaru
wskazywanego przez s do obszaru
wskazywanego przez d.

Pobierz znak wskazywany, wykorzystaj go,
zwiększ wskaźnik tak, by pokazywał na następny
element tablicy.

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

31

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

void strcpy4( char * d, char * s )
{
while( *d++ = *s++ )
;
}

„Kompresja” — krok trzeci

Znak '\0' to bajt o wartości 0

char * strcpy5( char * d, char * s )
{
while( *d++ = *s++ )
;
return d;
}

Tablica d jako rezultat funkcji

Często spotykaną praktyką w funkcjach bibliotecznych jest udostępnianie wskaźnika
do tablicy (jednej z tablic) będącej parametrem:

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

32

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char s1[ 80 ] = "C i C++";
char s2[ 80 ];
char s3[ 80 ];

Pozwala to na skrócenie kodu, załóżmy następujące definicje tablic s1, s2, s3:

Następujący fragment kodu:

strcpy5( s2, s1 );
strcpy5( s3, s2 );
puts( s3 );

Można zapisać krócej:

puts( strcpy5( s3, strcpy5( s2, s1 ) ) );

background image

Wskaźniki pod lupą — metamorfoza funkcji

Wskaźniki pod lupą — metamorfoza funkcji

strcpy

strcpy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

33

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * strcpy5( char * d, char * s )
{

*s = 'A'

;

. . .
}

Modyfikacja tablicy źródłowej

dozwolona, choć merytorycznie

niepoprawna

char * strcpy6( char * d,

const char * s

)

{

*s = 'A'

;

. . .
}

Tablica źródłowa jest chroniona

Aby temu zaradzić, można zadeklarować parametr reprezentujący tablicę źródłową
w specyficzny sposób:

W dotychczasowych realizacjach funkcji strcpyX, funkcja może modyfikować
zawartość tablicy źródłowej:

background image

Wskaźniki pod lupą — zastosowanie modyfikatora

Wskaźniki pod lupą — zastosowanie modyfikatora

const

const

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

34

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Można wyróżnić następujące kombinacje definicji wskaźnika z/bez const:

Aby funkcja nie mogła zmodyfikować parametru przekazanego za pośrednictwem
wskaźnika, należy w deklaracji użyć słowa const. Deklaracja:

const char * s;

oznacza, że s jest wskaźnikiem na stały (niemodyfikowalny) obiekt typu char.

const int * const p;

// Ustalony wska nika na niemodyfikowalny obiekt

ź

int * const p;

// Ustalony wska nika na modyfikowalny obiekt

ź

const int * p;

// Zwykły wska nika na niemodyfikowalny obiekt

ź

int * p;

// Zwykły wska nik na zwykły obiekt

ź

background image

Wskaźniki pod lupą — zastosowanie modyfikatora

Wskaźniki pod lupą — zastosowanie modyfikatora

const

const

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

35

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Wersja najbardziej restrykcyjna pod lupą:

const int * const p;

int i = 10;
const int * const

p = &i

;

. . .

j = *p + 10

;

. . .

*p = 20

;

. . .

p = &j

;

Niedozwolone, odwołanie modyfikujące obiekt

To jest OK, odwołanie nie modyfikujące obiektu

Niedozwolone, odwołanie modyfikujące wskaźnik

Posługiwanie się ustalonym wskaźnikiem do stałego obiektu:

To się nie uda, ustalony wskaźnik należy zainicjować!

background image

Wyznaczanie długości napisu — funkcja strlen klasycznie

Wyznaczanie długości napisu — funkcja strlen klasycznie

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

36

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Realizacja w wykorzystaniem iteracji while:

int strlen( char s[] )
{
int len = 0;

while( s[ len ] != '\0' )
len++;

return len;
}

Realizacja w wykorzystaniem iteracji for:

int strlen( char s[] )
{
int len;

for( len = 0; s[ len ] != '\0'; len++ )
;

return len;
}

background image

Wyznaczanie długości napisu — funkcja strlen wskaźnikowo

Wyznaczanie długości napisu — funkcja strlen wskaźnikowo

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

37

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

int strlen( char * s )
{
char * ptr = s;

while( *ptr != '\0' )
ptr++;

return ( int )( ptr – s );
}

int strlen( char * s )
{
char * ptr;

for( ptr = s; *ptr != '\0'; ptr++ )
;

return ( int )( ptr – s );
}

Realizacja w wykorzystaniem iteracji while:

Realizacja w wykorzystaniem iteracji for:

background image

Odwracanie kolejności znaków w napisie — strrev klasycznie

Odwracanie kolejności znaków w napisie — strrev klasycznie

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

38

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * strrev( char s[] )
{
int begin, end;

// Szukanie konca napisu

for( end = 0; s[ end ] != '\0'; end++ )
;

// Zamiana znakow miejscami

for( begin = 0, end--; begin < end; begin++, end-- )
{
char c = s[ begin ];
s[ begin ] = s[ end ];
s[ end ] = c;
}
return s;
}

background image

Odwracanie kolejności znaków w napisie — strrev wskaźnikowo

Odwracanie kolejności znaków w napisie — strrev wskaźnikowo

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

39

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * strrev( char * s )
{
char * begin, * end;

// Szukanie znacznika konca

for( end = s; *end ; end++ )
;

// Zamiana znakow miejscami

for( begin = s, end--; begin < end; begin++, end-- )
{
char c = *begin;
*begin = *end;
*end = c;
}
return s;
}

background image

Dynamiczna alokacja tablic — konwencja języka C

Dynamiczna alokacja tablic — konwencja języka C

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

40

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL

;

int n

;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) )

;

if(

s != NULL

)

{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .

free( s )

;

}

Na tablicach alokowanych dynamicznie na stercie, można wykonywać takie same
operacje
, jak na tablicach statycznych. Należy tylko uważnie przydzielać i zwalniać
pamięć
.

Zobaczmy, jak wyglądają kolejne etapy definiowania i wykorzystania takiej tablicy...

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 1-szy

Dynamiczna alokacja tablic — konwencja języka C, etap 1-szy

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

41

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL

;

int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );
}

Definicja wskaźnika — typ obiektu wskazywanego taki, jak typ elementów tablicy
jakich potrzebujemy. Zerowanie wskaźnika to dobra praktyka.

Pamięć operacyjna

Sterta

s

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 2-gi

Dynamiczna alokacja tablic — konwencja języka C, etap 2-gi

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

42

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;

int n

;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );
}

Zwykle korzystamy ze zmiennej, która pozwoli zapamiętać ilu elementową tablicę
potrzebujemy.

Pamięć operacyjna

Sterta

s

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 3-ci

Dynamiczna alokacja tablic — konwencja języka C, etap 3-ci

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

43

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );
}

Przed utworzeniem tablicy musimy ustalić konkretną liczbę elementów tablicy. Jak
ustalimy tę liczbę zależy od konkretnego zastosowania.

Pamięć operacyjna

Sterta

s

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 4-ty

Dynamiczna alokacja tablic — konwencja języka C, etap 4-ty

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

44

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) )

;

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );
}

Przydział pamięci dla tablicy — funkcja malloc otrzymuje liczbę bajtów potrzebnych
do przechowania ustalonej liczby elementów tablicy.

Pamięć operacyjna

s

Pamięć operacyjna

?....................?

Sterta

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 5-ty

Dynamiczna alokacja tablic — konwencja języka C, etap 5-ty

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

45

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )

{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );
}

Kontrola poprawności przydziału pamięci. Uwaga — to koniecznie niezbędny etap!
Przydzielony obszar pamięci ma przypadkową zawartość.

Pamięć operacyjna

s

Pamięć operacyjna

???..................?

Sterta

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

46

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{

strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );

. . .
free( s );
}

Tak utworzona tablicę można używać tak samo, jak każdą inną tablicę w języku C.
Wszystkie funkcje do manipulowania np. napisami działają bez problemu.

Pamięć operacyjna

s

Pamięć operacyjna

J zyk C fajny jest!

ę

Sterta

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

47

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .

free( s )

;

}

Gdy tablica nie jest już potrzebna, zwalniamy przydzieloną pamięć i oddajemy do
puli wolnych bloków. Uwaga, wskaźnik pokazuje dalej na zwolniony obszar pamięci!

Pamięć operacyjna

s

Pamięć operacyjna

J zyk C fajny jest!

ę

Sterta

background image

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Dynamiczna alokacja tablic — konwencja języka C, etap 6-ty

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

48

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = NULL;
int n;

/* Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n */

ę

s = malloc( n * sizeof( char ) );

if( s != NULL )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
free( s );

s = NULL

;

}

Zerowanie wskaźnika po zwolnieniu pamięci jest dobrą praktyką.

Pamięć operacyjna

Sterta

s

background image

Dynamiczna alokacja tablic — konwencja języka C++

Dynamiczna alokacja tablic — konwencja języka C++

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

49

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = 0;
int n;

// Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n

ę

s = new char [ n ]

;

if(

s != 0

)

{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .

delete [] s

;

}

W języku C++ wykorzystujemy operatory new i delete. „Stara” wersja, zakładająca,
że operator new oddaje wskaźnik zerowy w przypadku braku wolnej pamięci:

background image

Dynamiczna alokacja tablic — konwencja języka C++

Dynamiczna alokacja tablic — konwencja języka C++

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

50

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = 0;
int n;

// Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n

ę

try
{
s = new char [ n ];

strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .

delete [] s;
}
catch( ... )
{
cout << "Brak pami ci dla wykonania tej operacji";

ę

}

„Nowa” wersja, zakładająca, że operator new generuje wyjątek w przypadku braku
wolnej pamięci:

background image

Dynamiczna alokacja tablic — konwencja języka C++

Dynamiczna alokacja tablic — konwencja języka C++

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

51

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = 0

;

int n;

// Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n

ę

s = new (nothrow) char [ n ]

;

if(

s != 0

)

{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .

delete [] s

;

}

Wykorzystanie operatora new (nothrow) nie generującego wyjątków, obsługa jak w
„starej” wersji:

background image

Dynamiczna alokacja tablic — konwencja języka C++

Dynamiczna alokacja tablic — konwencja języka C++

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

52

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

char * s = 0;
int n;

// Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n

ę

s = new (nothrow) char [ n ];

if( s != 0 )
{
strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
delete [] s;

s = 0

;

}

Zerowanie wskaźnika po zwolnieniu pamięci jest dobrą praktyką.

background image

Dynamiczna alokacja tablic — konwencja języka C++

Dynamiczna alokacja tablic — konwencja języka C++

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

53

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Zerowanie wskaźnika po zwolnieniu pamięci jest dobrą praktyką.

char * s = 0;
int n;

// Tu ustalenie liczby potrzebnych elementów i zapami tanie w zmiennej n

ę

try
{
s = new char [ n ];

strcpy( s, "J zyk C " );

ę

strcat( s, "fajny jest!" );
puts( s );
. . .
delete [] s;

s = 0

;

}
catch( ... )
{
cout << "Brak pami ci dla wykonania tej operacji";

ę

}

background image

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

54

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

W funkcjach bibliotecznych języka C i C++ stałą praktyką jest deklarowanie
parametrów tablicowych z wykorzystaniem wskaźników, np:

int strlen( char * s );

int strlen( char s[] );

zamiast

Wymaga to dokładnego przeczytania dokumentacji, bowiem programiści często się
mylą. Rozważmy następujący przykład (fragment systemu pomocy firmy Borland):

Prototype

char *gets(char *s);

Description

Gets a string from stdin.

gets collects a string of characters terminated by a new line from the standard input stream stdin and
puts it into s. The new line is replaced by a null character (\0) in s.

gets allows input strings to contain certain whitespace characters (spaces, tabs). gets returns when it
encounters a new line; everything up to the new line is copied into s.

background image

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

55

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Niedokładna lektura dokumentacji może sugerować, że funkcji należy użyć tak:

char * imie;

printf( "Podaj imie: " );
gets( imie );

Pamięć operacyjna

imie

Pamięć operacyjna

Aga

???

gets( imie )

Gdyby wskaźnik był wyzerowany, kompilator czasem pomoże:

char * imie = NULL;

printf( "Podaj imie: " );
gets( imie );

Pamięć operacyjna

imie

Pamięć operacyjna

gets( imie )

Null pointer assignment

Stare kompilatory firmy Borland:

background image

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Ważna sprawa — ostrożnie z parametrami wskaźnikowymi!

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

56

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

A trzeba np. tak:

char imie[ 80 ];

printf( "Podaj imie: " );
gets( imie );

Pamięć operacyjna

imie

Pamięć operacyjna

Aga

gets( imie )

Lub tak:

char * imie = NULL;

imie = new (nothrow) char[ 80 ];
if( imie != 0 )
{
printf( "Podaj imie: " );
gets( imie );
. . .
delete [] imie;
}

Pamięć operacyjna

imie

Pamięć operacyjna

Aga

gets( imie )

background image

Można tworzyć dynamicznie tablice dowolnych typów

Można tworzyć dynamicznie tablice dowolnych typów

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

57

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

double * dochody = 0;

int liczbaMiesiecy;

// Tu ustalenie liczby miesiecy okresu rozrachunkowego

dochody = new (nothrow) double [ liczbaMiesiecy ]

;

if(

dochody != 0

)

{
for( int miesiac = 0; miesiac < liczbaMiesiecy; miesiac++ )

dochody[ miesiac ] = 0

;

. . .

delete [] dochody

;

}

background image

Można tworzyć dynamicznie tablice dowolnych typów

Można tworzyć dynamicznie tablice dowolnych typów

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

58

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

typedef unsigned char byte;

byte * bitmapa = 0;

int rozmiarRysunku;

// Tu ustalenie liczby bajtów rysunku bitmapowego

bitmapa = new (nothrow) byte [ rozmiarRysunku ]

;

if(

bitmapa != 0

)

{

// Zaladuj bitmape

// Zrob z nia co trzeba

// Gdy juz niepotrzebna

delete [] bitmapa

;

}

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

59

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Tablice a problem ich początkowego rozmiaru

Tablice a problem ich początkowego rozmiaru

Według standardu C89 i C++:

tablica zawsze składa się z ustalonej, i znanej na etapie kompilacji liczby
elementów,

liczba elementów tablicy nie ulega zmianie w trakcie działania programu ―
tablice są statyczne.

W standardzie C99 istnieją tablice VLA (ang. variable length array):

liczba elementów tablicy może być zdefiniowany w trakcie wykonania
programu
— może być określona wartością zmiennej, ta wartość nie musi być
znana
na etapie kompilacji,

liczba elementów tablicy nie ulega zmianie w trakcie działania programu ― raz
stworzona tablica zachowuje swój rozmiar.

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

60

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

Tablice a problem ich początkowego rozmiaru — przykład

Tablice a problem ich początkowego rozmiaru — przykład

Problem

Należy napisać program pozwalający na ewidencjonowanie czasów
osiągniętych przez zawodników maratonu.

Liczba zawodników nie jest dokładnie znana, zakłada się jednak, że startowa
pula numerów jest ograniczona do

300

.

Należy ewidencjonować dokładnie tyle czasów ile to potrzebne, program będzie
być może uruchamiany na starym komputerze przenośnym.

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

61

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{
float * czasy;
int nr_zawodnika;

if( ( czasy = malloc( lb_zawodnikow * sizeof( float ) ) ) != NULL )
{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
free( czasy );
}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Ustalenie liczby zawodników, których
czasy będą ewidencjonowane

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

62

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if(

lb_zawodnikow > 0 && lb_zawodnikow <= 300

)

{
float * czasy;
int nr_zawodnika;

if( ( czasy = malloc( lb_zawodnikow * sizeof( float ) ) ) != NULL )
{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
free( czasy );
}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Czy liczba zawodników nie przekracza
zadanego maksimum?

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

63

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{

float * czasy

;

int nr_zawodnika;

if( ( czasy = malloc( lb_zawodnikow * sizeof( float ) ) ) != NULL )
{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
free( czasy );
}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Tablica ewidencjonująca czasy
zostanie przydzielona dynamicznie

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

64

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{

float * czasy

;

int nr_zawodnika;

if( (

czasy = malloc( lb_zawodnikow * sizeof( float ) )

) != NULL )

{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
free( czasy );
}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Przydział pamięci dla tablicy czasów i
kontrola poprawności jego wykonania

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

65

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{

float * czasy

;

int nr_zawodnika;

if( (

czasy = malloc( lb_zawodnikow * sizeof( float ) )

) != NULL )

{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika <

lb_zawodnikow

; nr_zawodnika++ )

{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika <

lb_zawodnikow

; nr_zawodnika++ )

printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
free( czasy );
}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Operacje na tablicy — przetwarzana
jest rzeczywista liczba elementów

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

66

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C89 i tablica czasów dla liczby zawodników nie większej niż 300

C89 i tablica czasów dla liczby zawodników nie większej niż 300

int

lb_zawodnikow

;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d",

&lb_zawodnikow

);

if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{

float * czasy

;

int nr_zawodnika;

if( (

czasy = malloc( lb_zawodnikow * sizeof( float ) )

) != NULL )

{
printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika <

lb_zawodnikow

; nr_zawodnika++ )

{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika <

lb_zawodnikow

; nr_zawodnika++ )

printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );

free( czasy )

;

}
else
printf( "\nBrak pamieci!" );
}
else
printf( "Zbyt duza liczba zawodnikow" );

Tablica nie jest już dłużej potrzebna,
zwolnienie pamięci jej przydzielonej

background image

Podstawy programowania w C++

Podstawy programowania w C++

Copyright © Roman Simiński

67

Strona :

T a b l i c e a z m i e n n e w s k a ź n i k o w e

T a b l i c e a z m i e n n e w s k a ź n i k o w e

C99 i tablica czasów dla liczby zawodników nie większej niż 300

C99 i tablica czasów dla liczby zawodników nie większej niż 300

#include <stdlib.h>
#include <stdio.h>

int main()
{
int lb_zawodnikow;

printf( "\nPodaj liczbe zawodnikow (maks. 300): " );
scanf( "%d", &lb_zawodnikow );
if( lb_zawodnikow > 0 && lb_zawodnikow <= 300 )
{

float czasy[ lb_zawodnikow ]

;

int nr_zawodnika;

printf( "\nPodaj czasy kolejnych zawodnikow:\n" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
{
printf( "%d>", nr_zawodnika + 1 );
scanf( "%f", &czasy[ nr_zawodnika ] );
}

/* Jakies operacje na tablicy czasy */

printf( "\n\nZawodnik Czas" );
for( nr_zawodnika = 0; nr_zawodnika < lb_zawodnikow; nr_zawodnika++ )
printf( "\n%-10d%-.2f", nr_zawodnika + 1, czasy[ nr_zawodnika ] );
}
else
printf( "Zbyt duza liczba zawodnikow" );
return EXIT_SUCCESS;
}

Tablica VLA o rozmiarze początkowym
definiowanym w trakcie działania
programu


Document Outline


Wyszukiwarka

Podobne podstrony:
W09 Ja wstep ROZ
bal w09
Antropologia kulturowa W09 id 6 Nieznany (2)
c cxx w02
jezc w09 bity op
TRB W09 11 11 25 montaż
KZ BD w09 id 256667 Nieznany
223 B8 4 A W09 wykaz drobnych e Nieznany
c cxx w04
w09 Reakcje oksydacyjno -, In˙ynieria Ruchu Morskiego, rok I, gr
c cxx w13
Liber CXX
BD 2st 1 2 w09 tresc 1 1 kolor
Rachunek kosztow, w09
al1 w09 zima2011
2MA3 W09 SWOT Presentation revised (Jen Ottman)

więcej podobnych podstron