background image

Algorytmy i struktury 

danych

WYKŁAD 6, cz.1

 

3   7   7   9   3   8   4

 

2   5   0   1   2   5

background image

2

Algorytmy i struktury, wykład 6, cz.1

Wykład 6: Sortowanie plików

obsługa plików binarnych – c.d.

sortowanie plików metodą łączenia prostego i 
łączenia naturalnego

background image

3

Algorytmy i struktury, wykład 6, cz.1

Zmiana bieżącego położenia w pliku

Zmiana tzw. bieżącej pozycji wstawiania lub czytania w pliku 
dokonywana jest automatycznie podczas wykonywania operacji 
zapisu lub odczytu albo poprzez wywołanie funkcji:

int fseek (FILE* 

file

, long 

offset

, int 

whence

);

W wypadku powodzenia wynikiem wykonania funkcji jest 
przesunięcie pozycji w pliku o wartość 

offset

 (może być dodatnia lub 

ujemna) względem pozycji określonej przez parametr 

whence

:

SEEK_SET – (0) – względem początku pliku

SEEK_CUR – (1) – względem aktualnej pozycji

SEEK_END – (2) – względem końca pliku

W przypadku powodzenia operacji przesunięcia funkcja zwraca 0, w  
przeciwnym wypadku – wartość <> 0 

background image

4

Algorytmy i struktury, wykład 6, cz.1

Zmiana bieżącego położenia w pliku

Zmiana pozycji w pliku możliwa jest również poprzez 
wywołanie funkcji:

int fgetpos (FILE* 

file

, fpos_t* 

pos

) – zwraca bieżącą pozycję w pliku 

wpisując ją do 
zmiennej 

pos

;

int fsetpos (FILE* 

file

, const fpos_t* 

pos

) – ustawia bieżącą pozycję 

w pliku zgodnie z wartością zmiennej 

pos

;

Obydwie funkcje w razie bezbłędnego wykonania zwracają wartość 
0, lub !=0 w przypadku wystąpienia błędu

long ftell (FILE* 

file

) – zwraca pozycję w pliku (w bajtach)

void rewind (FILE* 

file

) – ustawia pozycję na początek pliku; jej 

użycie jest równoznaczne z wywołaniem fseek(file, 0, SEEK_SET)

background image

5

Algorytmy i struktury, wykład 6, cz.1

Reagowanie na znak końca pliku

Podczas czytania zawartości plików fakt dotarcia do końca pliku 
można sprawdzić przy pomocy funkcji:

int feof (FILE* 

file

);

Zwraca ona:

wartość różną od 0 - jeżeli podczas czytania danych z pliku 
natrafiono na jego koniec (EOF – End Of File) 
0 – jeżeli nie natrafiono na koniec pliku

Czytając plik binarny lub plik znakowy o nieznanej długości należy 
realizować to w pętli, której zakończenie jest uwarunkowane 
napotkaniem znaku końca pliku, czy właśnie EOF

background image

6

Algorytmy i struktury, wykład 6, cz.1

Wyjście danych do pliku binarnego – zapis 

blokowy

Posługując się plikiem binarnym, do zapisu można posłużyć się 
funkcją:

size_t fwrite(const void *

ptr

, size_t 

size

, size_t 

n

, FILE* 

stream

);

ptr – wskaźnik na dowolny obiekt, adres początkowy 
zapisywanych danych

size – wielkość każdego zapisywanego elementu

n – liczba zapisywanych elementów

stream – uchwyt pliku do którego następuje zapis

Łączna liczba zapisanych bajtów jest równa (n * size)
W przypadku poprawnego wykonania funkcji zwraca ona w wyniku liczbę 
poprawnie zapisanych elementów (nie bajtów) równą n, w przypadku 
wystąpienia błędu – liczbę mniejszą od n

background image

7

Algorytmy i struktury, wykład 6, cz.1

Binarny zapis – przykład wyjścia danych z 

rekordu

 #include <stdio.h>

 struct teststruct
 { int i;
   char ch; };

 void main(void)
 {
    FILE *stream;
    struct teststruct s;

    if ((stream = fopen("TEST.DAT", "wb")) == NULL)
      fprintf(stderr, "Nie mozna otworzyc pliku\n");

    s.i = 0;
    s.ch = 'A';

    fwrite(&s, sizeof(s), 1, stream);

    fclose(stream);
}

Blokowe 

wyjście 

rekordu do 

pliku 

zewnętrznego 

skojarzonego 

ze zmienną 

„stream” 

background image

8

Algorytmy i struktury, wykład 6, cz.1

Binarne wejście – czyli jak odczytywać na 

przykład rekordy?

Posługując się plikiem binarnym, do odczytu danych można posłużyć 
się funkcją:

size_t fread ( void *

ptr

, size_t 

size

, size_t 

n

, FILE* 

stream

);

ptr – wskaźnik na strukturę w pamięci w której umieszczone 
mają być odczytane dane

size – wielkość odczytywanych elementów

n – liczba odczytywanych elementów

stream – uchwyt pliku z którego następuje odczyt

Łączna liczba odczytanych bajtów jest równa (n * size)
W przypadku poprawnego wykonania funkcji zwraca ona w wyniku liczbę 
poprawnie odczytanych elementów (nie bajtów) równą n, w przypadku 
wystąpienia błędu – liczbę mniejszą od n

background image

9

Algorytmy i struktury, wykład 6, cz.1

Binarny odczyt – przykład odczytu danych 

do rekordu

 #include <stdio.h>

 struct teststruct
 { int i;
   char ch; };

 void main(void)
 {
    FILE *moj_plik;
    struct teststruct s;

    if ((moj_plik = fopen("TEST.DAT", "rb")) == NULL)
      fprintf(stderr, "Nie mozna otworzyc pliku\n");

   fread(&s, sizeof(s), 1, moj_plik);

    fclose(moj_plik);
}

Blokowe wejście 

danych z pliku 

zewnętrznego 

skojarzonego ze 

zmienną 

„mój_plik” do 

rekordu s 

background image

10

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Zdefiniujmy typ strukturowy przechowujące dane 
osobowe:

Struct osoba {

Char imie[25];
Char nazwisko[35];
Char PESEL[11];
Unsigned int wiek;
Unsigned int wzrost;
Char plec;

};

Zdefiniowana 

struktura będzie 

podstawą dla 

konstruowanej 

kartoteki

Polami struktury 
mogą być tablice

Albo zmienne typu 

prostego

background image

11

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Załóżmy, że chcemy dodatkowo przechowywać dane 
adresowe dla każdej osoby. Definicja struktury dla 
adresu może być następująca:

Struct dane_adresowe {

Char ulica[40];
Char dom[4], lokal[4];
Char kod_p[6];
Char miejscowość[30];

};

Aby dołączyć dane adresowe do definicji struktury dla 
danych osobowych, trzeba zastosować struktury 
zagnieżdżone 

background image

12

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Po prostu jako jedno z pól struktury należy zdefiniować 
pole zdefiniowane jako dane_adresowe:

Struct osoba {

Char imie[25];
Char nazwisko[35];
Char PESEL[11];
Unsigned int wiek;
Unsigned int wzrost;
Char plec;

Struct dane_adresowe adres;

};

Pole strukturowe, 

zagnieżdżone 

wewnątrz struktury

Struktura 

dane_adresowe 

została 

zdefiniowana 

wcześniej

background image

13

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Zbudujmy zatem kartotekę danych osobowych, którą 
zorganizujemy w postaci tablicy, której elementem jest 
struktura:

Struct osoba kartoteka[30];

[0]

[1]

[2]

[29]

zagnieżdż

one dane 

adresowe

background image

14

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Aby wstawić lub odczytać wartość pola w tablicy 
struktur, należy wykorzystać zarówno indeksowanie i 
kropkę charakterystyczną dla referencji do struktur, np. 
polecenie:

kartoteka[1].imie=„Anna”;

Powoduje wstawienie na pozycji o indeksie ==1 w jej 

pole „imie” wartości „Anna”.

Podobnie działamy przy zagnieżdżonych strukturach 
będących elementami tablic:

kartoteka[23].adres.ulica=„Świeradowska”;

background image

15

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych

Do obsługi (wczytywania, wypisywania) danych w 
skojarzeniu z klawiaturą i monitorem, 
przechowywanych w kartotece można wykorzystać 
pętlę for. Robimy to na takich zasadach, o których 
mówiliśmy już przy okazji tablic, np..:

for(i=0; i<30; i++) {

gets(kartoteka[i].imie);
………
scanf(„%u”, &kartoteka[i].wiek);
………
gets(kartoteka[i].adres.miejscowość);
………

}

background image

16

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych, wczytanie danych z 

pliku do kartoteki

#include <stdio.h>

FILE *moj_plik;
struct osoba kartoteka[30];
int erob, poz;

main()
 { if ((moj_plik = fopen("TEST.DAT", "rb")) == NULL)
      fprintf(stderr, "Nie mozna otworzyc pliku\n");

   

erob = feof(moj_plik);

   poz = 0;

   while (erob =

 

= 0) {

    fread(&kartoteka[poz], sizeof(kartoteka[poz]), 1, moj_plik);
     poz++;
     erob = feof(moj_plik);
   } 

  fclose(moj_plik);
}

Blokowe wczytywanie 

rekordów do kartoteki

Detekcja końca pliku, z 

którego następuje 

wczytywanie danych

background image

17

Algorytmy i struktury, wykład 6, cz.1

Przykład – kartoteka danych 

osobowych, zapis danych z 

kartoteki do pliku

#include <stdio.h>

FILE *moj_plik;
struct osoba kartoteka[30];
int poz;

main()
 { if ((moj_plik = fopen("TEST.DAT", „wb")) == NULL)
      fprintf(stderr, "Nie mozna otworzyc pliku\n");

   

   for (poz=0; kartoteka[poz]; poz++) {
    fwrite(&kartoteka[poz], sizeof(kartoteka[poz]), 1, moj_plik);
   } 

  fclose(moj_plik);
}

Blokowy zapis 

kolejnych rekordów do 

pliku zewnętrznego

background image

18

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych

Podobnie, jak sortowaliśmy tablice sekwencyjne, tak 
również możemy sortować dane, które są 
przechowywane w plikach sekwencyjnych,

Oczywiście inne są metody sortowania danych, które 
są zgromadzone w plikach zewnętrznych,

Wynika to przede wszystkim z innej organizacji 
dostępu do danych, które są przechowywane w plikach 
zewnętrznych. gdzie ogranicza nas przed wszystkim 
ich sekwencyjność. Takiego ograniczenia nie mieliśmy 
w przypadku sortowania tablic

Poznamy dwie metody sortowania danych w plikach 
zewnętrznych (wg N.Wirtha), tj.:

METODĘ ŁĄCZENIA PROSTEGO

METODĘ ŁĄCZENIA NATURALNEGO

background image

19

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych METODĄ ŁĄCZENIA 

PROSTEGO

Metoda łączenia prostego polega na sukcesywnym 

dzieleniu danych w pliku na podciągi o ustalonej długości 

maksymalnej i łączeniu tych podciągów wraz z 

równoczesnych porządkowaniem zawartych w nich 

elementów w uporządkowane podciągi danych. Porządek 

ten może być dowolny, np. rosnący lub malejący

Zapis logiki algorytmu sortowania metodą łączenia 

prostego może być następujący:

              

co_ile = 1;

do {

                      dalej=0;

    rozdzielanie;
    if rozdzielono{                    

  

       łączenie;

                        dalej = 1;
                      }

    co_ile = 2 * co_ile;
}while (dalej=1);

background image

20

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych METODĄ ŁĄCZENIA 

PROSTEGO - niemalejące

Zawartość sortowanego pliku:

 

3   7   2   5   7   9   1   0   8   3   2   5  4

co_ile == 1  

-  ROZDZIELANIE SERII

:

 

3   2   7   1   8   2   4

 

7   5   9   0   3   5

co_ile == 1  

-  ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

3   7   2   5   7   9   0   1   3   8   2   5  4

13 wygenerowanych  

serii liczb, które 

potem będą łączone 

w ustalonym 

porządku sortowania

background image

21

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE PROSTE – niemalejące, 

krok 2

Zawartość sortowanego pliku:

co_ile == 2  

-  ROZDZIELANIE SERII

:

 

3   7   7   9   3   8   4

 

2   5   0   1   2   5

co_ile == 2  

-  ŁĄCZENIE SERII

 – w ustalonym porządku sortowania

:

 

2   3   5   7   0   1   7   9   2   3   5   8  4

 

3   7   2   5   7   9   0   1   3   8   2   5  4

7 wygenerowanych  

serii liczb, które 

potem będą łączone 

w ustalonym 

porządku sortowania

background image

22

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE PROSTE – niemalejące, 

krok 3

Zawartość sortowanego pliku:

co_ile == 4  

-  ROZDZIELANIE SERII

:

 

2   3   5   7   2   3   5   8 

 

0   1   7   9   4

co_ile == 4  

-  ŁĄCZENIE SERII

 – w ustalonym porządku sortowania

:

 

0   1   2   3   5   7   7   9   2   3   4   5  8

 

2   3   5   7   0   1   7   9   2   3   5   8  4

4 wygenerowane  

serie liczb, które 

potem będą łączone 

w ustalonym 

porządku sortowania

background image

23

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE PROSTE – niemalejące, 

krok 4

Zawartość sortowanego pliku:

co_ile == 8  

-  ROZDZIELANIE SERII

:

 

0   1   2   3   5   7   7   9 

 

2   3   4   5   8

co_ile == 8  

-  ŁĄCZENIE SERII

 – w ustalonym porządku sortowania

:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

 

0   1   2   3   5   7   7   9   2   3   4   5  8

2 wygenerowane  

serie liczb, które 

potem będą łączone 

w ustalonym 

porządku sortowania

background image

24

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE PROSTE – niemalejące, 

krok 5

Zawartość sortowanego pliku:

co_ile == 16  

-  ROZDZIELANIE SERII

:

NIE ROZDZIELONO SERII – KONIEC ALGORYTMU SORTOWANIA PLIKU METODĄ ŁĄCZENIA PROSTEGO

PLIK POSORTOWANY WYGLĄDA NASTĘPUJĄCO:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

 

0   1   2   2   3   3   4   5   5   7   7   8  9

 

0   1   2   2   3   3   4   5   5   7   7   8  9

background image

25

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych METODĄ ŁĄCZENIA 

NATURALNEGO

Metoda łączenia naturalnego polega na sukcesywnym 

dzieleniu danych w pliku na podciągi i łączeniu tych 

podciągów wraz z równoczesnych porządkowaniem 

zawartych w nich elementów. Nie ustala się długości 

tych podciągów – zależy to wyłącznie od ułożenia 

wartości sortowanych elementów

Zapis logiki algorytmu sortowania metodą łączenia 

naturalnego może być następujący:

              

do {

                      dalej=0;

    rozdzielanie;
    if rozdzielono{                    

  

       łączenie;

                        dalej = 1;
                      }

}while (dalej=1);

background image

26

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych METODĄ ŁĄCZENIA 

NATURALNEGO-1 - niemalejące

Zawartość sortowanego pliku:

 

3   7   2   5   7   9   1   0   8   3   2   5  4

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

3   7             1         3        4

 

2   5   7   9   0   8    2   5

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

2   3   5   7   7   9   0   1   8   2   3   5  4

7 serii, które 

ułożyły się w 

porządku 

niemalejącym

background image

27

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-1 – 

niemalejące, krok 2

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

2   3   5   7   7   9   2   3   5 

 

0   1   8                               4 

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

0   1   2   3   5   7   7   8   9   2   3   4  5

4 serie, które 

ułożyły się w 

porządku 

niemalejącym

 

2   3   5   7   7   9   0   1   8   2   3   5  4

background image

28

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-1 – 

niemalejące, krok 3

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

0   1   2   3   5   7   7   8   9 

 

2   3   4   5 

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

2 serie, które 

ułożyły się w 

porządku 

niemalejącym

 

0   1   2   3   5   7   7   8   9   2   3   4  5

background image

29

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-1 – 

niemalejące, krok 4

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

 

0   1   2   2   3   3   4   5   5   7   7   8  9

NIE ROZDZIELONO SERII – KONIEC ALGORYTMU SORTOWANIA PLIKU METODĄ ŁĄCZENIA NATURALNEGO-1

PLIK POSORTOWANY WYGLĄDA NASTĘPUJĄCO:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

background image

30

Algorytmy i struktury, wykład 6, cz.1

Sortowanie danych w plikach 

zewnętrznych METODĄ ŁĄCZENIA 

NATURALNEGO-2 - niemalejące

Zawartość sortowanego pliku:

 

3   7   2   5   7   9   1   0   8   3   2   5  4

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

3   7             1         3        4

 

2   5   7   9   0   8                  2   5

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

2   3   5   7   7   9   0   1   3   4   8   2  5

Połączenie 

podciągów w 

jeden ciąg 

niemalejący

różnica 

pomiędzy 

łączeniem 

naturalnym w 

wersji 1 i 2

background image

31

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-2 – 

niemalejące, krok 2

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

2   3   5   7   7   9    2  5

 

0   1   3   4   8 

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

0   1   2   3   3   4   5   7   7   8   9   2  5

 

2   3   5   7   7   9   0   1   3   4   8   2  5

3 serie, które 

ułożyły się w 

porządku 

niemalejącym

background image

32

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-2 – 

niemalejące, krok 3

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

0   1   2   3   3   4   5   7   7   8  9

 

2   5

ŁĄCZENIE SERII – 

w ustalonym porządku sortowania

:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

2 serie, które 

ułożyły się w 

porządku 

niemalejącym

 

0   1   2   3   3   4   5   7   7   8   9   2  5

background image

33

Algorytmy i struktury, wykład 6, cz.1

ŁĄCZENIE NATURALNE-2 – 

niemalejące, krok 4

Zawartość sortowanego pliku:

ROZDZIELANIE SERII – podciągi o wartościach niemalejących

:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

 

0   1   2   2   3   3   4   5   5   7   7   8  9

NIE ROZDZIELONO SERII – KONIEC ALGORYTMU SORTOWANIA PLIKU METODĄ ŁĄCZENIA NATURALNEGO-2

PLIK POSORTOWANY WYGLĄDA NASTĘPUJĄCO:

 

0   1   2   2   3   3   4   5   5   7   7   8  9

background image

34

Algorytmy i struktury, wykład 6, cz.1

Podsumowanie

Poznaliśmy kolejne istotne elementy dotyczące obsługi 

plików binarnych,

Nauczyliśmy się zapisywać i odczytywać dane na styku 

pliku i rozbudowanej tablicy struktur. Jest to dobry 

wstęp do obsługi kartotek w języku C

Poznaliśmy wybrane zagadnienia dotyczące sortowania 

plików (czy potrafisz napisać odpowiedni program 

sortujący pliki?)

Przestudiuj samodzielnie metodę polifazowego 

sortowania plików – to też może być przydatne

To już wszystkie wiadomości na wykładzie z AiSD. 

Teraz należy przygotować się do rozliczenia z 

przedmiotu.

Dziękuję za uwagę


Document Outline