Praca na plikach możliwa jest dzięki funkcjom dostępnym w bibliotece stdio.h
.
Chcąc odczytać dane z pliku (lub zapisać dane do pliku) najpierw należy uzyskać dostęp
do pliku za pomocą funkcji fopen()
,
która otwiera plik i zwraca zmienną typu FILE*
.
Uzyskany w ten wskaźnik daje dostęp do pliku pozwalając na
sekwencyjny odczyt lub zapis danych do wskazanego pliku. Jest on argumentem wszystkich funkcji operujących
na plikach. Po zakończeniu pracy na pliku należy go zamknąć za pomocą funkcji fclose()
.
Przydatne funkcje
fopen()
, fclose()
- otwieranie i zamykanie plikufgetc()
, fputc()
- odczyt i zapis znaku (bajtu)fgets()
- odczyt linii tekstufscanf()
, fprintf()
- odczyt i zapis formatowany (np. liczby)fread()
, fwrite()
- odczyt i zapis ciągu bajtów
Funkcja fopen
otwiera plik o nazwie nazwa_pliku
.
FILE *fopen(char *nazwa_pliku, char *tryb);
Pierwszy argument nazwa_pliku
jest napisem zawierającym ścieżkę do pliku. Może to być ścieżka bezwzględna
(np. w Windows "C:\\Users\a.txt"
, w Unix/Linux "/home/user/a.txt"
) lub względna zależna od bieżącego katalogu roboczego.
Jeżeli podamy tylko nazwę pliku (bez pełnej ścieżki) to powinien on się znajdować w tym samym
katalogu co plik wykonywalny.
Argument tryb
to napis, który określa tryb dostępu do pliku.
Oto lista dostępnych trybów dla plików tekstowych:
Tryb | ||
---|---|---|
"r" | Odczyt pliku od początku. Jeżeli plik nie istnieje to funkcja fopen zwróci NULL . | |
"w" | Zapis (nadpisz od początku) Jeżeli plik nie istnieje to zostanie utworzony. Jeżeli plik istnieje to jego zawartość zostanie skasowana | |
"a" | Dodaj na końcu |
Uwaga: w przypadku wystąpienia błędu przy próbie uzyskania dostępu do pliku funkcja fopen
zwraca wartość NULL
. Przyczyną błędu może być zła nazwa pliku lub niepoprawna ścieżka, brak
uprawnień do otwierania (lub edycji) pliku lub nawet brak miejsca na nośniku.
Ponieważ tego typu sytuacje mogą występować często dlatego należy zawsze sprawdzić czy
operacja fopen
zakończyła się sukcesem.
Po zakończeniu pracy na pliku należy go zamknąć za pomocą funkcji fclose
int fclose (FILE *plik);
Pojedynczy znak z pliku możemy pobrać za pomocą funkcji fgetc
.
int fgetc(FILE *f);
Argumentem funkcji jest wskaźnik f
do pliku uzyskany wcześniej za pomocą fopen
. Plik powinien być otworzony w trybie do odczytu.
Funkcja fgetc
zwraca wartość EOF
, gdy strumień danych z pliku jest pusty (koniec pliku).
Funkcja fputc
umieszcza znak c
w pliku f
int fputc(char c, FILE* f);
Funkcja feof
pozwala sprawdzić, czy podczas odczytu pliku f
dotarliśmy do jego końca.
int feof(FILE *plik);
Funkcja zwraca wartość 1 gdy osiągnięto koniec pliku, w przeciwnym wypadku zwracana jest wartość 0.
Poniższy program odczytuje wszystkie znaki (bajty) z pliku plik.txt
i wyświetla je na ekranie.
Jeżeli plik wejściowy nie istnieje lub gdy nastąpił jakikolwiek błąd przy otwieraniu pliku wówczas wyświetlany jest komunikat o błędzie i program kończy swoje działanie.
#include<stdio.h> int main() { FILE *plik = NULL; int znak; plik = fopen( "plik.txt", "r" ); if( plik == NULL ) { printf("Wystapil blad otczytu pliku\n"); return 1; } while( feof(plik) == 0 ) { znak = fgetc(plik); if (znak != EOF) printf("%c", znak); } fclose( plik ); return 0; }
Przykładowy plik wejściowy: plik.txt. Należy umieścić go w katalogu w którym znajduje się plik wykonywalny programu.
Napisz program, który wypisze na wyjściu zawartość pliku o nazwie plik.txt
w liniach o długości N
znaków. Wartość N
podaje użytkownik na początku działania programu. Wynik zapisz również w pliku o nazwie wynik.txt
.
Dane: liczba całkowita N
oraz plik z tekstem
Wynik: zawartość pliku wyświetlona na ekranie oraz zapisana do pliku wynik.txt
, gdzie wiersze mają długość N
znaków.
Przykład
Jeżeli plik wejściowy zawiera tekst:
The origin of C is closely tied to the development of the Unix operating system
to po uruchomieniu programu uzyskamy wynik:
n=2 Th e or ig in o f C is ...
Funkcja fgets
odczytuje linię tekstu z pliku.
char* fgets (char *s, int n, FILE *f);
Funkcja czyta linię tekstu z pliku f
i umieszcza ją w postaci napisu (dodaje znak '\0
') w tablicy s
. Argument n
ogranicza maksymalna liczbę znaków jaką wczyta funkcja zapobiegając przepełnieniu bufora dla zbyt długich linii wejściowych, tzn. funkcja przeczyta maksymalnie n-1
znaków.
Wartością zawracana jest s
lub wartość NULL
, gdy nastąpi koniec pliku lub błąd odczytu.
Jest to więc odpowiednik funkcji czytaj_linie
z poprzednich zajęć, z tą różnicą, że gets()
operuje na strumieniu f
, zaś czytaj_linie()
pobiera tekst ze standardowego wejścia.
Uwaga: funkcja fgets()
pozostawia znak '\n
' na końcu napisu.
W pliku stdio.h
zadeklarowane są zmienne, które dają dostęp do strumieni standardowych procesu:
Poniższy program wypisuje ponumerowane linie pliku o nazwie podanej przez użytkownika.
Nazwa pliku wejściowego odczytywana jest za pomocą fgets()
ze standardowego wejścia stdin
.
#include<stdio.h> #include<string.h> #define MAX 1000 int main() { char linia[MAX]; int i=1, n; FILE *plik; printf("Podaj nazwe pliku: "); fgets(linia, MAX, stdin); /* usuwanie znaku '\n' z konca napisu */ n = strlen(linia); linia[n-1] = '\0'; plik = fopen(linia, "r"); if(!plik) { printf("Blad odczytu pliku: %s\n", linia); return 1; } i = 0; while(fgets(linia, MAX, plik) != NULL) { printf("%d : %s", i, linia); i++; } fclose(plik); }
Napisz program, który wyszuka w pliku tekstowym linie zawierające podany wzorzec. Program pobiera od użytkownika 2 linie tekstu, pierwsza zawiera nazwę pliku wejściowego a druga - wzorzec do wyszukiwania. Następnie z podanego pliku wypisuje te linie, które zawierają wzorzec. Jeśli podany plik nie istnieje to program wypisuje stosowny komunikat błędu i kończy swoje działanie.
Wskazówka: do wyszukiwania wzorca w tekście można użyć funkcję strstr()
Przykład działania
Dla pliku o nazwie abacus.txt
' zawierającego tekst
The abacus, also called a counting frame, is a calculating tool that was in use in the ancient Near East, Europe, China, and Russia, centuries before the adoption of the written Hindu–Arabic numeral system. The exact origin of the abacus is still unknown.
oraz wprowadzonych przez użytkownika danych postaci
podaj nazwe pliku: abacus.txt podaj wzorzec: abacus
program wypisze
The abacus, also called a counting frame, is a calculating tool The exact origin of the abacus is still unknown.
Funkcja fprintf
służy do zapisu tekstu do pliku z formatowaniem.
Jej działanie jest takie samo jak funkcji printf()
z jedną rożnica - formatowany tekst zamiast na ekran trafia do pliku f
otworzonego w trybie do zapisu.
int fprintf(FILE *f, char *format, ...);
Poniższy program demonstruje zapis wartości całkowitej 42, wartości rzeeczywistej 4.13 oraz napisu "Witaj swiecie"
do pliku o nazwie "output.txt"
.
#include<stdio.h> int main() { int a = 42; float x = 3.14; char napis[]="Witaj swiecie\n"; FILE* plik; plik = fopen("output.txt", "w"); if (plik) { fprintf(plik, "a = %d\n", a); fprintf(plik, "x = %f\n", x); fprintf(plik, "%s\n", napis); fclose(plik); } else printf("Blad zapisu do pliku\n"); return 0; }
Do odczytu z pliku danych z uwzględnieniem ich formatowania służy funkcja fscanf
. Działa ona identycznie jak znana nam już funkcja scanf
, z tą rożnica, że
odczyt danych następuje z pliku f
otworzonego w trybie do odczytu.
int fscanf(FILE *f, char *format, ...);
Poniższy program demonstruje sposób użycia funkcji fscanf
do odczytania danych zapisanych za pomocą programu z poprzedniego przykładu.'
#include<stdio.h> int main() { int a; float x; char napis[100]; FILE* plik; plik = fopen("output.txt", "r"); if (!plik) { printf("Blad odczytu do pliku\n"); return 1; } fscanf(plik, "a = %d\n", &a); fscanf(plik, "x = %f\n", &x); fgets(napis, 100, plik); fclose(plik); printf("a = %d\n", a); printf("x = %f\n", x); printf("%s\n", napis); return 0; }
Przykładowy plik z danymi do odczytu: output.txt
Więcej informacji o funkcjach służących do manipulacji na plikach znajdziesz w dokumentacji biblioteki stdio.h
Napisz program, który zaszyfruje zawartość pliku tekstowego poprzez zamianę miejscami kolejnych par znaków (bajtów). Jeżeli plik wejściowy zawiera nieparzystą liczbę znaków, wówczas ostatni znak pozostaje na swoim miejscu. W przypadku problemów z odczytaniem pliku wejściowego program wyświetla stosowny komunikat błędu i kończy swoje działanie. Nazwę pliku wejściowego (lub ścieżkę do pliku) oraz nazwę pliku docelowego (do którego zostanie zapisany wynik) podaje użytkownik na początku działania programu.
Dane wejściowe programu
Wynik działania: powstaje plik docelowy z zaszyfrowaną zawartością pliku źródłowego lub pojawia sie komunikat błędu, jeżeli plik źródłowy nie istnieje lub nie można odczytać jego zawartości.
Przykład
Jeżeli w katalogu roboczym znajduje sie plik input.txt
o treści:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
to uruchomienie programu z następującymi danymi:
Podaj nazwe pliku zrodlowego: input.txt Podaj nazwe pliku docelowego: output.txt
utworzy plik o nawie output.txt
zawierający taką treść
oLer mpius modol ris tmate ,ocsnceetut rdapisiicgne il,ts ded oiesuom detpmroi cndidinu ttul baro eted loro eamng alaqiau.
Rozwiązanie umieść w Moodle pod adresem: https://moodle.umk.pl/WFAIIS/mod/assign/view.php?id=2151