Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1
Pętle Pętla jest konstrukcją sterującą stosowaną w celu wielokrotnego wykonania tego samego zestawu instrukcji jednokrotne wykonanie zestawu instrukcji stanowi pojedynczą iterację pętli formalnie, zestaw instrukcji to pojedyncza instrukcja lub blok instrukcji, tworzący instrukcje złożoną W trakcie realizacji pętli, w kolejnych iteracjach, dokonuje się najczęściej pewnych modyfikacji danych W pętlach podstawowymi elementami związanymi ze sterowaniem są: ustalenie stanu początkowego przed wejściem do pętli oznacza to stan danych przed rozpoczęciem wykonania pętli warunku zakończenia pętli warunek oznacza zazwyczaj osiągnięcie pewnego stanu przez dane modyfikowane w pętli Krzysztof Banaś Podstawy programowania 2
Pętla for Ważnym rodzajem pętli jest pętla for, która może przybierać różne postacie W najbardziej podstawowym wariancie składnia pętli for określa podstawowe elementy sterowania wykonaniem pętli: for(int i=0; i<10; i++){... pojedyncza iteracja... pętla jest powiązana z tzw. zmienną sterującą pętli wykonanie pętli oznacza wykonanie określonej liczby iteracji każda iteracja jest związana z pewną wartością zmiennej sterującej składnia uwzględnia nadanie wartości początkowej zmiennej sterującej warunek, który ma spełniać zmienna sterująca, dla dalszej kontynuacji wykonania pętli zaprzestanie spełniania warunku oznacza przerwanie wykonania peli modyfikacje zmiennej sterującej po każdej iteracji Krzysztof Banaś Podstawy programowania 3
Pętla for Przykład: #define LICZBA_WYDRUKOW 5 int i; // zmienna sterująca widoczna w całej funkcji main // suma liczb - inicjowanie danych przed wejściem do pętli int suma_liczb=0; // for w postaci "kanonicznej" for(i = 1; i <= LICZBA_WYDRUKOW; i++){ suma_liczb = suma_liczb + i; // suma_liczb += i; printf("iteracja %d: suma liczb od 1 do %d wynosi %d\n", i, i, suma_liczb); printf("wartość zmiennej sterującej po wykonaniu pętli: i = %d\n", i); W przypadku standardowej pętli for możliwe jest określenie z góry liczby iteracji Krzysztof Banaś Podstawy programowania 4
Pętle Pętla while while(warunek){... iteracja pętli... składnia wymaga tylko określenia warunku powtarzania iteracji inicjowanie danych początkowych i modyfikacje danych w pętli określane są standardowym kodem warunek sprawdzany jest przed wykonaniem pierwszej (i każdej kolejnej) iteracji oznacza to, że możliwe jest nie wykonanie żadnej iteracji przykład: i=0; while(i<5) { i++; Pętla do do{... iteracja pętli... while(warunek); pętla do różni się od pętli while tylko tym, że warunek jest sprawdzany po pierwszej (i każdej kolejnej iteracji) oznacza to, że co najmniej jedna iteracja jest wykonana Krzysztof Banaś Podstawy programowania 5
Pętle Pętla for for(w1; w2; w3){... iteracja pętli... jest równoważne: w1; while( w2 ) {...; w3; gdzie w1, w2 i w3 są dowolnymi wyrażeniami dozwolona składnia pętli for jest bardzo elastyczna i pozwala na: umieszczanie rozmaitych operacji (jednej lub wielu, oddzielonych operatorem przecinka) jako w1 i w3 najczęściej są to przypisania: for (i = 0, j = n; i < j; i++, j--) {... umieszczanie złożonych wyrażeń jako warunku w2 for (i=0; i<zakres && (znak=getchar())!= EOF && znak!= '\n'; i++){... pomijanie składowych definicji for(;;){... pętla nieskończona Krzysztof Banaś Podstawy programowania 6
Tablice Tablica jest strukturą danych, w której zbiór elementów tego samego typu jest przechowywany w kolejno następujących po sobie komórkach pamięci Dostęp do elementu tablicy uzyskuje się przez indeks elementu w C/C++ indeksem pierwszego elementu jest 0 Tablice mogą przechowywać elementy rozmaitych typów, także złożonych (omawianych później) Podstawowe definicje (ew. z inicjowaniem zerami): int tab_int[123] = {0; double tab_double[12]; char tab_char[16]; Tablice jako struktura danych są powiązane z pętlami jako strukturami sterowania Operacje na elementach tablic często wykonuje się w pętlach for, while, do Krzysztof Banaś Podstawy programowania 7
Tablice i pętle przykład Prosty problem: obliczanie średniej płacy w roku na podstawie płac w poszczególnych miesiącach: płace zapisane w tablicy: int place[12]; Kod C/C++: int place_suma =0; for(int i=0; i<12; i++) { place_suma += place[i]; lub int i=0; int place_suma=0; while(i<12){ place_suma += place[i]; i++; Kod w asemblerze:.l2 cmp %ebx, 12 // 12 <> i? jl.l4 jmp.l3.l4 add (%ebx), %ecx // place_suma += place[i] inc %ebx // i++ jmp.l2.l3 Krzysztof Banaś Podstawy programowania 8
Pętla while Przykład pętli while w programie kopiowania standardowego wejścia (stdin) na standardowe wyjście (stdout): #include <stdio.h> // definicje symboli związanych z funkcjami wejścia/wyjścia // (w tym stdin i stdout oraz EOF (end of file) - liczbowa // wartość reprezentująca koniec strumienia danych; // plik jest także strumieniem danych ) void main( void ) { int c = getchar(); // int ponieważ EOF niekoniecznie jest znakiem while (c!= EOF) { putchar(c); // liczba całkowita z odpowiedniego zakresu // jest interpretowana jako znak c = getchar (); Krzysztof Banaś Podstawy programowania 9
Pętla do Przykład pętli do w programie obliczania liczby PI // wzór: PI/4 = 1-1/3 + 1/5-1/7 + 1/9 itd. itp. double suma=0.0; int i=0; do{ int j = 1 + 4*i; // i = 0, 1, 2,itd., j = 1, 5, 9, itd. suma += 1.0/j 1.0/(j+2.0); // zawsze dodatnie i++; // dla każdego i liczymy dwa wyrazy z sumy // użycie instrukcji break dla zbyt wielu wyrazów w sumie // można w miejscu... dodać dodatkowe instrukcje, wydruki itd. itp. if( i==ceil(max_liczba_wyrazow/2.0) ) {...; break; // warianty zakończenia : 1. oba warunki (brak dodatkowych informacji) // while(i<ceil(max_liczba_wyrazow/2.0) && 4.0/j-4.0/(j+2) > dokladnosc); while( ( 4.0/j - 4.0/(j+2.0) ) > dokladnosc ); // wariant zakończenia 2 double obliczone_pi = 4*suma; Krzysztof Banaś Podstawy programowania 10
Tablice znaków i napisy Napis jest tablicą znaków z dodanym na zakończenie znakiem końca napisu \0 : char s[] = "abc"; // równoważne: char s[] = { 'a', 'b', 'c', '\0' Przykład powyżej podaje inicjowanie tablicy (dotyczy nie tylko znaków) bez podania rozmiaru kompilator automatycznie oblicza potrzebny rozmiar specjalne inicjowanie napisu jako tablicy znaków "abc" standardowe inicjowanie tablicy kolejnymi wartościami { 'a',... jeśli liczba wartości jest mniejsza od rozmiaru, uzupełnia się przez 0 Operacji na napisach można dokonywać: jak na tablicy znaków dostęp do pojedynczych elementów tablicy za pomocą specjalnych funkcji traktujących napis jako całość wiele takich funkcji zawiera standardowa biblioteka C Krzysztof Banaś Podstawy programowania 11
Przykład: wczytanie pojedynczej linii z stdin #include <stdio.h> #define MAXLINE 100 // maximum input line size void main( void ) { char linia[maxline]; int zakres = MAXLINE - 1; // w napisie jako tablicy znaków miejsce na \0 int znak; // do podstawiania znaków z getchar() - EOF nie jest znakiem int i; for (i=0; i<zakres && (znak=getchar())!= EOF && znak!= '\n'; i++) linia[i] = znak; if (znak == '\n') { linia[i] = znak; i++; // koniec linii też do tablicy linia[i] = '\0'; // od 0 do i - czyli i+1 elementów tablicy int dlugosc_linii = i; // liczymy tylko znaki, bez \0!!! printf("%s",linia); // lub: for(i=0; i<dlugosc_linii; i++) printf("%c", linia[i]); return; Krzysztof Banaś Podstawy programowania 12
Instrukcje break i continue Instrukcja break służy do przerwania wykonania: ciągu instrukcji w ramach instrukcji switch ciągu instrukcji w ramach dowolnej pętli (while, for, do) i przeniesienia sterowania poza pętlę lub instrukcję switch for (i = 0; i < n; i++) { if (a[i] == szukana_wartosc){ szukana_pozycja = i; break; // przerwane wykonanie najbardziej wewnętrznej pętli Instrukcja continue służy do przerwania ciagu instrukcji w ramach pojedynczej iteracji dowolnej pętli (while, for, do) i przeniesienia sterowania na koniec iteracji for (i = 0; i < n; i++) { if (a[i] < 0) continue; // pomijamy elementy ujemne... // skomplikowane przetwarzanie elementów dodatnich Krzysztof Banaś Podstawy programowania 13
Instrukcja goto Instrukcja goto jest pozostałością dawnego stylu programowania, odpowiednikiem rozkazu skoku w językach asemblera procesorów składnia: goto etykieta; gdzie etykieta oznacza konkretne miejsce w programie zdefiniowane jako etykieta: zasięgiem nazwy etykiety jest funkcja, w której jest zdefiniowana najczęściej definicja etykiety jest osobną linią Jedynym sensownym użyciem goto jest wyjście na zewnątrz wielokrotnie zagnieżdżonych pętli (kiedy nie wystarcza zastosowanie break): for (...) { for (...) { if (blad) goto obsluga_bledu; // co najmniej dwie pętle dla uzasadnienia użycia goto obsluga_bledu:... // kod obsługi błędu Krzysztof Banaś Podstawy programowania 14
Przykład zliczanie znaków z stdin #include <stdio.h> // USES void main(void) { char c; int i, nwhite=0, nother=0, ndigit[10]={0; // definicje i inicjowanie while((c = getchar())!= EOF) { // złożone wyrażenie specjalność C switch (c) { // switch porównuje wyrażenie o typie int case '0': case '1': case '2': case '3': case '4': // z zestawem stałych wartości case '5': case '6': case '7': case '8': case '9': // także o typie int ndigit[c-'0']++; // printf("%c, %d, %d\n", c, c-'0', ndigit[c-'0']); break; case ' ': case '\n': case '\t': nwhite++; // po porównaniu wykonuje zestaw instrukcji i przechodzi dalej break; // można więc łączyć kilka wartości z tym samym zestawem instrukcji default: // etykieta default jest opcjonalna nother++; break; // break jest specjalną instrukcją, która przenosi sterowanie // poza zakończenie danej instrukcji sterującej (dotyczy to switch i pętli) printf("digits ="); for (i = 0; i < 10; i++) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); Krzysztof Banaś Podstawy programowania 15