Informacje ogólne Obsługa plików w języku C

Transkrypt

Informacje ogólne Obsługa plików w języku C
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).
Przykłady
//odczyt liczby całkowitej z pliku
int i;
char lan[] = { "Operacje plikowe" };
FILE *f = fopen("dane.txt", "wt");
fscanf(f, "%d", &i);
//zapis łańcucha znaków do pliku
fprintf(f, "%s", lan);
//zamknięcie pliku
fclose(f);
Odczyt/zapis łańcucha znaków
char *fgets(char *str, int size, FILE *stream);
int fputs (const char *s, FILE *stream);
Przykłady
char lan_do_zapisu[] = { "Operacje plikowe" };
char lan_do_odczytu[80];
FILE *f = fopen("dane.txt", "wt");
//odczyt łańcucha
fgets(lan_do_odczytu,f);
//zapis łańcucha
fputs(lan_do_zapisu,f);
//zamknięcie pliku
fclose(f);
Odczyt/zapis pojedynczego znaku
int fgetc ( FILE * stream );
int fputc ( int character, FILE * stream );
Przykłady
char znak2;
FILE *f = fopen("dane.txt", "wt");
//odczyt znaku
znak2=fgetc(f);
//zapis znaku
fputc('a',f);
//zamknięcie pliku
fclose(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);
Przykłady
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;
FILE *f = fopen("dane.txt", "wt");
while (!feof(f))
{
znak=fgetc(f);
printf("%c",znak);
}
//zamknięcie pliku
fclose(f);
//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
#include <stdio.h>
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
#include <stdio.h>
void main()
{
int liczba;
FILE *plik= fopen("liczby.txt", "wt");
if(!plik)
{
printf("Blad otwarcia pliku");
return;
}
//wczytanie pierwszej liczby
scanf("%d",&liczba);
//wczytywane są liczby aż do wystąpienia 0
while (liczba!=0)
{
fprintf(plik,"%d",liczba);
scanf("%d",&liczba);
}
fclose(plik);
// otworzenie pliku do odczytu
}
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 <stdio.h>
#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 <stdio.h>
#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.