• Nie Znaleziono Wyników

ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików

N/A
N/A
Protected

Academic year: 2022

Share "ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików"

Copied!
7
0
0

Pełen tekst

(1)

ISO/ANSI C

Dostęp do plików

• Plik to uporządkowany ciąg danych

• Dostęp do danych w pliku jest sekwencyjny,

tj. istnieje pojęcie elementu aktualnego (tzw. wskaźnika pliku). Możliwy dostęp do danych w pliku jest tylko tam, gdzie wskazuje wskaźnik. Można dokonać przesunięcia wskaźnika elementu aktualnego

lub też przenieść go od razu na początek lub koniec całego pliku.

• Do elementów pliku nie można się odwoływać tak swobodnie, jak do elementów tablicy – tj. po indeksie

© UKSW, WMP. SNS, Warszawa 71

ISO/ANSI C – dostęp do plików

FILE* - wskaźnik na strukturę zawierającą informacje o pliku, do których samodzielnie programista nigdy się nie odwołuje; FILE to alias, który zastępuje nazwę tej struktury.

Nigdy nie deklaruje się w programie zmiennej typu FILE. Taka zmienna tworzona jest na żądanie jako dynamiczna, a program korzysta wyłącznie ze wskaźnika na tę zmienną.

Otwieranie pliku:

FILE *fopen(const char *nazwapliku, const char *tryb);

Jeżeli zwrócona wartość nie jest NULL, to znaczy, że plik udało się pomyślnie otworzyć

72

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

FILE *fopen( const char *nazwapliku, const char *tryb );

<stdio.h>

tryby otwarcia:

r– do odczytu

w– do zapisu (jeżeli plik o podanej nazwie już istniał, to jest kasowany) a– do pisania na końcu pliku (dołączania), jeżeli coś w nim już było zapisane

(jeżeli taki plik nie istnieje – tworzy nowy) r+- do odczytu i zapisu (plik musi już istnieć)

w+- do odczytu i zapisu (plik nie może jeszcze istnieć, jeżeli istnieje, to istniejąca wersja jest kasowana)

a+- do odczytu i dołączania (jeżeli plik nie istnieje, jest tworzony) Jaka jest różnica między ‘a’ i ‘a+’?

73

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

FILE *fopen( const char *nazwapliku, const char *tryb );

<stdio.h>

tryby otwarcia:

r– do odczytu

w– do zapisu (jeżeli plik o podanej nazwie już istniał, to jest kasowany) a– do pisania na końcu pliku (dołączania), jeżeli coś w nim już było zapisane

(jeżeli taki plik nie istnieje – tworzy nowy) r+- do odczytu i zapisu (plik musi już istnieć)

w+- do odczytu i zapisu (plik nie może jeszcze istnieć, jeżeli istnieje, to istniejąca wersja jest kasowana)

a+- do odczytu i dołączania (jeżeli plik nie istnieje, jest tworzony) Jaka jest różnica między ‘a’ i ‘a+’?

Aby odpowiedzieć, najpierw należy coś wyjaśnić.

© UKSW, WMP. SNS, Warszawa 74

ISO/ANSI C – dostęp do plików

Przykład: IBM System/360. Nie ma jeszcze monitora, dlatego ..

© UKSW, WMP. SNS, Warszawa 75

70 71

72 73

74 75

(2)

Tryb dostępu do plików: tekstowy vs. binarny

W trybie tekstowym istnieje specjalny znak oznaczający koniec pliku (EOF):

1. Unix – Ctrl-D (kod ASCII 04) 2. Win – Ctrl-Z (kod ASCII 26)

(ale getchar() zwróci -1, kiedy napotka EOF) oraz dwa znaki: CR i LF (kody ASCII: 13 i 10) razem oznaczające koniec linii.

Otwarcie pliku w trybie tekstowym sprawia, że:

1. najpierw w pliku znajdowane jest pierwsze wystąpienie EOF i usuwane.

Po zakończeniu pracy w chwili zamknięcia pliku EOF jest dodawany na końcu pliku

2. każdorazowe wczytanie z pliku pary znaków CR-LF powoduje zwrócenie programowi tylko LF. Odwrotnie, wysyłanie do pliku tylko LF (znak ‘\n’) powoduje w rzeczywistości zapisanie w pliku CR-LF

© UKSW, WMP. SNS, Warszawa 76

Tryb dostępu do plików: tekstowy vs. binarny

Otwarcie pliku w trybie binarnym sprawia, że żadne manipulacje ze znakami EOF ani CR-LF opisane na poprzednim slajdzie nie są wykonywane.

Uwagi:

Otwarcie w trybie binarnym może zostać wymuszone poprzez dopisanie znaku ‘b’ w definicji trybu otwarcia, np. ‘rb’, natomiast w trybie tekstowym – znaku ‘t’, np. ‘rt’

Jeżeli tryb otwarcia nie jest podany jawnie, domyślnie tryb jest odczytywany ze zmiennej globalnej ‘_fmode ’. Domyślnym ustawieniem tej zmiennej w systemie jest wartość _O_TEXT ,

co oznacza tryb tekstowy.

© UKSW, WMP. SNS, Warszawa 77

ISO/ANSI C – dostęp do plików

Wróćmy do pytania: jaka jest różnica między ‘a’ i ‘a+’?

‘a+’ pozwala również na odczyt, ale przy każdej próbie zapisu wskaźnik pliku jest automatycznie przesuwany na koniec pliku, tak aby żadne dane nie zostały utracone (w innych trybach przejście z odczytu na zapis często wymaga ręcznego przesunięcia wskaźnika pliku – będzie o tym na następnych slajdach).

78

© UKSW, WMP. SNS, Warszawa

‘a’ – otwiera plik w trybie pisania na końcu pliku, ale nie usuwa znaku EOF, tylko dopisuje nowe dane od razu (jak w trybie binarnym)

‘a+’ – otwiera plik w trybie czytania i dołączania, usuwa znak EOF na końcu pliku, a następnie dopisuje (jak w trybie tekstowym).

Opis wg MSDN (niejasny i częściowo nieprawdziwy)

UWAGA

W dalszej części będziemy zajmować się wyłącznie trybem tekstowym, który nie wymaga żadnych szczególnych ustawień w wywołaniach funkcji bibliotecznych bo jest trybem domyślnym.

79

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

Otwieranie pliku – przykład:

FILE* stream;

if((stream = fopen( "crt_fopen.c", "r" )) == NULL) printf("Pliku 'crt_fopen.c' nie otwarto\n");

else

printf("Plik 'crt_fopen.c' został otwarty\n");

© UKSW, WMP. SNS, Warszawa 80

ISO/ANSI C – dostęp do plików

Otwieranie i zamykanie pliku – przykład:

int fclose( FILE *stream ); <stdio.h>

FILE* stream;

if((stream = fopen("foo.c", "r")) == NULL) printf("Pliku 'foo.c' nie otwarto\n" );

else

printf("Plik 'foo.c' został otwarty\n");

if(fclose( stream ))

printf("Plik 'foo.c' nie został zamknięty\n");

© UKSW, WMP. SNS, Warszawa 81

76 77

78 79

80 81

(3)

Formatowane czytanie z pliku otwartego w trybie tekstowym

• Po otwarciu pliku otrzymujemy prawo dostępu do tekstu w pliku.

• Dane reprezentowane są jako strumień znaków.

• Po otwarciu mamy prawo do odczytu pierwszego elementu w pliku (pierwszego znaku).

• Aktualną pozycję w pliku, z której w danej chwili mamy prawo czytać, określa wskaźnik pliku.

• Po odczycie wskaźnik pliku przesuwa się w przód o tyle bajtów, ile zostało odczytanych.

• Wskaźnika nie można cofać (!).

© UKSW, WMP. SNS, Warszawa 82

Formatowane czytanie z pliku

int fscanf( FILE *stream,

const char *format [, argument ]... );

FILE *stream;

char s[50];

if((stream = fopen( "crt_test.txt","r")) == NULL) exit( 0 );

fscanf( stream, "%s", s ); /* łańcuch tekstowy do pierwszej spacji */

fclose( stream );

© UKSW, WMP. SNS, Warszawa 83

ISO/ANSI C – dostęp do plików

Formatowane zapisywanie do pliku

int fprintf( FILE *stream,

const char *format [, argument ] ... );

FILE *stream;

char s1[] = "I am Groot!";

char s2[] = "I thought it was a good plan.";

char c = '\n';

if((stream = fopen("crt_test.txt","a+" )) == NULL) exit( 0 );

fprintf( stream, "%s%c", s1, c );

fprintf( stream, "%s", s2 );

fclose( stream );

84

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

Odczyt z pliku o nieznanym rozmiarze

int feof( FILE *stream);

Przykład:

FILE *stream;

char buf[20];

if((stream = fopen("abc.txt", "r")) == NULL) exit( 0 );

fscanf(stream, "%s", buf);

while (!feof(stream)) { printf("%s", buf);

fscanf(stream, "%s", buf);

}

fclose(stream);

return 0;

85

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

Odczyt z pliku o nieznanym rozmiarze

int feof( FILE *stream);

• feof sprawdza stan flagi w strumieniu stream.

• Aby zwrócił wartość 1, flaga musi być zapalona.

• Aby flaga była zapalona, znak EOF musi zostać pobrany z pliku.

Ostatnie znaki w pliku – dwa przypadki:

1.

2.

fscanf(stream, "%s", buf); // odczyt słowa: Groot!

1. Pobranie znaku końca linii kończy wczytywanie słowa,

2. Pobranie znaku EOF kończy wczytywanie słowa – flaga jest zapalana (!)

© UKSW, WMP. SNS, Warszawa 86

ISO/ANSI C – dostęp do plików

Odczyt z pliku o nieznanym rozmiarze

FILE *stream;

char buf[20];

if((stream = fopen("abc.txt", "r")) == NULL) exit( 0 );

fscanf(stream, "%s", buf); // fscanf #1 while (!feof(stream)) {

printf("%s\n", buf);

fscanf(stream, "%s", buf); // fscanf #2 }

fclose(stream);

return 0;

1. 2.

© UKSW, WMP. SNS, Warszawa 87

82 83

84 85

86 87

(4)

Odczyt z pliku o nieznanym rozmiarze

FILE *stream;

char buf[20];

if((stream = fopen("abc.txt", "r")) == NULL) exit( 0 );

while (!feof(stream)) {

fscanf(stream, "%s", buf); // fscanf #1 printf("%s\n", buf);

}

fclose(stream);

return 0;

1. 2.

© UKSW, WMP. SNS, Warszawa 88

Odczyt z pliku o nieznanym rozmiarze

FILE *stream;

char buf[20];

if((stream = fopen("abc.txt", "r")) == NULL) exit( 0 );

while (!feof(stream)) {

fscanf(stream, "%s", buf); // fscanf #1 printf("%s\n", buf);

}

fclose(stream);

return 0;

Odczyt z pustego pliku:

Co to jest?!

© UKSW, WMP. SNS, Warszawa 89

UWAGA!

Tyle informacji wystarczy, żeby wykonać pierwsze zadania dotyczące dostępu do plików, jakie będą realizowane na laboratoriach.

Następne slajdy dotyczą dostępu do plików w sposób, jaki może okazać się przydatny przy realizacji zadania semestralnego.

90

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C

Dostęp do plików w trybie tekstowym znak po znaku

ISO/ANSI C – dostęp do plików

Czytanie z pliku

int fgetc( FILE *stream );

<stdio.h>

FILE *stream;

char buffer[81];

int i, ch;

if((stream =

fopen("test.txt","r"))

== NULL ) exit( 0 );

ch = fgetc( stream );

for(i=0; (i < 80 ) &&

(feof(stream)==0);i++) {

buffer[i] = (char)ch;

ch = fgetc( stream );

}

buffer[i] = '\0';

printf( "%s\n", buffer );

fclose( stream );

© UKSW, WMP. SNS, Warszawa 92

ISO/ANSI C – dostęp do plików

Czytanie z pliku

int fgetc( FILE *stream );

/* zaimplementowane jako funkcja */

int getc( FILE *stream );

/* zaimplementowane jako funkcja i makro */

Działa tak samo.

© UKSW, WMP. SNS, Warszawa 93

88 89

90 91

92 93

(5)

Pisanie do pliku

int fputc( int c, FILE *stream );

FILE *stream;

char strptr[] = "Volume 2 is fine.\n";

char *p;

if( (stream = fopen( "crt_test.txt", "w" )) == NULL ) exit( 0 );

p = strptr;

while( (*p != '\0') && fputc( *(p++), stream ) != EOF );

fclose( stream );

© UKSW, WMP. SNS, Warszawa 94

fgetc, getc i putc są niepraktyczne, jeżeli mamy działać na

danych tekstowych, reprezentujących wartości o znaczeniu leksykalnym (np. słowa, liczby).

fgetc, getc i putc wymagają w programie dodatkowego kodu

służącego do analizy wczytanych znaków, aby prawidłowo określić, czy jest to np. liczba oraz czy ta liczba jest poprawnie zapisana. tymczasem są inne funkcje biblioteczne, które taką analizę mają już wbudowaną w sobie i służą np. do odczytywania całych liczb lub całych słów.

Dlatego, o ile to możliwe, należy jednak stosować formatowany dostęp do plików.

© UKSW, WMP. SNS, Warszawa 95

ISO/ANSI C – dostęp do plików

Pisanie do pliku serii znaków

int fputs( const char *string, FILE *stream );

FILE *stream;

char strptr[] = "I am Groot!\n";

if((stream = fopen("crt_test.txt", "w")) == NULL) exit( 0 );

fputs( strptr, stream );

fclose( stream );

96

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

Dygresja:

fputs vs. puts

fputs – pisze do wskazanego strumienia (pierwszy argument wywołania) puts – pisze do standardowego strumienia wyjściowego (okno konsoli)

putsdołącza na końcu znak nowej linii '\n'

97

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików Manipulowanie wskaźnikiem bieżącego elementu w pliku

ISO/ANSI C – dostęp do plików

Czytanie z pliku

• Po otwarciu pliku otrzymujemy prawo dostępu do danych w pliku

• Dane reprezentowane są jako strumień

• Po otwarciu mamy prawo do odczytu pierwszego elementu w pliku (pierwszego bajtu)

• Aktualną pozycję w pliku, z której w danej chwili mamy prawo czytać, określa wskaźnik pliku

• Po odczycie wskaźnik pliku przesuwa się w przód o tyle bajtów, ile zostało odczytanych

• Wskaźnika nie można cofać (w zasadzie..)

© UKSW, WMP. SNS, Warszawa 99

94 95

96 97

98 99

(6)

int fseek( FILE *stream, long offset, int origin );

<stdio.h>

stream – wskaźnik do otwartego pliku

offset – liczba bajtów od miejsca wskazywanego przez origin origin – stała:

SEEK_CUR – bieżąca pozycja wskaźnika SEEK_END – koniec pliku

SEEK_SET – początek pliku

fseek zwraca zero, jeżeli przesunięcie wskaźnika pliku się powiodło, lub wartość niezerową w przeciwnym przypadku

© UKSW, WMP. SNS, Warszawa 100

int fseek( FILE *stream, long offset, int origin );

<stdio.h>

fseek to funkcja ryzykowna, np.:

– kiedy plik jest otwarty w trybie do dołączania (‘a’ lub ‘a+’), bieżącą pozycją wskaźnika w pliku jest rezultat ostatniej operacji We/Wy.

Jeżeli takiej operacji jeszcze nie było (plik został tylko otwarty), wskaźnik wskazuje na pierwszy element pliku (!)

– dla plików otwartych w trybie tekstowym znaki nowej linii (CR-LF) wprowadzają funkcje fseek w błąd i mogą powodować nieoczekiwane rezultaty jej działania. Poprawne działanie jest gwarantowane tylko gdy offset jest ustawione na 0 (położenie określone jest tylko przez ostatni parametr: origin).

© UKSW, WMP. SNS, Warszawa 101

ISO/ANSI C – dostęp do plików

FILE *stream;

char line[81];

int result;

stream = fopen( "fseek.out", "w+" );

if( stream == NULL ) printf( "Plik nie został otwarty\n" );

else {

fprintf( stream, "fseek przesunie tutaj: abrakadabra.\n" );

result = fseek( stream, 23L, SEEK_SET);

if( result ) printf( "Fseek nie powiodl sie" );

else {

printf( "Wskaznik jest ustawiony w polowie linii.\n" );

fscanf( stream, "%s", line );

printf( "%s", line );

}

fclose( stream );

} /* co pojawi się w oknie konsoli? */

102

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

void rewind( FILE *stream );

przesuwa wskaźnik pliku na początek pliku

Działa tak samo jak:

fseek( stream, 0L, SEEK_SET );

ale rewind nie zwraca wartości informującej czy przesunięcie wskaźnika się powiodło

103

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

FILE *stream;

int data1, data2;

data1 = 1;

data2 = -37;

if( (stream = fopen( "crt_rewind.out", "w+" )) != NULL ) { fprintf( stream, "%d %d", data1, data2 );

printf( "Wartosci zapisane to: %d i %d\n", data1, data2 );

rewind( stream );

fscanf( stream, "%d %d", &data2, &data1 );

printf( "Wartosci odczytane to: %d i %d\n", data1, data2 );

fclose( stream );

} /* co pojawi się w oknie konsoli? */

© UKSW, WMP. SNS, Warszawa 104

ISO/ANSI C – dostęp do plików

int fflush( FILE *stream );

• Wypchnięcie z tzw. strumienia (tj. bufora pliku) znajdujących się tam danych (jeżeli pomyślne, zwraca zero, jeżeli nie – EOF)

• Jeżeli plik był otwarty do zapisu, dane są natychmiast przepisywane do pliku. Jeżeli do odczytu – dane z bufora są tracone, a bufor staje się pusty

• fflush(NULL)wymusza zapisanie do plików danych ze wszystkich strumieni otwartych w trybie do zapisu

• Strumienie są zarządzane przez system operacyjny, który sam decyduje, kiedy przepisać dane z rzeczywistego pliku (np. albo w momencie zamykania pliku, albo kiedy już bufor jest zapełniony, albo też kiedy program kończy się poprawnie jednak bez wywołania polecenia zamykającego plik)

© UKSW, WMP. SNS, Warszawa 105

100 101

102 103

104 105

(7)

Oprócz strumieni otwieranych przez użytkownika istnieją trzy strumienie standardowe otwierane przez system i dostępne w programie (biblioteka <stdio.h>):

• stdin – standardowe wejście, np. klawiatura

• stdout – standardowe wyjście, np. okno konsoli

• stderr – standardowy strumień dla komunikatów o błędach, np. okno konsoli

Te trzy zmienne są const i nie można ich zapisać innymi wartościami. Można je natomiast przekierować używając funkcji freopen

© UKSW, WMP. SNS, Warszawa 106

FILE *freopen( const char *path, const char *mode, FILE *stream );

Zamyka plik przypisany do aktualnie otwartego strumienia i przypisuje zmienną stream do pliku wskazywanego przez path

Typowo funkcja jest używana do przekierowywania strumieni standardowych stdin, stdout, stderr

Argument mode przyjmuje takie same wartości jak w funkcji fopen

Przykład:

stream = freopen( "freopen.out", "w", stderr );

© UKSW, WMP. SNS, Warszawa 107

ISO/ANSI C – dostęp do plików

int fgetpos(FILE *stream, fpos_t *pos);

int fsetpos(FILE *stream, const fpos_t *pos);

• Odczyt aktualnej pozycji wskaźnika pliku lub przesuniecie go w nowe miejsce. Jeżeli pomyślnie, funkcja zwraca zero.

• Pozycja wskaźnika musi być przechowywana w zmiennej typu

fpos_t.

• Pozycja wskaźnika jest interpretowana jako numer bajtu.

108

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

FILE *stream;

fpos_tpos;

char buffer[20];

if( (stream = fopen( "crt_fgetpos.txt", "rb" )) == NULL ) printf( "Trouble opening file\n" );

else { pos = 14;

if( fsetpos( stream, &pos ) != 0 ) perror( "fsetpos error" );

fread( buffer, sizeof( char ), 10, stream );

printf( "10 bytes at byte %I64d: %.10s\n", pos, buffer );

fclose( stream );

}

sizeof()– zwraca liczbę bajtów zajmowanych przez zmienne danego typu 109

© UKSW, WMP. SNS, Warszawa

ISO/ANSI C – dostęp do plików

Uwaga:

jeżeli zdecydowano otworzyć plik w trybie ‘r+’, ‘w+’ lub ‘a+’

i następuje zmiana z czynności zapisu do czynności odczytu, lub odwrotnie, to musi być najpierw wywołana funkcja fflush, fsetpos, fseek, lub rewind, która prawidłowo ustawi wskaźnik pliku.

© UKSW, WMP. SNS, Warszawa 110

106 107

108 109

110

Cytaty

Powiązane dokumenty

case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile.. do if

Ich rozmiar może być określony dopiero czasie działania programu (nie musi być wcześniej znany programiście), a po ich wykorzystaniu, zaalokowany obszar pamięci można zwolnić i

#include lato.h Rzecz między nami była cicha Westchnąłem do ciebie Tak jak się wzdycha I było nam ciasno, miło Dużo się spało i często się piło No i czego, czego

Podobnie jak adres tablicy jest zwracany przez jej nazwę, podaną bez nawiasu kwadratowego, adres funkcji uzyskuje się za pomocą nazwy funkcji pozbawionej listy argumentów.

Idea: follow paths through the CFG to an assertion, and build a formula that corresponds to the path.. CBMC: Bounded Model Checking for ANSI-C –

We present a tool for the formal verification of ANSI-C pro- grams using Bounded Model Checking (BMC). The emphasis is on us- ability: the tool supports almost all ANSI-C

[r]

Przerwania włącza się w trakcie działania procesora, za pomocą funkcji biblioteki jak poniżej.