PLIKI - opis funkcji
Transkrypt
PLIKI - opis funkcji
MATERIAŁY POMOCNICZE – PODSTAWY PROGRAMOWANIA
Na podstawie: „Programowanie w C”
- Stworzone na Wikibooks,
bibliotece wolny podręczników
Funkcja getchar()
Jest to bardzo prosta funkcja, wczytująca 1 znak z klawiatury. W wielu przypadkach dane
mogą być buforowane przez co wysyłane są do programu dopiero, gdy bufor zostaje
przepełniony lub na wejściu jest znak przejścia do nowej linii. Z tego powodu po wpisaniu
danego znaku należy nacisnąć klawisz enter, aczkolwiek trzeba pamiętać, że w następnym
wywołaniu zostanie zwrócony znak przejścia do nowej linii. Funkcja zwraca typ int int
getc(FILE *stream);
Gdy nastąpił błąd lub nie ma już więcej danych funkcja zwraca wartość EOF (która ma
jednak wartość logiczną 1 toteż zwykła pętla while (getchar()) nie da oczekiwanego
rezultatu):
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar())!=EOF) {
if (c==' ') {
c = '_';
}
putchar(c);
}
return 0;
}
Funkcja gets
Funkcja gets służy do wczytania pojedynczej linii. Przyjmuje ona jeden argument — adres
pierwszego elementu tablicy, do którego należy zapisać odczytaną linię. Z tego powodu nie
ma żadnej możliwości przekazania do tej funkcji rozmiaru bufora podanego jako argument.
Podobnie jak w przypadku scanf() może to doprowadzić do przepełnienia bufora, co może
mieć tragiczne skutki. Zamiast tej funkcji należy używać funkcji fgets().
char *gets(char *str);
Funkcja gets() czyta linię ze standardowego wejścia (usuwa ją stamtąd) i umieszcza ją w
tablicy znakowej wskazywanej przez str. Ostatni znak linii (znak nowego wiersza - '\n')
zastępuje zerem (znakiem '\0').
Funkcja fgets
Funkcja fgets() jest bezpieczną wersją funkcji gets(), która dodatkowo może operować na
dowolnych strumieniach wejściowych. Jej użycie jest następujące:
fgets(tablica_znaków, rozmiar_tablicy_znaków, stdin);
#include <stdio.h>
int main(void) {
char buffer[128], whole_line = 1, *ch;
while (fgets(buffer, sizeof buffer, stdin)) { /* 1 */
if (whole_line) { /* 2 */
putchar('>');
if (buffer[0]!='>') {
putchar(' ');
}
}
fputs(buffer, stdout); /* 3 */
for (ch = buffer; *ch && *ch!='\n'; ++ch); /* 4 */
whole_line = *ch == '\n';
}
if (!whole_line) {
putchar('\n');
}
return 0;
}
Czytanie i pisanie do plików
Nazwy funkcji z pierwszej grupy zaczynają się od litery “f” (np. fopen(), fread(), fclose()),
a identyfikatorem pliku jest wskaźnik na strukturę typu FILE. Owa struktura to pewna grupa
zmiennych, która przechowuje dane o danym pliku — jak na przykład aktualną pozycję w
nim. Szczegółami nie musisz się przejmować, funkcje biblioteki standardowej same zajmują
się wykorzystaniem struktury FILE, programista może więc zapomnieć, czym tak naprawdę
jest struktura FILE i traktować taką zmienną jako “uchwyt”, identyfikator pliku.
Dane znakowe
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE *fp; /* używamy metody wysokopoziomowej */
/* musimy mieć zatem identyfikator pliku, uwaga na
gwiazdkę! */
char tekst[] = "Hello world";
if ((fp=fopen("test.txt", "w"))==NULL) {
printf ("Nie mogę otworzyć pliku test.txt do zapisu!\n");
exit(1);
}
fprintf (fp, "%s", tekst); /* zapisz nasz łańcuch w pliku */
fclose (fp); /* zamknij plik */
return 0;
}
Funkcja fopen zwraca wskaźnik do struktury *FILE w przypadku poprawnego otwarcia pliku,
bądź też NULL, gdy plik nie może zostać otwarty.
Po zakończeniu korzystania z pliku należy plik zamknąć. Robi się to za pomocą funkcji
fclose.
Pliki a strumienie
Do zapisu do pliku używamy funkcji fprintf, która wygląda bardzo podobnie do printf —
jedyną różnicą jest to, że w fprintf musimy jako pierwszy argument podać identyfikator pliku.
Podobnie jak scanf i fscanf.
W rzeczywistości język C traktuje tak samo klawiaturę i plik — są to źródła danych, podobnie
jak ekran i plik, do których można dane kierować PLIKI NAZYWAMY STRUMIENIAMI
Każdy program w momencie uruchomienia “otrzymuje” od razu trzy otwarte strumienie:
• stdin (wejście)
• stdout (wyjście)
• stderr (wyjście błędów)
(aby z nich korzystać należy dołączyć plik nagłówkowy stdio.h)
fprintf (stdout, "Hej, ja działam!") = printf ("Hej, ja
działam!");
fscanf (stdin, "%d", &zmienna) = scanf("%d",
&zmienna);
Przykład:
…
printf("Wcisnij Ctrl+D+Enter lub Ctrl+Z+Enter aby
zakonczyc\n");
while ( (c = fgetc(stdin)) != EOF) {
fputc (c, stdout);
fputc (c, fp);
}
fclose(fp);
…
Rozmiar pliku
Dzięki standardowym funkcjom języka C możemy m.in. określić długość pliku. Do tego celu
służą funkcje fsetpos, fgetpos oraz fseek. Ponieważ przy każdym odczycie/zapisie z/do
pliku wskaźnik niejako “przesuwa” się o liczbę przeczytanych/zapisanych bajtów. Możemy
jednak ustawić wskaźnik w dowolnie wybranym miejscu.
int fseek(FILE *file, long offset, int mode);
Funkcja fseek ustawia pozycję w pliku file na offset w zależnośći od wartości argumentu
mode. Jeśli mode jest równy zero, to offset liczony jest od początku. Jeśli 1, to offset
przesuwany od aktualnej pozycji, a 2 przesuwany o offset od końca pliku (wskaźnik pliku jest
przesuwany do pozycji będącej sumą rozmiaru pliku i parametru offset).
Zwraca: Zero gdy funkcja wykonała się pomyślnie, w przypadku błędu wartość niezerowa.
int fsetpos (FILE* file, fpos_t* pos);
Funkcja fsetpos zmienia aktualną pozycję wskaźnika do pliku file na pos.
Zwaraca: Zero gdy funkcja wykonała się pomyślnie, EOF w przypadku wystąpienia błędu, k
int fgetpos (FILE* file, fpos_t* pos);
Funkcja fgetpos umieszcza w pos aktualną pozycję wskaźnika do pliku file.
Zwaraca: Zero gdy funkcja wykonała się pomyślnie, EOF w przypadku wystąpienia błędu
#include <stdio.h>
int main (int argc, char **argv)
{
FILE *fp = NULL;
int dlugosc;
if ((fp=fopen(“plik.txt”, "rb"))==NULL) {
printf ("Błąd otwarcia pliku: %s!\n",”plik.txt”);
return 1;
}
fseek (fp, 0, SEEK_END); /* ustawiamy wskaźnik na
koniec pliku */
fgetpos (fp, &dlugosc);
printf ("Rozmiar pliku: %d\n", dlugosc);
fclose (fp);
return 0;
}
Pliki binarne – np: pliki graficzne
Do zapisu :
nagłówka pliku używana jest funkcja fprintf,
tablicy do pliku używana jest funkcja fwrite.
Do odczytu:
nagłówka pliku używana jest funkcja fscanf,
tablicy do pliku używana jest funkcja fread.
size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
Argumenty:
ptr - wskaźnik na tablicę
size - rozmiar elementu tablicy
nitems - liczba elementów do zapisu
stream - plik, na którym wykonywana jest operacja
Opis
Funkcja fwrite kopiuje nitems elementów z poddanej tablicy do pliku. Kopiowanie kończy się
w przypadku wystąpienia błędu lub po skopiowaniu podanej liczby elementów. Wskaźnik
pliku jest przesuwany, tak by wskazywał pierwszy element po ostatnim zapisanym.
Wartość zwracana
Liczba faktycznie zapisanych elementów.
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
Argumenty:
ptr - wskaźnik na tablicę
size - rozmiar elementu tablicy
nitems - liczba elementów do odczytu
stream - plik, na którym wykonywana jest operacja
Opis
Funkcja fread kopiuje nitems elementów z podanego pliku do tablicy. Kopiowanie kończy się
w przypadku wystąpienia błędu, końca pliku lub po skopiowaniu podanej liczby elementów.
Wskaźnik pliku jest przesuwany, tak by wskazywał pierwszy nieodczytany element.
Wartość zwracana
Liczba faktycznie wczytanych elementów.
#include <stdio.h>
int main() {
const int dimx = 800;
const int dimy = 800;
int i, j;
FILE * fp = fopen("first.ppm", "wb"); /* b - tryb binarny */
fprintf(fp, "P6\n%d %d\n255\n", dimx, dimy);
for(j=0; j<dimy; ++j){
for(i=0; i<dimx; ++i){
static unsigned char color[3];
color[0]=i % 255; /* red */
color[1]=j % 255; /* green */
color[2]=(i*j) % 255; /* blue */
fwrite(color,1,3,fp);
}
}
fclose(fp);
return 0;
}
Inne przydatne funkcje:
long ftell(FILE *file);
Funkcja ftell zwraca aktualną pozycję wskaźnika pliku.
// ... - mamy otwarty plik i czytamy z niego dane
long offset = ftell(file); // 'file' to nasz plik
printf("Pozycja w pliku: %d\n", offset);
// ...
int feof(FILE *stream);
Funkcja zwraca wartość niezerową jeżeli napotka koniec pliku tekstowego.
#include <stdio.h>
int main()
{
int i=0;
int nr[32];
FILE *plik;
plik=fopen("numery.txt", "r");
while (feof(plik)==0)
{
fscanf(plik, "%d\n", &nr[i]);
printf("%d %d\n", i+1, nr[i]);
++i;
}
fclose(plik);
return 0;
}