Przetwarzanie plików
Marek Deutsch
wat-wdp@wp.pl
/* sort_def.h */
#if !defined(__sort_def_H)
#define __sort_def_H
const Dl_string = 20;
const Maks_il_graczy = 10;
enum T_pozycje {srodkowy,skrzydlowy,rozgrywajacy};
typedef struct T_koszykarz {
char imie[Dl_string];
char nazwisko[Dl_string];
int wzrost;
T_pozycje gra_na;
};
...
#endif /* __sort_def_H */
Struktury
danych
-
przypomnienie
/* sort_io.h */
#if !defined(__sort_io_H)
#define __sort_io_H
#include "sort_def.h"
void wczytaj_kosz(T_koszykarz *k);
void wczytaj_druzyne_kosz(T_druzyna_kosz *d_k);
void wypisz_kosz(T_koszykarz *k);
void wypisz_druzyne_kosz(T_druzyna_kosz *d_k);
#endif /* __sort_io_H */
Operacje wejścia/wyjścia dla struktur
- przypomnienie
/* plik_io.h */
#if !defined(__plik_io_H)
#define __plik_io_H
int listowanie_pliku(
FILE *plik
, char *nazwa);
int wyszukiwanie_wg_nazwisk(
FILE *plik
, char *nazwa);
int dopisywanie_do_pliku(
FILE *plik
, char *nazwa);
#endif /* __plik_io_H */
Typ plikowy
int listowanie_pliku(FILE *plik, char *nazwa)
{
T_koszykarz el;
...
plik = fopen(nazwa,"rb");
if (
plik == NULL
) {
return(0);
}
while (
fread(&el,sizeof(T_koszykarz),1,plik) == 1
) {
...zrób coś z odczytanym el...
}
fclose(plik);
return(1);
}
Odczyt z pliku
plik = fopen(nazwa,"rb");
if (plik == NULL)
...
fopen otwiera plik w określonym trybie:
„rb” – do odczytu plik binarny
„rt” – do odczytu plik tekstowy
Zwraca wskaźnik na plik (obszar sterujący pliku, strumień) lub
NULL w przypadku niepowodzenia.
ilosc_odczytanych_rek = fread(&el,sizeof(T_koszykarz),1,plik)
...
fread czyta rekordy:
„&el” – pod wskazany adres
„sizeof(T_koszykarz)” – rekordy o wskazanym rozmiarze
„1” – zadaną ilość rekordów
„plik” – z pliku (wskaźnik strumienia wejściowego)
Zwraca ilość odczytanych rekordów (lub 0).
fclose(plik);
...
fclose zamyka wskazany plik.
Odczyt z pliku
int dopisywanie_do_pliku(FILE *plik, char *nazwa)
{
T_koszykarz el;
...
plik = fopen(nazwa,"ab");
if (
plik == NULL
) {
plik = fopen(nazwa,"wb");
if (
plik == NULL
)
return(0);
}
do {
...wypełnij el...
ilosc =
fwrite(&el,sizeof(T_koszykarz),1,plik)
;
if (ilosc != 1)
return(0);
}
while (...);
fclose(plik);
return(1);
}
Zapis do pliku
plik = fopen(nazwa,„wb");
if (plik == NULL)
...
fopen otwiera plik w określonym trybie:
„wt” – do zapisu plik tekstowy (tworzy plik)
„ab” – do aktualizacji plik binarny (dopisywanie)
Zwraca wskaźnik na plik (obszar sterujący pliku, strumień) lub
NULL w przypadku niepowodzenia.
ilosc_zapisanych_rek = fwrite(&el,sizeof(T_koszykarz),1,plik)
...
fwrite zapisuje do pliku:
„&el” – spod wskazanego adresu
„sizeof(T_koszykarz)” – rekordy o wskazanym rozmiarze
„1” – zadaną ilość rekordów
„plik” – do pliku (wskaźnik strumienia wyjściowego)
Zwraca ilość zapisanych rekordów (lub 0).
fclose(plik);
...
fclose zamyka wskazany plik.
Zapis do pliku
dl_serii = 1;
do {
rozdzielanie;
if (rozdzielono)
łączenie;
dl_serii = 2 * dl_serii;
} while (rozdzielono);
Sortowanie plików
Łączenie proste
3 7 2 5 7 9 1 0 8 3 2 5 4
3 7 2 5 7 9 0 1 3 8 2 5 4
3 2 7 1 8 2 4
7 5 9 0 3 5
3 7 7 9 3 8 4
2 5 0 1 2 5
rozdzielenie
dl_serii = 1
łączenie
rozdzielenie
dl_serii = 2
3 7 2 5 7 9 1 0 8 3 2 5 4
3 7 2 5 7 9 0 1 3 8 2 5 4
3 2 7 1 8 2 4
7 5 9 0 3 5
3 7 7 9 3 8 4
2 5 0 1 2 5
rozdzielenie
dl_serii = 1
łączenie
rozdzielenie
dl_serii = 2
2 3 5 7 0 1 7 9 2 3 5 8 4
2 3 5 7 2 3 5 8
0 1 7 9 4
łączenie
rozdzielenie
dl_serii = 4
int sortowanie_pliku(FILE *plik, char *nazwa)
{
int dl_serii;
int rozdzielono;
FILE *plik1, *plik2;
dl_serii = 1;
do {
/* otwórz plik do odczytu oraz plik1 i plik2 do zapisu */
rozdzielono = rozdzielanie(plik,plik1,plik2,dl_serii);
/* zamknij pliki */
if (rozdzielono) {
/* otwórz plik do zapisu oraz plik1 i plik2 do odczytu */
laczenie(plik,plik1,plik2,dl_serii);
/* zamknij pliki */
}
dl_serii = dl_serii*2;
} while(rozdzielono);
return(1);
}
Procedura sortowania
Łączenie proste
int rozdzielanie(FILE *pl_wej,FILE* pl_wyj_1,FILE *pl_wyj_2,int dl_serii)
{
T_koszykarz el;
int ilosc, seria, odp;
odp = 0; /* wskaźnik rozdzielenia */
do {
seria = 0; /* przepisanie serii na pierwszy plik */
do {
ilosc = fread(&el,sizeof(T_koszykarz),1,pl_wej);
if(ilosc == 1) {
fwrite(&el,sizeof(T_koszykarz),1,pl_wyj_1);
seria++;
}
} while((seria < dl_serii) && (ilosc == 1));
if(ilosc == 1) {
seria = 0; /* przepisanie serii na drugi plik */
do {
ilosc = fread(&el,sizeof(T_koszykarz),1,pl_wej);
if(ilosc == 1) {
fwrite(&el,sizeof(T_koszykarz),1,pl_wyj_2);
seria++;
odp = 1;
/* sygnalizacja rozdzielenia */
}
} while((seria < dl_serii) && (ilosc == 1));
}
} while(ilosc == 1);
return(odp);
}
Procedura rozdzielania
void laczenie(FILE *pl_wyj, FILE* pl_wej_1, FILE *pl_wej_2, int dl_serii)
{
T_koszykarz el_1, el_2;
int ilosc_1, ilosc_2, seria_1, seria_2;
ilosc_1 = fread(&el_1,sizeof(T_koszykarz),1,pl_wej_1);
ilosc_2 = fread(&el_2,sizeof(T_koszykarz),1,pl_wej_2);
do {
/* przepisanie serii na plik łączony */
seria_1 = 0; seria_2 = 0;
while((seria_1 < dl_serii) && (seria_2 < dl_serii) &&
(ilosc_1 == 1) && (ilosc_2 == 1)) {
if(el_1.wzrost > el_2.wzrost) {
fwrite(&el_1,sizeof(T_koszykarz),1,pl_wyj);
seria_1++;
ilosc_1 = fread(&el_1,sizeof(T_koszykarz),1,pl_wej_1);
}
else {
...zapis elementu z drugiego pliku...
}
}
/* przepisanie końcówki serii */
while((ilosc_1 == 1) && (seria_1 < dl_serii)) {
fwrite(&el_1,sizeof(T_koszykarz),1,pl_wyj);
seria_1++;
ilosc_1 = fread(&el_1,sizeof(T_koszykarz),1,pl_wej_1);
}
...przepisanie końcówki z drugiego pliku...
} while((ilosc_1 == 1) || (ilosc_2 == 1));
}
Procedura łączenia
do {
rozdzielanie;
if (rozdzielono)
łączenie;
} while (rozdzielono);
Sortowanie plików
Łączenie naturalne
3 7 2 5 7 9 1 0 8 3 2 5 4
2 3 5 7 7 9 0 1 3 4 8 2 5
3 7
1 3 4
2 5 7 9 0 8 2 5
2 3 5 7 7 9 2 5
0 1 3 4 8
rozdzielenie
łączenie
rozdzielenie
0 1 2 3 3 4 5 7 7 8 9 2 5
0 1 2 3 3 4 5 7 7 8 9
2 5
łączenie
rozdzielenie