Pliki Informacje ogólne Plik jest pewnym zbiorem danych, zapisanym w systemie plików na nośniku danych. Może posiadać określone atrybuty, a odwołanie do niego odbywa się poprzez nazwę. Każdy plik ma skończoną długość, a informacja w nim zapisana jest ciągiem zer i jedynek (bitów). Ze względu na sposób interpretowania zawartości pliku wyróżnić możemy: pliki tekstowe - poszczególne bajty w pliku można zinterpretować jako dane alfanumeryczne (znaki), zapisane przy pomocy określonego kodowania (np. ASCII). Takie pliki są "czytelne" dla człowieka po otwarciu w podstawowym edytorze tekstu (Notatnik, vim) lub bezpośrednim wypisaniu zawartości przy pomocy polecenia powłoki (type-windows, cat-linux). pliki binarne - poszczególne bajty w pliku mają dowolne wartości, niekoniecznie są interpretowalne jako znaki alfanumeryczne. Taki plik jest zazwyczaj nieczytelny dla człowieka po otwarciu w podstawowym edytorze tekstu. Struktura informacji w plikach binarnych jest ściśle określona przez oprogramowanie, które zapisuje tego typu pliki (np. określoną strukturę ma plik MS Word, MS Excel itp.). Programista chcący odczytać i właściwie zinterpretować w swoim programie dane z pliku binarnego, powinien znać jego strukturę. Obsługa plików w języku C Standardowa biblioteka wejścia/wyjścia języka C udostępnia funkcje do operowania na plikach, tj. odczytu i zapisu danych z plików tekstowych i binarnych. Sposób pracy z plikami w języku C jest następujący: 1. Otwarcie pliku o określonym nazwie w określonym trybie (odczyt, zapis, dopisywanie) Funkcja fopen, prototyp: FILE *fopen(const char *filename, const char *mode); Funkcja fopen otwiera plik, którego nazwa podana jest w pierwszym argumencie. Drugim jest łańcuch znaków zwierający litery oznaczające sposób otwarcia pliku: "r" - otwiera plik do czytania "r+" - otwiera plik do czytania i nadpisywania (aktualizacja) "w" - otwiera plik do nadpisywania (zamazuje starą treść) "w+" - otwiera plik do nadpisywania i czytania "a" - otwiera plik do dopisywania (jeśli plik nie istnieje, to jest tworzony) "a+" - otwiera plik do dopisywania i odczytu (jeśli plik nie istnieje, to jest tworzony) "t" - otwiera plik w trybie tekstowym "b" - otwiera plik w trybie binarnym Litery można ze sobą łączyć, np. "rwb" albo "wt". Funkcja zwraca wskaźnik do pliku (FILE *) lub NULL, gdy pliku nie udało się otworzyć (nie istnieje, jest już otwarty w innym programie itp..
Przykład wywołania: FILE *f = fopen("dane.txt", "rt"); 2. Wykonywanie operacji odczytu/zapisu Odczyt/zapis danych z pliku tekstowego Funkcje do formatowanego odczytu/zapisu. int fscanf(file *stream, const char *format,...); int fprintf(file *stream, const char *format,...); Funkcje działają tak jak scanf i printf, przy czym jako pierwszy argument przyjmują wskaźnik do pliku uzyskany w punkcie 1 (ogólnie - wskaźnik do strumienia danych). //odczyt liczby całkowitej z pliku int i; char lan[] = "Operacje plikowe" ; fscanf(f, "%d", &i); //zapis łańcucha znaków do pliku fprintf(f, "%s", lan); Odczyt/zapis łańcucha znaków char *fgets(char *str, int size, FILE *stream); int fputs (const char *s, FILE *stream); char lan_do_zapisu[] = "Operacje plikowe" ; char lan_do_odczytu[80]; //odczyt łańcucha fgets(lan_do_odczytu,f); //zapis łańcucha fputs(lan_do_zapisu,f); Odczyt/zapis pojedynczego znaku int fgetc ( FILE * stream ); int fputc ( int character, FILE * stream ); char znak2; //odczyt znaku
znak2=fgetc(f); //zapis znaku fputc('a',f); Odczyt/zapis danych z pliku binarnego //odczyt size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); //zapis size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); a) zapis łańcucha znaków do pliku binarnego char x[10]="abcdefghij"; FILE *fp; fp=fopen("test.bin", "wb"); fwrite(x, sizeof(x[0]), 10, fp); fclose(fp); b) odczyt liczby całkowitej z pliku binarnego int i; FILE *fp; fp=fopen("test.bin", "rb"); fread(&i, sizeof(i), 1, fp); fclose(fp); Pozostałe funkcje operujące na plikach //funkcja sprawdzająca, czy odczytano już cały plik int feof(file *stream); Przykład //wypisywanie zawartości pliku na konsolę char znak; while (!feof(f)) znak=fgetc(f); printf("%c",znak); //funkcja do zmiany odcztywanej/zapisywanej pozycji w pliku int fseek(file *file, long offset, int mode); //pobranie aktualnej pozycji w pliku long ftell(file *file);
3. Zamknięcie pliku int fclose (FILE *plik); Przykładowe programy wykonujące operacje na plikach a) wypisanie zawartości pliku tekstowego na ekran void main() char znak; FILE *plik= fopen("dane.txt", "rt"); if(!plik) printf("blad otwarcia pliku"); return; while (feof(plik) == 0) znak = fgetc(plik); printf("%c", znak); fclose(plik); // otworzenie pliku do odczytu b) zapis pobranych z klawiatury liczb do pliku tekstowego void main() int liczba; FILE *plik= fopen("liczby.txt", "wt"); if(!plik) printf("blad otwarcia pliku"); return; //wczytanie pierwszej liczby scanf("%d",&liczba); // otworzenie pliku do odczytu //wczytywane są liczby aż do wystąpienia 0 while (liczba!=0) fprintf(plik,"%d",liczba); scanf("%d",&liczba); fclose(plik);
Zadania 1. Napisz program zliczający i wypisujący na ekranie liczbę znaków w pliku tekstowym. 2. Zmodyfikuj program z punktu 1, aby zliczał tylko cyfry. 3. Napisz program wczytujący liczby całkowite (rozdzielone białymi znakami) z pliku tekstowego i obliczający ich sumę. 4. Napisz program wczytujący plik tekstowy i wypisujący na ekran każdy znak dwukrotnie. 5. Rozszerz program z punktu 4, aby znaki były dodatkowo zapisywane do pliku wyjściowego (innego niż wejściowy). 6. Napisz program zapisujący tablicę liczb zmiennoprzecinkowych do pliku tekstowego. 7. Napisz program zapisujący i odczytujący tablicę zmiennych typu strukturalnego z/do pliku.
Biblioteka standardowa 1. qsort (http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/) Sortuje elementy tablicy algorytmem quicksort. /* qsort example */ #include <stdlib.h> int values[] = 40, 10, 100, 90, 20, 25 ; int compare (const void * a, const void * b) return ( *(int*)a - *(int*)b ); int main () int n; qsort (values, 6, sizeof(int), compare); for (n=0; n<6; n++) printf ("%d ",values[n]); return 0; 2. bsearch (http://www.cplusplus.com/reference/clibrary/cstdlib/bsearch/) Wyszukuje element w tablicy. /* bsearch example */ #include <stdlib.h> int compareints (const void * a, const void * b) return ( *(int*)a - *(int*)b ); int values[] = 10, 20, 25, 40, 90, 100 ; int main () int * pitem; int key = 40; pitem = (int*) bsearch (&key, values, 6, sizeof (int), compareints); if (pitem!=null) printf ("%d is in the array.\n",*pitem); else printf ("%d is not in the array.\n",key); return 0;
Zadania 1. Zmodyfikuj programy przykładowe, aby sortowały i wyszukiwały dane w tablicach elementów typu double. 2. Zmodyfikuj programy przykładowe, aby sortowały i wyszukiwały dane w tablicach zdefiniowanych samodzielnie struktur.