Informatyka 05 06 2012

background image

Ć

wiczenia 12 VI 2012


REKORDY (STRUKTURY)

W tablicach mieliśmy do czynienia z elementami tego samego typu, natomiast tutaj możemy łączyć różne
typy danych. Matematycznie, możemy to potraktować jako iloczyn kartezjański, tzn.
Mając dane zbiory Z

1

, ..., Z

n

możemy utworzyć iloczyn kartezjański Z

1

x...xZ

n

. Wówczas element ma postać:

(z

1

,...,z

n

). Każdy taki ciąg nazywamy rekordem. W tym przypadku można wybrać operator pozwalający

pobrać poszczególne wartości. Operator ten wybiera z rekordu (z1,...,zn) np. i-tą składową. W tablicy
mogliśmy za pomocą pętli for oraz indeksu (liczba całkowita) wykonać potrzebne operacje, natomiast w
przypadku rekordu, identyfikatory stanowią nieuporządkowany zbiór różnych nazw, nie tworząc ustalonego
typu danych. Składowe rekordów należy nazywać oddzielnie nie mogąc się do nich odwoływać kolejno.
Rekordy warto stosować wówczas, gdy chcemy operować złożoną strukturą danych mając do niej dostęp
przez jedną zmienną. Struktury są deklarowane ze słowem kluczowym struct. Deklaracja ma postać: struct
nazwa;
Natomiast jej definicja: struct nazwa { /*...*/ };
Zauważmy, że nazwa jest nazwą nowo zdefiniowanego typu. Na końcu struktury dajemy średnik po
nawiasie klamrowym.

Przykład

#include <cstdlib>
#include <iostream>

using namespace std;

background image


struct pracownik {
char *tytul_stopien;
char *nazwisko;
int wiek, liczba_publikacji; };
int main() {

pracownik prac;

prac.tytul_stopien ="Dr";

prac.nazwisko = "Jan Nowak";

prac.wiek = 35;

prac.liczba_publikacji = 32;

cout <<"info1 : "<<prac.tytul_stopien <<endl;

cout <<"info2 : "<<prac.nazwisko << endl;

cout <<"info3 : "<<prac.wiek<< endl;

cout <<"info4 : "<<prac.liczba_publikacji <<endl;

system("PAUSE");
return EXIT_SUCCESS;
}

Szczególną uwagę przy korzystaniu z rekordów należy zwrócić na zgodność typów. Każda deklaracja
struktury wprowadza nowy, niepowtarzalny typ, np.
struct sI { int n ; };
struct sII { int m ; };
są to dwa różne typy, stąd w deklaracjach

background image

sI a,b ;
sII c ;
zmienne a oraz b są tego samego typu sI, ale c już nie!
Wobec tego przypisania
a=b;
b=a;
są poprawne!
a = c;
nie jest poprawne!
Natomiast przypisania składowych rekordów o tych samych typach są poprawne, np.
a.i = b.j;

WSKAŹNIKI

Do tej pory deklarowaliśmy np.
int i;
rezerwując miejsce w pamięci dla zmiennej i typu całkowitego.
Wskaźnik (ang. pointer) jest to specjalny rodzaj zmiennej, w której zapisany jest adres w pamięci
komputera, tzn. wskaźnik wskazuje miejsce, gdzie zapisana jest jakaś informacja (stąd nazwa zmienna
wskaźnikowa).
Adres to pewna liczba całkowita, w sposób jednoznaczny definiująca położenie pewnego obiektu (np.
liczby, znaku, struktury czy tablicy) w pamięci komputera. Wskaźnik ma ścisłą kontrolę typów i z tego
powodu nie tylko wskazuje miejsce zajmowane przez zmienną, ale także ile bajtów ta zmienna potrzebuje,
Definicja zmiennej typu wskaźnikowego ma następującą strukturę:
typ *identyfikator_zmiennej;

background image


Przykład:
int *i; (zapis może być różny: int *i1; int * i2; int* i3; int*i4;)
float *x;
float *x,y;

Jak już wspominaliśmy, operator & służy do pobrania adresu miejsca w pamięci, gdzie istnieje dana
zmienna, jest nazywany referencją a operator * jest nazywany operatorem dereferencji lub wskaźnikiem.

Przykład

#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
int i=3;
int *j;
j=&i; //przypisanie zmiennej, która przechowuje adres adresu zmiennej i
cout<<"wartosc liczby j="<<*j<<endl;
cout<<"adres liczby i ="<<&i<<endl;

system("PAUSE");

background image

return EXIT_SUCCESS;
}

Inicjalizacja wskaźnika może być wykonana następująco:
int *wsk = NULL;

(NULL oznacza element nie istniejący)

int *wsk = 0;

Przy tworzeniu i używania wskaźników łatwo można popełnić błąd. Jeżeli zaniedbamy przypisanie
wskaźnikowi adresu.
int *wskaznik_numer;
*wskaznik_numer = 1532;
Jest to błąd, ponieważ nie wiemy co oznacza komórka o adresie 1532, może się okazać, iż adres ten jest już
zajęty przez program, wówczas nie będzie można zapisać nic w miejsce wskazane przez wskaznik_numer
(jest on dość trudny do wykrycia).

TABLICE-WSKAŹNIKI

Przykład:

#include <cstdlib>
#include <iostream>

using namespace std;

int main()

background image

{ int x[15];
int k;
cout<<"podaj rozmiar swojej tablicy"<<endl;
cin>>k;

for (int i=0; i<k; i++)
x[i]=rand()%100;
for (int i=0; i<k; i++)
cout<<"x "<<i<<"= "<<*(x+i)<<"* "<<x[i]<<endl;

system("PAUSE");
return EXIT_SUCCESS;
}

Zadanie 10.1 (domowe):

Posługując się tablicą z rekordami – zaprojektuj listę towarów strukturze: dostawca (rekord), rodzaj towaru
(art. papiernicze, zabawki, etc.), ilość, cena, dzień tygodnia, w którym realizowana jest dostawa, itd. Dla
wszystkich przypadków wprowadź przykładowe dane.

SORTOWANIE BĄBELKOWE

Porównywane są kolejne elementy tablicy i jeśli elementy są w nieodpowiedniej kolejności, to są one
zamieniane miejscami. Jeśli sortowana struktura danych posiada k elementów to aby sprawdzić wszystkie
elementy musi być wykonane k-1 porównań. W najmniej korzystnym przypadku element, który powinien

background image

znaleźć się na początku tablicy znajduje się na końcu. Ponieważ przy jednym sprawdzeniu element może się
przesunąć tylko o jedno miejsce to musimy wykonać k-1 sprawdzeń listy, czyli zostanie wykonanych (k-1)

2

porównań. W trakcie zamiany wartości w tablicy wykorzystywana jest zmienna pomocnicza, nazwijmy ją
np. tmp.

Przykład:

int i, j, k, x, tmp;
int tablica[10];

cout << "Podaj ilość liczb : \n";
cin>>k;
cout << "Podaj elementy swojej tablicy: \n";

for (i=0; i<k; i++)
cin >>tablica[i];

for (i=0;i<k; i++)
for (j=0;j<k; j++)
if (tablica[j]>tablica[j+1])
{
tmp = tablica[j];
tablica[j] = tablica[j+1];
tablica[j+1] = tmp;
}

background image


for (i=0; i<=4; i++) /* wyświetlanie posortowanych liczb */
cout << tablica[i] << " , "<<endl;

system("pause");
return 0;
}

TABLICE DYNAMICZNE

Ich pamięć i wymiar są alokowane podczas pracy programu. Dynamiczna alokacja tablicy jednowymiarowej

może wyglądać (przy użyciu słowa kluczowego new) następująco:


int * tablica;
tablica = new int[rozmiar];

gdzie rozmiar jest wyrażeniem typu int.
lub

int *tablica= new int [rozmiar];

Każdą zadeklarowaną tablicę należy „zlikwidować” tzn. zwolnić zajętą przez nią pamięć:

background image

delete [] tablica;

Pamięć komputera nie jest nieograniczona. Trzeba się z tym liczyć i sprawdzać czy operacja się powiodła


float *wsk;
wsk=new float[8192];
if(!wsk) //czyli if(wsk==NULL)
{

cout<< ”Pamiec wyczerpana”;}


Przykład: Dynamiczna alokacja tablicy jednowymiarowej:

#include <iostream>
using namespace std;

main()
{
int *T; // tworzymy wskaźnik
int i,n;
cin >> n; // odczytujemy ilość komórek
T = new int[n]; // tworzymy tablicę dynamiczną o n komórkach
for(i = 0; i < n; i++)
cin >> T[i]; // wczytujemy kolejne komórki

background image

for(i = 0; i < n; i++)// wypisujemy odczytaną tablicę
cout << endl << "T[" << i << "] = " << T[i];
cout << endl;

system("PAUSE");
}

Zadanie 10.2 (domowe):

Zadeklarować dynamiczną jednowymiarową tablicę elementów typu rzeczywistego, wypełnić ją danymi a
następnie: posortować tablicę rosnąco, malejąco, podać wartość mediany.

Przykład: Dynamiczna alokacja tablicy dwuwymiarowej:

#include <iostream>
using namespace std;

main()
{
int **tablica;
int l_wierszy=5,l_kolumn=6;
tablica=new int*[ l_wierszy];

for(int i=0;i< l_wierszy;i++)
tablica[i]=new int[l_kolumn];

background image


//I teraz już mamy tablicę tablica[5][6];i możemy ją wypełnić

for(int i=0;i< l_wierszy; i++)

for(int j=0;j< l_kolumn; j++)

cin>>tablica[i][j];


cout<<tablica[3][4];

for(int i=0;i< l_wierszy;i++)// zwolnienie pamięci
delete []tablica [i];
delete []tablica;
}

Funkcja (czasami zwana procedurą) to fragment programu, któremu nadano odrębną nazwę (powinna
mówić o jej działaniu), dzięki czemu może być wykonywany poprzez podanie nazwy oraz ewentualnych
argumentów. Argumentami są natomiast dane przekazywane do funkcji.
Budowa funkcji:
typ_zwracanej_wartosci_z_funkcji nazwa_funkcji( typ_argumentu_1 nazwa_argumentu_1 ,…,
typ_argumentu_m nazwa_argumentu_m ).

{
return zwracana_wartosc

;

}

background image

Słowem kluczowym return regulujemy, co ma zostać zwrócone przez funkcję.

Wywoływanie funkcji

Polega na wpisaniu jej nazwę i przekazaniu wartości do funkcji:
nazwa_funkcji( wartosc_argumentu_1 ,…, wartosc_argumentu_m );

Przykład (bez argumentów i zwracania wartości)

#include <cstdlib>
#include <iostream>

using namespace std;

int gwiazdki(int ile)
{

int i ;

for(i = 0 ; i < ile ; i++)

{

cout << " * " ;

}

return 13 ;

}

int main()

background image

{

int m = 100 ;

cout << "Zaczynamy" << endl ;

m = gwiazdki(20) ;

cout << "\nNa wyjsciu zmiana wartosci i m = " << m <<endl;

system("PAUSE");
return EXIT_SUCCESS;
}

Przykład 2 (tym razem ze zwracaniem wartości)

I sposób realizacji

#include <cstdlib>
#include <iostream>

using namespace std;

int kukulka(int ile) //
{ //

int i ;

for(i = 0 ; i < ile ; i++)

{

background image

cout << "Ku-ku ! " ;

}

return 77 ; //

}
/**************************************************/
int main()
{

int m = 20 ;

cout << "Zaczynamy" << endl ;

m = kukulka(5) ; //

cout << "\nNa koniec m = " << m ; //

system("PAUSE");
return EXIT_SUCCESS;
}

II sposób realizacji

#include <cstdlib>
#include <iostream>

using namespace std;

int gwiazdki(int ile);

background image


int main()
{

int m = 100 ;

cout << "Zaczynamy" << endl ;

m = gwiazdki(20) ;

cout << "\nNa wyjsciu zmiana wartosci i m = " << m <<endl;

system("PAUSE");
return EXIT_SUCCESS;
}


int gwiazdki(int ile)
{

int i ;

for(i = 0 ; i < ile ; i++)

{

cout << " * " ;

}

return 13 ;

}

background image

Czas życia zmiennych w funkcjach

Zmienne, które zostały utworzone w funkcji są tymczasowe, pojawiają się do użycia przy każdorazowym
wywołaniu funkcji a znikają po jej opuszczeniu. Zmienne te nie zachowują niczego z poprzedniego.

Przykład 3

#include <cstdlib>
#include <iostream>

using namespace std;

float mnozenie_liczb()
{ float a, b;
cin >> a;
cin >> b;
return a * b;
}

int main()
{

cout << "Prosze podac dwie liczby: ";

float wynik = mnozenie_liczb();
cout << "Wynik dzialania wynosi: " << wynik << endl;

background image

system("PAUSE");
return EXIT_SUCCESS;
}

Zadanie 10.3:

Napisać program, który odwołując się do funkcji potega (zdefiniowanej przed programem) dla liczb
całkowitych z określonego przedziału, policzy wszystkie potęgi od 2 do 5.

Zadanie 10.4:

Napisać program, który odwołując się do funkcji silnia (zdefiniowanej przed programem) dla wczytanej
liczby naturalnej policzy silnię.


Wyszukiwarka

Podobne podstrony:
Informatyka 12 06 2012
MPLP 344;345 24.05.;05.06.2012
912 PSI 2012 v 05 06 2012 id 48 Nieznany
31 05 2012 10 09 2012 1 06 2012
Informatyka0 05 2012
ZAPYTANIE OFERTOWE tabliczka informacyjna przedszkole (1), Przegrane 2012, Rok 2012, mail 18.05 Wart
Informatyka, Wykład informatyka 2012-05-23, 2012-05-23
31 05 2012 10 09 2012 1 06 2012
2012 05 06 Rozdarte dzieci rozwodników
2012 05 06 Zaskakująće odkrycie ws popędu seksualnego
2012 05 06 Radom Kolejny gwałt w szpitalu psychiatrycznym
Fizyka 0 wyklad organizacyjny Informatyka Wrzesien 30 2012
prez UZ 4FD Iseria 05 06
05 09 2012 INTERNA
wyklad 2 c.d.- 05.03.2012, ALMAMER Fizjoterapia, Masaż

więcej podobnych podstron