Wykład 5. Operacje na tablicach

Podobne dokumenty
tablica: dane_liczbowe

Wykład 3. Instrukcje powtarzające

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

Wykład 1_2 Algorytmy sortowania tablic Sortowanie bąbelkowe

Proste typy zmiennych języka C++ *) Zapis 3.4 e-38 jest równoważny zapisowi 3,

WYKŁAD 9. Algorytmy sortowania elementów zbioru (tablic) Programy: c4_1.c... c4_3.c. Tomasz Zieliński

Podstawy Programowania C++

Język C zajęcia nr 11. Funkcje

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Wstęp do wskaźników w języku ANSI C

Wykład 6. Operacje na łańcuchach znakowych

funkcje rekurencyjne Wykład 12. Podstawy programowania (język C) Funkcje rekurencyjne (1) Funkcje rekurencyjne (2)

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

1 Podstawy c++ w pigułce.

Podstawy programowania. Wykład: 8. Wskaźniki. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Ćwiczenie 4 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Wskaźniki w C. Anna Gogolińska

Tablicę 2-wymiarową można przedstawić jako pewien zestaw tablic 1-wymiarowych np.:

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Lab 9 Podstawy Programowania

Ćwiczenie 5 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

KURS C/C++ WYKŁAD 8. Deklaracja funkcji informuje komplilator jaką wartość funkcja będzie zwracała i jakiego typu są jej argumenty.

1 Podstawy c++ w pigułce.

Argumenty wywołania programu, operacje na plikach

Rozwiązanie. #include <cstdlib> #include <iostream> using namespace std;

Algorytmy i język C++

Język C, tablice i funkcje (laboratorium, EE1-DI)

Zmienne, stałe i operatory

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Podstawy Informatyki sem. I 2014/2015 studia zaoczne Elektronika i Telekomunikacja!

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Instrukcja wyboru, pętle. 2 wykład. Podstawy programowania - Paskal

Funkcje. Deklaracja funkcji. Definicja funkcji. Wykorzystanie funkcji w programie.

W większości języków programowania(nie we wszystkich) wymaga się, żeby użyte w programie zmienne były wcześniej zadeklarowane:

Część 4 życie programu

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Funkcja (podprogram) void

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Deklaracje. W większości języków programowania(nie we wszystkich) wymaga się, żeby użyte w programie zmienne były wcześniej zadeklarowane:

Program 14. #include <iostream> #include <ctime> using namespace std;

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

> C++ dynamiczna alokacja/rezerwacja/przydział pamięci. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

IX. Wskaźniki.(3 godz.)

część 8 wskaźniki - podstawy Jarosław Gramacki Instytut Informatyki i Elektroniki Podstawowe pojęcia

2 Przygotował: mgr inż. Maciej Lasota

//zmienne globalne int *pa, *pb; //wskaźniki globalne void main(void) { clrscr(); printf("\n podaj wartosc liczby a\n"); scanf("%d",&a); pa=&a;

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Programowanie w C++ Wykład 4. Katarzyna Grzelak. 19 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 37

Zmienne i struktury dynamiczne

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Język C, tablice i funkcje (laboratorium)

Wykład 6_1 Abstrakcyjne typy danych stos Realizacja tablicowa i za pomocą rekurencyjnych typów danych

Stałe, tablice dynamiczne i wielowymiarowe

Wstęp do Programowania, laboratorium 02

Zadania do wykonania. Rozwiązując poniższe zadania użyj pętlę for.

Podstawy algorytmiki i programowania - wykład 2 Tablice dwuwymiarowe cd Funkcje rekurencyjne

Wskaźniki. Programowanie Proceduralne 1

4) Operacje na tablicy dwuwymiarowej bez wykorzystywania indeksów liczbowych:

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Język C++ zajęcia nr 2

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Podstawy programowania skrót z wykładów:

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Algorytm selekcji Hoare a. Łukasz Miemus

Programowanie w C/C++ Instrukcje - konstrukcje powtórka. LABORKA Piotr Ciskowski

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Programowanie - wykład 4

Podstawy Programowania Podstawowa składnia języka C++

1. Wprowadzanie danych z klawiatury funkcja scanf

1,3,4,2,3,4,0,1,4,5,0. Wówczas największa suma trzech kolejnych liczb (zaznaczone na czerwono) wynosi:

Komentarze w PHP (niewykonywane fragmenty tekstowe, będące informacją dla programisty)

Struktury, unie, formatowanie, wskaźniki

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda.

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Struktury Struktura polami struct struct struct struct

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Proste programy w C++ zadania

C-struktury wykład. Dorota Pylak

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Wykład 7 Abstrakcyjne typy danych słownik (lista symboli)

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

W języku C/C++ pomiędzy wskaźnikami a tablicami istnieje bardzo ścisły związek. Do onumerowania elementów w tablicy służą tzw. INDEKSY.

Podstawy programowania C. dr. Krystyna Łapin

Podstawy programowania w języku C++

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

KURS C/C++ WYKŁAD 6. Wskaźniki

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Transkrypt:

Wykład 5. Operacje na tablicach 1. Opis i deklarowanie zmiennej tablicowej Tablica jest strukturą danych, zawierająca stałą liczbę elementów. Każdy z tych elementów jest jednakowego typu. Typem elementu tablicy może być typ znakowy, jeden z typów liczbowych, lub typ strukturalny. Można także utworzyć tablicę, której elementy także są tablicami będzie to tablica dwuwymiarowa. Na rysunku 1 pokazano tablicę, która zawiera 6 elementów typu int. Adresy elementów FFDC FFDE FFE0 FFE2 FFE4 FFE6 Przykładowa zawartość Odwołania do elementów -1 tab[0] 4 tab[1] -10 tab[2] 8 tab[3] 17 tab[4] 2 tab[5] Rys. 1. Struktura zmiennej tablicowej int tab[6] Deklaracja zmiennej tablicowej ma ogólną postać: typ_elementów_tablicy nazwa_zmiennej_tablicowej [rozmiar_tablicy]; Rozmiaru tablicy, czyli liczby jej elementów, nie można zmieniać w czasie wykonywania programu. Jest to wartość stała, którą można zapisać w postaci stałej jawnej lub stałej definiowanej. Definiując stałą dla rozmiaru tablicy posługujemy się typem całkowitym, lub specjalnie do tego przeznaczonym typem size_t. Na przykład tablica z rysunku 8.1 będzie zadeklarowana następująco: const int R=6; // lub: const size_t R=6; int tab[r];

2 Tablicę można zapełnić z klawiatury, lub za pomocą odpowiednich instrukcji programu. Początkowe wartości elementów można zainicjować przy deklarowaniu tablicy: int tab[r]=-1,4,-10,8,17,2; Jak widać, wartości elementów wpisuje się po znaku =, w postaci ich listy, ujętej w nawiasy klamrowe. Warto podkreślić, że liczba wpisanych wartości nie może być większa od rozmiaru tablicy. Jeżeli wpiszemy mniej niż R wartości, to pozostałe elementy tablicy będą równe zeru. 2. Odwoływanie się do elementów tablicy Chcąc odnieść się w jakimś wyrażeniu do określonego elementu tablicy, piszemy nazwę zmiennej tablicowej, a za nią, w nawiasach kwadratowych, numer pozycji, zwany indeksem. Na przykład, chcąc zapisać zero na pozycji 2 zmiennej tablicowej tab, napiszemy: tab[2]=0; Indeksem pierwszego elementu tablicy zawsze jest liczba 0. Ostatni element ma indeks R-1, gdzie R to rozmiar tablicy. Indeks elementu tablicy jest typu całkowitego. Może być stałą jawną, stałą definiowaną, zmienną, wyrażeniem. Przykład: Zamiana miejscami wartości na dwóch początkowych pozycjach tablicy tab: int tab[6],j=0,buf; buf=tab[j]; tab[j]=tab[j+1]; tab[j+1]=buf. Uwaga: Nie wolno przekraczać definiowanego zakresu indeksów! 3. Wskaźnikowe odwołania do elementów W języku C++ nazwa zmiennej tablicowej jest stałą wskaźnikową, która jest równa jest adresowi tej zmiennej: tab==&tab[0]

Adresy kolejnych elementów tablicy są odpowiednio przesunięte względem adresu elementu początkowego. Adres k-tego elementu tablicy o nazwie tab to: tab+k Pamiętajmy, że symbol + użyty w tym wyrażeniu nie oznacza dodawania, lecz przesunięcie o k elementów typu int względem adresu elementu początkowego &tab[0]. Pokazuje to rysunek 2. 3 Względne adresy elementów tab tab+1 tab+2 tab+3 tab+4 tab+5 Przykładowa zawartość -1 * tab Odwołania wskaźnikowe 4 * (tab+1) -10 * (tab+2) 8 * (tab+3) 17 * (tab+4) 2 * (tab+5) Rys. 2. Wskaźnikowe odwołania do tablicy int tab[6] Za pomocą wskaźników można odwoływać się do wskazywanych przez nie zmiennych, pisząc przed wskaźnikiem symbol *. Dwa sposoby odwołania się do k tego elementu tablicy: tab[k]=0; //odwołanie przez indeks *(tab+k)=0; //odwołanie przez wskaźnik

4 4. Tablica jako argument funkcji Argument tablicowy może mieć postać indeksową lub wskaźnikową. Przykład: Funkcja znajduje w tablicy tab[] liczbę elementów równych x. Wynik ile jest przekazywany przez referencję. Nagłówek funkcji: lub: void policz(int tab[],int r,int x,int &ile) void policz(int *tab,int r,int x,int &ile) Przez argument r przekazuje się rozmiar tablicy. Dzięki temu funkcja może operować na tablicach o różnej liczbie elementów. 5. Zapełnianie losowe tablicy i drukowanie jej zawartości. Przykład: Program z funkcjami własnymi operującymi na tablicy (zapełnianie losowe, wyprowadzanie na ekran) #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <time.h> void zaptablos(int[],int,int); void poktab(int[],int); int main(void) const int R=10; int tab[r]k; zaptablos(tab,r,100); poktab(tab,r); getch(); return 0; void zaptablos(int tab[],int r,int z) int j; srand(time(null)); //odwołania indeksowe for (j=0; j<r; j++) tab[j]=rand()%z;

5 void poktab(int *tab,int n) printf("\n\noto liczby w tablicy:\n\n"); //odwołania wskaźnikowe for (int j=0; j<n; j++) printf("%4d",*(tab+j)); /* void poktab(int *tab,int n) printf("\n\noto liczby w tablicy:\n\n"); //odwołania wskaźnikowe z operatorem ++ for (int j=0; j<n; j++) printf("%4d",*tab++); */ Argument tablicowy jest typu wskaźnikowego, jednak w instrukcji wywołanie przed identyfikatorem tab nie ma operatora adresu &. Nazwa tablicy z definicji jest adresem zmiennej tablicowej, dlatego operator & jest zbyteczny. 6. Sumowanie wartości elementów tablicy Przykład: Znajdowanie sumy elementów tablicy #include <conio.h> #include <stdio.h> long sumtab(int[],int); int main(void) const int R=10; int tab[r]=9,7,4,6,8,1,3,7,0,2; printf("\nsuma elementow: %ld",sumtab(tab,r)); getch(); return 0; long sumtab(int t[],int r) long s=0; for (int j=0;j<r;) s+=t[j++]; return s;

6 7. Zliczanie elementów o zadanych cechach Przykład poniżej pokazuje funkcję odd_even, która sprawdza, ile jej tablica wejściowa t zawiera wartości parzystych, a ile nieparzystych. Wyniki są przekazywane przez dwa argumenty wskaźnikowe p oraz n. Argumenty te służą jednocześnie jako liczniki elementów parzystych i nieparzystych. Dzięki temu nie trzeba deklarować dodatkowych zmiennych licznikowych. Przykład: Zliczanie elementów tablicy o wartościach parzystych i nieparzystych #include<stdio.h> #include<conio.h> void odd_even(int*,int,int*,int*); int main() const int R=12; int tab[r]=1,3,4,12,6,10,8,16,9,7,2,5; int parz, nieparz; odd_even(tab,r,&parz,&nieparz); printf("\nliczba parzystych: %d",parz); printf("\nliczba nieparzystych: %d",nieparz); getch(); return 0; void odd_even(int *t,int r,int *p,int *n) *n=*p=0; for(int j=0;j<r;j++) if(*(t+j)%2) (*n)++; else (*p)++; 8. Znajdowanie maksimum i minimum Znajdowanie w tablicy tab o rozmiarze r maksymalnej spośród pamiętanych w niej wartości przebiega według prostego algorytmu, pokazanego poniżej. int max=tab[0]; for (int j=1; j<r; j++) if (tab[j]>max) max=tab[j];

Przykład: Znajdowanie największego i najmniejszego elementu oraz liczby ich wystąpień w tablicy #include<stdio.h> #include<conio.h> void max_min(int[],int,int&,int&,int&,int&); int main() const int R=12; int tab[r]=1,3,4,16,6,1,8,16,9,7,16,5; int max,min,ilemax,ilemin; max_min(tab,r,max,min,ilemax,ilemin); printf("\nmaksimum: %3d Wystapien: %d",max,ilemax); printf("\nminimum: %3d Wystapien: %d",min,ilemin); getch(); return 0; 7 void max_min(int t[],int r,int &max,int &min, int &ilemax,int &ilemin ) max=min=t[0]; ilemax=ilemin=1; for(int j=1;j<r;j++) if (t[j]==max) ilemax++; else if(t[j]>max) ilemax=1; max=t[j]; if (t[j]==min) ilemin++; else if(t[j]<min) ilemin=1; min=t[j]; 9. Przesunięcie cykliczne zawartości tablicy Przesunięciem cyklicznym zawartości tablicy o jedną pozycję w prawo nazywamy taką zmianę jej zawartości, po której każdy element zajmuje miejsce jego sąsiada po prawej stronie, przy czym element ostatni zajmuje miejsce zerowego. Dla int tab[r] można to zrealizować za pomocą trzech instrukcji:

8 int buf=tab[r-1]; for (int j=r-1;j>0;j--) tab[j]=tab[j-1]; tab[0]=buf; Zmienna pomocnicza buf jest konieczna. Musimy w niej przejściowo zapamiętać ostatni element tablicy w przeciwnym przypadku jego wartość zostałaby utracona w wyniku zapisania do niego wartości elementu poprzedzającego. A przecież jest ona potrzebna, bo ma znaleźć się na zerowej pozycji tablicy. Chcąc przesunąć zawartość pozycji o p pozycji, trzeba pokazaną wyżej trójkę instrukcji powtórzyć p razy za pomocą zewnętrznej pętli for. tab[0] tab[1] tab[2] tab[3] tab[4] tab[5] 1 2 3 4 5 6 tab[0] tab[1] tab[2] tab[3] tab[4] tab[5] 6 1 2 3 4 5 Rys. 3. Przesunięcie cykliczne zawartości tablicy o jedną pozycję w prawo Przykład: Przesuwanie cykliczne zawartości tablicy w prawo #include<stdio.h> #include<conio.h> void cykl_prawo(int*,int,int); void poktab(int[],int); int main() const int R=8; int tab[r]=1,2,3,4,5,6,7,8; int p; printf("o ile pozycji? "); scanf("%d",&p); poktab(tab,r); cykl_prawo(tab,r,p); poktab(tab,r); getch(); return 0; void poktab(int t[],int r) printf("\n\noto liczby w tablicy:\n\n"); for (int j=0; j<r; j++) printf("%4d",*(t+j));

void cykl_prawo(int *t,int r,int p) int buf; for (int k=0;k<p;k++) buf=*(t+r-1); for(int j=r-1;j>0;j--) *(t+j)=*(t+j-1); *t=buf; 9 10. Sortowanie bąbelkowe tablicy Sortowaniem nazywamy porządkowanie zawartości tablicy w taki sposób, by kolejne elementy tablicy zawierały wartości uszeregowane w porządku rosnących lub malejących wartości. Przykład poniżej zawiera funkcję własną bubblesort. Funkcja ta realizuje sortowanie bąbelkowe tablicy, przekazanej jako argument t. Sortowanie przebiega w porządku rosnącym lub malejącym, w zależności od wartości argumentu p. Przykład: Sortowanie bąbelkowe tablicy #include<stdio.h> #include<conio.h> void poktab(int*,int); void bubble(int[],int,int); int main() const int R=8; int tab[r]=10,2,3,15,6,5,7,13; int p; poktab(tab,r); printf("\njaki porzadek? <1> rosnacy, <0> malejacy: "); scanf("%d",&p); bubble(tab,r,p); poktab(tab,r); getch(); return 0;

10 void poktab(int *t,int r) printf("\n\noto liczby w tablicy:\n\n"); for (int j=0; j<r; j++) printf("%4d",*(t+j)); printf("\n"); void bubble(int t[],int r,int p) int kopia,war; for (int j=0; j<r-1; j++) for (int k=j+1; k<r; k++) if (p!=0) war=t[j]>t[k]; else war=t[j]<t[k]; if (war) kopia=t[j]; t[j]=t[k]; t[k]=kopia; 11. Sortowanie rekurencyjne tablicy quick sort Podstawą algorytmu quick sort jest następujący pomysł: Jeden z elementów sortowanej tablicy wyróżnia się jako tzw. element osiowy. Pozostałe elementy dzielimy na dwie grupy. Do jednej z nich przenosimy elementy mniejsze od osiowego. Drugą grupę tworzą pozostałe elementy, większe od elementu osiowego lub mu równe. Następnie proces ten kontynuujemy rekursywnie, dzieląc w podobny sposób każdą z obu grup na podgrupy względem im właściwych elementów osiowych. Te podgrupy dzielimy dalej, dopóki kolejna podgrupa nie stanie się pojedynczym elementem wtedy dalszy podział jest niemożliwy. Algorytm quick sort jest znacznie bardziej efektywny od algorytmu bąbelkowego. Dla quick sort liczba operacji jest proporcjonalna do wyrażenia n*log(n), natomiast dla bubble sort wzrasta ona proporcjonalnie do n 2, gdzie symbol n oznacza rozmiar sortowanej tablicy. Poniżej pokazano sekwencję instrukcji, dzielącą tablicę na dwie grupy względem elementu t[0], który pełni rolę elementu osiowego. Zmienna j jest licznikiem indeksów, powiększanym o wartość 1 w każdym kolejnym cyklu pętli for. Zmienna m wskazuje numer elementu, który podlega kolejnej zamianie w procesie podziału grupy na dwie podgrupy.

Po kolei sprawdza się, czy j-ty element tablicy jest mniejszy od osiowego. Jeżeli ma to miejsce, następuje inkrementacja licznika m, a następnie element t[j] jest zamieniany miejscami z elementem t[m]. int t[12]=8,13,5,2,15,1,30,4,0,16,7,28; int m=0; for(int j=1;j<12;i++) if(t[j]<t[0]) m++; zamiana(t[m],t[j]); zamiana(t[m],t[0]); Ostatnia zamiana elementów, dokonywana już po zakończeniu instrukcji for, ma na celu przesunięcie elementu osiowego na właściwą pozycję. Przykład poniżej zawiera pełny program z rekurencyjną funkcją sortującą qsort. Po zakończeniu kolejnego podziału tablicy na dwa fragmenty względem elementu osiowego, funkcja qsort dwukrotnie wywołuje samą siebie, dzieląc względem odpowiednich elementów osiowych dwa fragmenty, otrzymane podczas pierwszego podziału. Proces ten jest kontynuowany rekursywnie tak długo, dopóki końcowe fragmenty nie zostaną zredukowane do pojedynczych elementów (rys. 4). 11 Przykład: Program sortujący tablicę zgodnie z algorytmem quick sort #include <conio.h> #include <stdio.h> void poktab(int[],int,int); void zamiana(int &,int &); void qsort(int[],int,int); int main() const int N=12; int t[n]=8,13,5,2,15,1,30,4,0,16,7,28; poktab(t,0,n-1); qsort(t,0,n-1); poktab(t,0,n-1); getch(); return 0; void poktab(int t[],int p,int k)

12 for(int j=p;j<=k;j++) printf("%4d",t[j]); printf("\n\n"); void zamiana(int &a, int &b) int buf=a; a=b; b=buf; void qsort(int t[],int left,int right) if (left<right) int m=left; for(int i=left+1;i<=right;i++) if (t[i]<t[left]) zamiana(t[++m],t[i]); zamiana(t[left],t[m]); qsort(t,left,m-1); qsort(t,m+1,right); Początkowa postać tablicy: t[0] t[1] t[2] t[3] t[4] t[5] t[6] t[7] t[8] t[9] t[10] t[11] 8 13 5 2 15 1 30 4 0 16 7 28 Porządkowanie wg elementów osiowych t[0] t[1] t[2] t[3] t[4] t[5] t[6] t[7] t[8] t[9] t[10] t[11] 7 5 2 1 4 0 8 15 13 16 30 28 t[0] t[1] t[2] t[3] t[4] t[5] t[7] t[8] t[9] t[10] t[11] 0 5 2 1 4 7 13 15 16 30 38 t[0] t[1] t[2] t[3] t[4] t[9] t[10] t[11] 0 5 2 4 1 16 30 28 t[1] t[2] t[3] t[4] t[10] t[11] 4 2 1 5 28 30 t[1] t[2] t[3] 1 2 4 t[1] t[2] 1 2 Końcowa postać tablicy:

t[0] t[1] t[2] t[3] t[4] t[5] t[6] t[7] t[8] t[9] t[10] t[11] 0 1 2 4 5 7 8 13 15 16 28 30 Rys.4. Kolejne podziały fragmentów tablicy w czasie pracy funkcji qsort 13 12. Tablica dwuwymiarowa Struktura i sposób deklarowania const int LW=3, LK=4; int tab[lw][lk]= 0, 1, 2, 3, 10,11,12,13, 20,21,22,23; int tab[3][4]; tab[0][0] tab[0][1] tab[0][2] tab[0][3] tab[0] 0 1 2 3 tab[1][0] tab[1][1] tab[1][2] tab[1][3] tab[1] 10 11 12 13 tab[2][0] tab[2][1] tab[2][2] tab[2][3] tab[2] 20 21 22 23 Rys.5. Tablica dwuwymiarowa Odwoływanie się do elementów Odwołanie za pomocą indeksów: tab[j][k]=0; gdzie j numer wiersza; k numer kolumny.

14 Odwołania wskaźnikowe: Interpretując j-ty wiersz jako jednowymiarową tablicę o nazwie tab[j], odwołamy się do elementu znajdującego się w j tym wierszu i k tej kolumnie, jak następuje: *(tab[j]+k)=0; Ponieważ odwołanie tab[j] zapisuje się wskaźnikowo jako *(tab+j), odwołanie wskaźnikowe do elementu tab[j][k] przyjmie ostatecznie postać: *(*(tab+j)+k)=0; Funkcje operujące na tablicy dwuwymiarowej Dla tablicy dwuwymiarowej argument tablicowy może mieć postać, jak w poniższym nagłówku funkcji: void poktab(int tab[][lk]) Występują tu dwie pary nawiasów kwadratowych. Zawartość pierwszej pary może być pusta; można też do nie wpisać liczbę wierszy tablicy. W drugiej parze nawiasów koniecznie należy wpisać liczbę kolumn (stała LK). Instrukcja wywołania funkcji poktab w main będzie wyglądać następująco: poktab(tab); W instrukcji wywołania przed nazwą tablicy nie ma operatora adresu, ponieważ ta nazwa jest właśnie przekazywanym adresem tablicy. Argument tablicowy może mieć postać wskaźnika na początkowy element tablicy: void poktab(int *t, int lw, int lk) Jako dodatkowe argumenty wykorzystano liczbę wierszy lw i liczbę kolumn lk. Takie podejście jest wygodniejsze, bo funkcja może operować na tablicach o dowolnej liczbie wierszy lub kolumn. Wywołanie funkcji poktab w main ma teraz postać:

poktab(&tab[0][0],lw,lk); Jak widać, w instrukcji wywołania wpisujemy po prostu adres początkowego elementu tablicy. W przykładzie poniżej pokazano proste funkcje stosujące oba rodzaje argumentów tablicowych i różne sposoby odwoływania się do elementów. Wspólną cechą jest to, że odwołują się do wszystkich elementów tablicy, wykorzystując dwie zagnieżdżone pętle for. Odwołania: Adresy Względne tab[0] int *t=&tab[0][0]; tab[0][0] *(*(tab+0)+0) 0 t tab[0][1] *(*(tab+0)+1) 1 (t+1) tab[0][2] *(*(tab+0)+2) 2 (t+2) tab[0][3] *(*(tab+0)+3) 3 (t+3) tab[1] tab[1][0] *(*(tab+1)+0) 10 (t+4) tab[1][1] *(*(tab+1)+1) 11 (t+5) tab[1][2] *(*(tab+1)+2) 12 (t+6) tab[1][3] *(*(tab+1)+3) 13 (t+7) tab[2] tab[2][0] *(*(tab+2)+0) 20 (t+8) tab[2][1] *(*(tab+2)+1) 21 (t+9) tab[2][2] *(*(tab+2)+2) 22 (t+10) tab[2][3] *(*(tab+2)+3) 23 (t+11) 15 Rys. 6. Ułożenie elementów tablicy dwuwymiarowej w pamięci

16 Przykład: Trzy różne funkcje wyprowadzające na ekran zawartość tablicy dwuwymiarowej i ich wywołania w main. #include <conio.h> #include <stdio.h> const int LW=3, LK=4; //stałe globalne void poktab1(int [][LK]); void poktab2(int [][LK]); void poktab3(int *,int,int); int main() int tab[lw][lk]= 0, 1, 2, 3, 10,11,12,13, 20,21,22,23;; poktab1(tab); poktab2(tab); poktab3(&tab[0][0],lw,lk); getch(); return 0; void poktab1(int t[][lk]) for(int j=0;j<lw;j++) for(int k=0;k<lk; k++) printf("%4d",t[j][k]); printf("\n"); printf("\n"); void poktab2(int t[][lk]) for(int j=0;j<lw;j++) for(int k=0;k<lk; k++) printf("%4d",*(*(t+j)+k)); printf("\n"); printf("\n"); void poktab3(int *t,int lw,int lk) for(int j=0;j<lw;j++) for(int k=0;k<lk;k++) printf("%4d",*t++); printf("\n"); printf("\n");

17 Przykład: Program pokazujący tablicę mnożenia liczb od 1 do 16 w zapisie dziesiętnym, ósemkowym lub szesnastkowym #include <conio.h> #include <stdio.h> char dane(); void poktab(int *,int,int,char); void zaptab(int *,int,int); int main() const int LW=16, LK=16; int tab_2[lw][lk]; zaptab(&tab_2[0][0],lw,lk); poktab(&tab_2[0][0],lw,lk,dane()); getch(); return 0; char dane() printf("\nwybierz podstawe zapisu.\n"); printf("p=10 - <d>, p=8 - <o>, p=16 - <x> : "); char b; do scanf("%c",&b); while (b!='o'&&b!='d'&&b!='x'); return b; void zaptab(int *m,int lw,int lk) for(int j=0;j<lw;j++) for(int k=0;k<lk;k++) *(m++)=(j+1)*(k+1); void poktab(int *m,int lw, int lk, char b) char s[4]='%','4',b,'\0'; printf("\ntablica mnozenia\n\n"); for(int j=0;j<lw;j++) for(int k=0;k<lk;k++) printf(s,*m++); printf("\n");

18 Wybierz podstawe zapisu. p=10 - <d>, p=8 - <o>, p=16 - <x> : x Tablica mnozenia 1 2 3 4 5 6 7 8 9 a b c d e f 10 2 4 6 8 a c e 10 12 14 16 18 1a 1c 1e 20 3 6 9 c f 12 15 18 1b 1e 21 24 27 2a 2d 30 4 8 c 10 14 18 1c 20 24 28 2c 30 34 38 3c 40 5 a f 14 19 1e 23 28 2d 32 37 3c 41 46 4b 50 6 c 12 18 1e 24 2a 30 36 3c 42 48 4e 54 5a 60 7 e 15 1c 23 2a 31 38 3f 46 4d 54 5b 62 69 70 8 10 18 20 28 30 38 40 48 50 58 60 68 70 78 80 9 12 1b 24 2d 36 3f 48 51 5a 63 6c 75 7e 87 90 a 14 1e 28 32 3c 46 50 5a 64 6e 78 82 8c 96 a0 b 16 21 2c 37 42 4d 58 63 6e 79 84 8f 9a a5 b0 c 18 24 30 3c 48 54 60 6c 78 84 90 9c a8 b4 c0 d 1a 27 34 41 4e 5b 68 75 82 8f 9c a9 b6 c3 d0 e 1c 2a 38 46 54 62 70 7e 8c 9a a8 b6 c4 d2 e0 f 1e 2d 3c 4b 5a 69 78 87 96 a5 b4 c3 d2 e1 f0 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0 100 Rys. 7. Wydruk tablicy mnożenia w zapisie szesnastkowym