28
Wprowadzenie do programowania Wprowadzenie do programowania w języku C w języku C Tablice — koncepcja, reprezentacja, przetwarzanie Część pią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 [email protected] www.us.edu.pl/~siminski Autor Kontakt

Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Embed Size (px)

Citation preview

Page 1: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Wprowadzenie do programowania Wprowadzenie do programowania w języku Cw języku C

Tablice — koncepcja, reprezentacja, przetwarzanie

Część pią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

[email protected]/~siminski

Autor

Kontakt

Page 2: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — deklaracja, reprezentacja wewnętrznaTablice — deklaracja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 2Strona :

Co to jest tablica?

Po co się stosuje tablice?

Tablica jest zmienną złożoną z elementów tego samego typu. Obejmuje ona ciągły obszar pamięci operacyjnej dokładnie tak duży, aby zmieścić wszystkie jej elementy.

Termin tablica w języku potocznym jest zmiennikiem sformułowania zmienna tablicowa.

Tablice stosuje się wtedy, gdy trzeba zgromadzić wiele obiektów tego samego typu w jednej strukturze danych, i w sposób wygodny przetwarzać je według jednorodnego schematu.

Dwie istotne własności tablic (wg. standardu C89):

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.

Page 3: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — deklaracja, reprezentacja wewnętrznaTablice — deklaracja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 3Strona :

Deklaracja zmiennych tablicowych

Ogólna postać deklaracji tablicy — zmiennej tablicowej:

typ_elemetu nazwa_tablicy[ <wyra enie_ stałeż > ]

wyrażenie_ stałe — wyrażenie określające liczbę elementów tablicy, wartość tego wyrażenia musi być znana na etapie kompilacji.

Dziesięcioelementowa tablica liczb całkowitych Różne warianty deklaracji C C++

int tab[ 10 ]; poprawne poprawne #define N 10 . . . int tab[ N ];

poprawne poprawne

const int N = 10; . . . int tab[ N ]

niepoprawne poprawne

Kwalifikator typu const może wystąpić z każdą specyfikacją typu. Zmienna

z const powinna być zainicjowana ale potem nie może zmieniać wartości.

Zmienna z kwalifikatorem const w języku C nie jest traktowana jako stała i nie

może być wykorzystywana do określania rozmiaru tablicy.

Page 4: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — deklaracja, reprezentacja wewnętrznaTablice — deklaracja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 4Strona :

Reprezentacja tablicy w pamięci operacyjnej

Elementy tablicy numerowane są zawsze od 0. Zatem jeżeli N oznacza liczbę elementów tablicy, to ostatni jej element ma numer N - 1.

W języku C i C++ nie ma żadnych wbudowanych mechanizmów zabezpieczających przed odwoływaniem się do „elementów” leżących poza zakresem indeksowym tablic!

10 elementów

0 1 2 3 4 5 6 7 8 9tab

#define N 10. . .int tab[ N ];

Dowoływanie się do elementów tablicy

tab[ 0 ] = 1; tab[ N - 1 ] = 5; a = 2 * tab[ 3 ];

int i = 0, j = N – 1;a = tab[ i ] + tab [ j ];

0 1 2 3 4 5 6 7 8 9tab

10 11 12? ? 10

Obszar poza zakresem tablicy !

tab[ 12 ] = 10;

Page 5: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — deklaracja, reprezentacja wewnętrznaTablice — deklaracja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 5Strona :

Tablice wolno inicjalizować na etapie deklaracji:

Jeżeli inicjalizowana tablica nie posiada określonego rozmiaru, ostanie on określony na podstawie liczby elementów inicjalizujących.

Jeżeli liczba wartości początkowych jest mniejsza od rozmiaru tablicy, to elementy o brakujących wartościach początkowych otrzymują wartość zero (zmienne zewnętrzne, statyczne i automatyczne).

Podanie zbyt wielu wartości początkowych jest błędem.

Nie ma sposobu na zainicjowanie środkowego elementu bez podania wszystkich wartości pośrednich.

int tab[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int dni_miesiecy[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };`

float przychody[ 12 ] = { 0, 0, 0 }; /* Za mało warto ci pocz tkowych */ś ą

Typowa inicjalizacja

Rozmiar określony liczbą wartości początkowych

Zbyt mało warości początkowych

Page 6: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 6Strona :

Typowe operacje na tablicach

Przetwarzanie tablic realizowane jest zwykle z wykorzystaniem instrukcji iteracyjnych. Do przetwarzania tablic najczęściej wykorzystuje się iterację for.

for( i = 0; i < N; i++ ) tab[ i ] = 0;

Ustawianie wartości wszystkich elementów tablicy, np. zerowanie:

for( i = 0; i < N; tab[ i++ ] = 0 ) ;

Wersja pierwsza:

Wersja druga:

#define N 10. . .int tab[ N ];int i;

Ogólnie, wypełnianie pewnym wzorcem pattern:

int pattern = -1;. . .for( i = 0; i < N; tab[ i++ ] = pattern ) ;

Page 7: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 7Strona :

Typowe operacje na tablicach, cd. ...

char linia[ 80 ];. . .for( i = 0; i < N; i++ ){ printf( "\n>" ); fgets( linia, 80, stdin ); tab[ i ] = atoi( linia );}

Wczytywanie danych ze strumienia stdin do tablicy:

Wersja pierwsza:

#define N 10. . .int tab[ N ];int i;

Page 8: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 8Strona :

Typowe operacje na tablicach, cd. ...

Wczytywanie danych ze strumienia stdin do tablicy:

#define N 10. . .int tab[ N ];int i;

Wersja druga, z wykorzystaniem funkcji wczytaj_liczbe_int:

for( i = 0; i < N; i++ ) tab[ i ] = wczytaj_liczbe_int( "\n>" );

int wczytaj_liczbe_int( char komunikat[] ){ char bufor_tekstowy[ 80 ];

printf( komunikat ); fgets( bufor_tekstowy, 80, stdin ); return atoi( bufor_tekstowy );}

Przykładowa realizacja funkcji wczytaj_liczbe_int:

Page 9: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 9Strona :

Typowe operacje na tablicach, cd. ...

Wyprowadzanie danych z tablicy do strumienia stdout:

#define N 10. . .int tab[ N ];int i;

for( i = 0; i < N; i++ ) printf( "\n%d", tab[ i ] );

Wersja pierwsza:

for( i = 0; i < N; printf( "\n%d", tab[ i++ ] ) ) ;

Wersja druga:

x = tab[ ++i ] + tab[ i ];

Uwaga na takie konstrukcje:

Na marginesie...

tab[ ++i ] = a * ++i;

Page 10: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 10Strona :

Typowe operacje na tablicach, cd. ...

Sumowanie liczb zapisanych w tablicy:

#define N 10. . .int tab[ N ];int i;

int suma = 0;. . .for( i = 0; i < N; i++ ) suma = suma + tab[ i ];

Wersja pierwsza:

int suma;. . .for( i = 0, suma = 0; i < N; suma += tab[ i++ ] ) ;

Wersja druga:

Page 11: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 11Strona :

Typowe operacje na tablicach, cd. ...

Przykładowe „dziwactwo”:

#define N 10. . .int tab[ N ];int i;

int suma;. . .for( i = 0, suma = 0; i < N; i+= 2 ) if( tab[ i ] > 0 ) if( tab[ i ] % 3 == 0 ) suma += tab[ i ];

Wyznaczanie sumy co drugiego, dodatniego elementu tablicy, podzielnego przez 3:

int suma;. . .for( i = 0, suma = 0; i < N; i+= 2 ) if( tab[ i ] > 0 && tab[ i ] % 3 == 0 ) suma += tab[ i ];

Ponieważ wyrażenia logiczne w języku C nie są wartościowane „kompletnie”:

Page 12: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 12Strona :

Kopiowanie zawartości tablic

Tak w języku C nie wolno:

#define N 5int a[] = { 1, 2, 3, 4, 5 };int b[ N ];. . .int i;

for( i = 0; i < N; i++ ) b[ i ] = a[ i ];

Trzeba:

b = a; /* Nie wolno przypisywać do siebie tablic */

Uwaga na niejednakowe rozmiary tablic

#define SIZE_A 30#define SIZE_B 20

int a[ SIZE_A ];int b[ SIZE_B ];

for( i = 0; i < SIZE_B; i++ ) b[ i ] = a[ i ];

Page 13: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 13Strona :

Kopiowanie zawartości tablic, cd. ...

void copy_int_table( int d[], int s[], int n ) { int i = 0; for( i = 0; i < n; i++ ) d[ i ] = s[ i ];}

Lub krócej:

Z tymi parametrami formalnymi to coś nie gra...

Czasem warto napisać funkcję do kopiowania zawartości tablic:

void copy_int_table( int d[], int s[], int n ) { while( --n >= 0 ) d[ n ] = s[ n ];}

W języku C nazwy tablic są traktowane w specyficzny sposób. O tym już niedługo.

Z tego powody wolno definiować tablicowe parametry formalne bez rozmiaru.

Taki parametr przyjmuje do siebie tablicę o dowolnym rozmiarze.

Tablice pozornie zachowują się tak, jakby były przekazywane przez zmienną.

Page 14: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Tablice — przetwarzanieTablice — przetwarzanie

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 14Strona :

Kopiowanie zawartości tablic, rozwiązania alteratywne

Na marginesie,alternatywa dla iteracyjnego zerowania tablicy

Ponieważ z definicji tablice to spójne obszary pamięci operacyjnej, można do ich kopiowania użyć funkcji memmove lub memcpy (nagłówek mem.h, zgodne z ANSI C):

memmove( b, a, N * sizeof( int ) );

Lub sprytniej:

memmove( b, a, N * sizeof( b[ 0 ] ) );

Alternatywnie:

memcpy( b, a, N * sizeof( int ) );

Lub sprytniej:

memset( b, 0, N * sizeof( b[ 0 ] ) );

memmove( dest, src, n );Kopiuje blok n bajtów z lokalizacji src do dest. Lokalizacje te mogą się nakładać.

memcpy( dest, src, n );Kopiuje blok n bajtów z lokalizacji src do dest. Gdy lokalizacje te się nakładają, działanie funkcji jest niezdefiniowane.

Można do tego wykorzystać funkcję memset

:

memset( s, c, n );Wypełnia n pierwszych bajtów obszaru s bajtem o wartości c.

memcpy( b, a, N * sizeof( b[ 0 ] ) );

Page 15: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — koncepcja, reprezentacja wewnętrznaŁańcuchy znakowe — koncepcja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 15Strona :

Łańcuchy znakowe jako tablice znaków ze znacznikiem końca

Do reprezentacji łańcuchów znakowych w języku C wykorzystuje się zwykłe tablice znakowe.

Tablice takie nie różnią się od innych tablic w języku C, wprowadzono jedynie kilka udogodnień czyniących łatwiejszym manipulowanie takimi tablicami.

W języku C przyjęto koncepcję łańcuchów ze znacznikiem końca (ang. null terminated strings).

Podstawowy problem — zmienna długość łańcuchów znakowych

”To jest napis” a to jego reprezentacja wewnętrzna:

Fizyczna długość napisu = liczba znaków + 1 Znacznik końca napisu to znak o kodzie \0 0

T o j e s t n a p i s \0

Page 16: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — koncepcja, reprezentacja wewnętrznaŁańcuchy znakowe — koncepcja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 16Strona :

Deklarowanie i inicjowanie zmiennych łańcuchowych

Tablice znakowe można inicjować w zwykły sposób, przewidziany dla tablic:

Reprezentacja wewnętrzna

#define N 80. . .char imie[ N ] = { ’A’, ’g’, ’a’ }; /* \0 ??? */char imie[] = { ’A’, ’g’, ’a’, ’\0’ }; /* \0 !!! */

choć można wykorzystywać wygodniejszą formę:

char imie[ N ] = "Aga";

Uwaga — powyższe przypisanie wystąpić może jedynie przy definicji zmiennej!

0 1 2 3A g a \0Literał łańcuchowy :

Zmienna imie :0 1 2 3 4 5 78A g a \0 . . .

79

Page 17: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — koncepcja, reprezentacja wewnętrznaŁańcuchy znakowe — koncepcja, reprezentacja wewnętrzna

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 17Strona :

Deklaracja łańcucha zainicjowanego napisem pustym

char imie[ N ] = {’\0’};

Reprezentacja wewnętrzna łańcucha pustego:

imie[ 0 ] = ’\0’;

char imie[ N ] = "";

Zmienna imie:0 1 2 3 4 5 78\0 . . .

79Ustawianie łańcucha pustym w po deklaracji

imie = ""; /* Bł d,tak nie wolno */ą

Page 18: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 18Strona :

Ogólny schemat przetwarzania tablic znakowych

Wyprowadzanie napisu do stdout znak po znaku:

int i;char s[ N ];. . .for( i = 0; s[ i ] != ’\0’; i++ ) < tu jakie operacje na ka dym znaku s[ i ] >ś ż

Przetwarzanie tablic polega zwykle na „przemaszerowaniu” zmienna indeksową po tablicy, dopóki nie ma końca napisu oznaczanego znakiem ’\0’:

int i;char s[ N ];. . .for( i = 0; s[ i ] != ’\0’; i++ ) putchar( s[ i ] );

Albo w krótszej postaci:

int i;char s[ N ];. . .for( i = 0; s[ i ] != ’\0’; putchar( s[ i++ ] ) ) ;

Page 19: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 19Strona :

Przetwarzanie z wykorzystaniem funkcji bibliotecznych — string.h

#define N 80char napis[ N ] = "J zyk C";ę. . .printf( "Liczba znaków w ła cuchu:%s wynosi:%d", napis, ń strlen( napis ) );

Do manipulowania tablicami znakowymi opracowano szereg funkcji bibliotecznych (plik nagłówkowy string.h),... większość z nich można łatwo napisać samemu!

Funkcja strlen — wyznaczanie długości łańucha

Rezultatem funkcji strlen jest liczba znaków napisu, przekazanego tej funkcji

parametrem.

Liczba znaków w łańcuchu:Język C wynosi:7

int i, len;char s[ N ];. . .for( i = 0, len = strlen( s ) ; i < len; putchar( s[ i++ ] ) ) ;

Alternatywny schemat przetwarzania napisów (z wykorzystaniem strlen):

Uwaga — nigdy tak i < strlen( s )

Page 20: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 20Strona :

Funkcja strlen — przykładowe realizacje

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

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

return len;}

Iteracja while

int strlen( char s[] ){ int len; for( len = 0; s[ len ] != '\0'; len++ ) ; return len;}

Iteracja for

Page 21: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 21Strona :

Funkcje strupr i strlwr — przykładowe realizacje

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

Funkcja strupr

char a[] = "ALA";char b[] = "ala";

strlwr( a ); /* Po wywołaniu strlwr zmienna a zawiera napis "ala" */strupr( b ); /* Po wywołaniu strupr zmienna a zawiera napis "ALA" */

Konwersja - małe litery na duże: strupr, duże litery na małe: strlwr.

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

Funkcja strlwr

Konwersja elementu tablicy, toupper zamienia znak będący parametrem na literę dużą, o ile był literą małą.

Konwersja elementu tablicy, tolower zamienia znak będący parametrem na literę małą, o ile był literą dużą.

Page 22: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 22Strona :

Funkcja strcpy — koncepcja kopiowania napisów

char s1[ 80 ] = "J zyk C";ęchar s2[ 20 ];

Pamiętamy, że w języku nie można kopiować zawartości tablic wykorzystując operator przypisania.

s2 = s1; /* Tak nie wolno !!! */

Do kopiowania zawartości tablic znakowych używamy funkcji strcpy:

strcpy( s2, s1 );

Funkcja strcpy kopiuje zawartość tablicy znakowej s1 do tablicy s2. Kopiowaniu podlegają wszystkie znaki łańcucha s1 (aż do \0), zakłada się, że tablica s2 ma rozmiar

wystarczający na pomieszczenie kopiowanych znaków.

Funkcja strcpy służy również do kopiowania literałów łańcuchowych:

strcpy( s1, "Programowanie " );strcpy( s2, "w j zyku C" );ę

Page 23: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 23Strona :

Funkcja strcpy — przykładowe realizacje

Funkcja strcpy — wersja pierwsza, iteracja for

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

0 1 2 3 4 5

J ę z y k . . .79

C \06

0 1 2 3 4 5

J ę z y k . . .19

C \06

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';}

Ta wersja funkcji strcpy przepisuje

znacznik końca napisu z tablicy s do d,

jednak dzieje się to poza iteracją, tuż po jej

zakończeniu:d[ i ] = '\0';

Page 24: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 24Strona :

Funkcja strcpy — przykładowe realizacje, cd. ...

Funkcja strcpy — wersja druga, iteracja for

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

W języku C operator przypisania jest lewostronnie łączny. Pozwala to na pisanie następujących konstrukcji, np.:

d[ 0 ] = d[ 1 ] = d[ 2 ] = 0;

Jak to działa?

Konstrukcja:( d[ i ] = s[ i ] ) != '\0'

przypisuje i-ty element tablicy s do i-tego elementu tablicy d. Przypisana wartość jest następnie porównywana (operator !=) ze znacznikiem końca napisu '\0'.

Ta wersja funkcji strcpy przepisuje znacznik końca napisu z tablicy s do d w iteracji while.

Page 25: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 25Strona :

Co się stanie, gdy tablica docelowa jest za krótka?

void main(){ char s1[ 5 ] = "AAAA"; char c1 = 'A'; char c2 = 'B'; char s2[ 5 ] = "BBBB"; strcpy( s2, "XXXXXXXXXXXXXXXXXXXX" );

}

printf( "\ns1 : %s\nc1 : %c\nc2 : %c\ns2 : %s", s1, c1, c2, s2 );

Gdzie oryginalna zawartość tablicy s1?

Co się stało ze zmienną c2?

Dlaczego zmienna c1 jest OK?

Nigdy nie należy zakładać, że „się uda”, czyli że tablica docelowa jest wystarczająco

długa. Należy szacować, przewidywać, jeszcze raz przewidywać — programować

defensywnie.

Page 26: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 26Strona :

Funkcja strcat — przykładowa realizacja

Funkcja strcat dołącza zawartość tablicy znakowej s1 do tablicy s2. Kopiowaniu podlegają wszystkie znaki łańcucha s1 (aż do \0), zakłada się, że tablica s2 ma rozmiar

wystarczający na pomieszczenie kopiowanych znaków.

strcpy( s1, "Programowanie " );strcpy( s2, "w j zyku C" );ę

strcat( s1, s2 );puts( s1 ); Programowanie w języku C

Jak to działa?

void strcat( char d[], char s[] ){ int i = 0, j = 0;

}

while( d[ i ] != ’\0’ ) i++;

while( ( d[ i++ ] = s[ j++ ] ) != ’\0’ ) ;

Znajdź znacznik końca napisu docelowego, zapamiętaj jego pozycje w zmiennej i.

Przepisz elementy tablicy s do tablicy d. Maszeruj zmienną j od początku tablicy s, zmienną i od pozycji znalezionego wcześniej znacznika końca napisu.

Page 27: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 27Strona :

Jak nie dopuszczać do „przepełnienia bufora”?

Biblioteka funkcji operujących na tablicach znaków zawiera funkcje wykonujące operacje analogiczne do przedstawionych uprzednio, pozwalające na kontrolę liczby znaków biorących udział np. w kopiowaniu. Są to np. funkcje: strncpy, strncat, strnset.

#define N 10#define M 80char s1[ N ];char s2[ M ] = "J zyk C jest wietny lecz pełen pułapek";ę ś

strncpy( s1, s2, N - 1 );

puts( s1 );

strncpy( s1, s2, sizeof( s1 ) - 1 );

puts( s1 );

Funkcja strncpy nie zawsze przekopiuje ’\0’!

s1[ N - 1 ] = '\0'; s1[ sizeof( s1 ) - 1 ] = '\0';

Ciekawostka

Często rezultatem funkcji operujących na tablicach są one same. Rezultatem funkcji strncpy jest tablica będąca pierwszym parametrem a więc, w naszym przypadku, s1.

strncpy( s1, s2, N - 1 ) [ N - 1 ] = '\0';

s1Skrócona wersja kopiowania i dopisy-wania znacznika końca napisu

Page 28: Wprowadzenie do programowania w języku C - USNETprac.us.edu.pl/~siminski/jp/pjp_c_05.pdf · Wprowadzenie do programowania w języku C Tablice — koncepcja, reprezentacja, ... z

Łańcuchy znakowe — typowe operacjeŁańcuchy znakowe — typowe operacje

Tablice — koncepcja, reprezentacja, przetwarzanieJęzyk CJęzyk CPodstawy i języki programowaniaPodstawy i języki programowania

Copyright © Roman Simiński 28Strona :

Funkcja strncpy — przykładowa, bezpieczniejsza realizacja

void strncpy_while( char d[], char s[], int n ){ int i = 0; while( ( d[ i ] = s[ i ] ) != '\0' && i < n ) i++; while( i <= n ) d[ i++ ] = '\0'; }

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

Wersja z iteracją while

Wersja z iteracją for