Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest...

41
Pliki w C++

Transcript of Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest...

Page 1: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Pliki w C++

Page 2: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

• Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości.

• Koniec strumienia identyfikowany jest znacznikiem końca pliku — EOF.

• Z każdym strumieniem związany jest wskaźnik bieżącej pozycji — od tej pozycji realizowane będzie czytanie lub pisanie. Każdy zapis i odczyt zmienia wskaźnik bieżącej pozycji.

• Z każdym strumieniem związany jest znacznik osiągnięcia końca pliku oraz znacznik błędu.

Page 3: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Strumienie mogą być otwierane w trybie:

• Binarnym — strumień jest ciągiem jednakowo traktowanych bajtów, każdy zapis i odczyt realizowany jest bez żadnych konwersji.

• Tekstowym — strumień jest ciągiem linii tekstu zakończonych znacznikiem końca linii — znak ’\n’. W trakcie odczytu i zapisu do takiego strumienia mogą zachodzić konwersje spowodowane np. różna fizyczna reprezentacja znacznika końca wiersza (np. para \r\n w plikach tekstowych DOS/Windows, pojedynczy znak \n w systemach Unix’owych).

Page 4: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Otwieranie plików

• Aby rozpocząć operacje na plikach należy zadeklarować w programie zmienną stanowiącą „dojście” do takiego pliku.

• W przypadku obsługi standardowych strumieni deklaruje się zmienną wskaźnikową.

• Typem wskazywanym jest FILE, jest to zdefiniowany w pliku nagłówkowym stdio.h typ rekordowy, zawierający informacje o otwartym dojściu do pliku.

• Wykorzystanie pliku rozpoczyna operacja jego otwarcia, realizowana zwykle przez funkcję fopen, otwarcie pliku dane.txt do odczytu w trybie tekstowym może wyglądać następujaco:

Page 5: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

fopen

Pierwszy parametr funkcji fopen to nazwa pliku (być może ze ścieżką), drugi parametr to napis zawierający tryb otwarcia – r oznacza odczyt, t tryb tekstowy.

W przypadku poprawnego otwarcia pliku, funkcja fopen alokuje na stercie rekord opisu pliku (typu FILE), wypełnia go odpowiednimi informacjami i oddaje w postaci rezultatu wskaźnik do tego rekordu. Wskaźnik ten stanowi odtąd „dojście” do pliku i będzie przekazywany każdej funkcji operującej na pliku, informując ją, na jakim pliku ma wykonywać właściwe dla niej operacje.

Zatem w przypadku poprawnego otwarcia pliku wskaźnik fp będzie miała wartość różną od NULL. Wtedy można wykonywać dalsze operacje na pliku. Jeżeli w trakcie otwierania pliku nastąpił błąd, rezultatem funkcji fopen jest wartość NULL. Nie można wtedy przetwarzać pliku.

Page 6: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

FILE * fopen( const char *filename, const char *mode );

• Otwiera strumień związany z plikiem o nazwie przekazanej parametrem filename.

• Nazwa może zawierać ścieżkę dostępu do pliku. Strumień otwierany jest w trybie mode. Jeżeli otwarcie zakończyło się sukcesem, funkcja udostępnia wskaźnik do dynamicznie alokowanej struktury typu FILE, stanowiącej programową reprezentację fizycznego pliku.

• Jeżeli pliku nie udało się otworzyć, rezultatem funkcji jest NULL.

Page 7: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 8: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Znak + w trybie otwarcia oznacza aktualizacje — możliwość czytania i pisania do otwartego strumienia. Jednak zapis odczyt i zapis (albo zapis i odczyt) nie mogą po sobie następować bezpośrednio. Należy użyć funkcji „wymiatania” bufora fflush lub jednej z funkcji pozycjonowania pozycji — fseek, fsetpos, rewind.

Jeżeli informacja o trybie otwarcia (t lub b) nie występuje, przyjmowany jest tryb otwarcia zgodnie z wartością globalnej zmiennej _fmode. Jeżeli _fmode posiada wartość O_BINARY, plik jest otwierany w trybie binarnym, jeżeli _fmode posiada wartość O_TEXT, plik jest otwierany w trybie tekstowym.

Domyślna wartość to O_TEXT. Symbole O_... są zdefiniowane w pliku fcntl.h.

Page 9: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Zamykanie plików

Do zamykania pliku służy funkcja fclose. Przykład jej wykorzystania przedstawiono poniżej. if( ( fp = fopen( "dane.dat", "rt" ) ) != NULL )

{

/* Otwarcie OK, wykonaj operacje na pliku */

. . .

/* Zamknij plik jeżeli przetwarzanie zakończono */

fclose( fp );

}

else

{

/* Otwarcie nieudane, obsługa sytuacji błędnej */

. . .

}

Page 10: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

• Dokładniejszy opis funkcji zamykającej plik jest następujący:

int fclose( FILE * stream );

• Funkcja zamyka strumień i zapisuje wszystkie bufory.

• Rezultat EOF oznacza błąd zamykania, rezultat równy zero oznacza bezbłędne zamknięcie.

• Pamięć przydzielona strukturze wskazywanej przez wskaźnik stream jest zwalniana.

Page 11: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Odczyt i zapis pojedynczych znaków • Odczyt pojedynczego znaku ze strumienia realizuje funkcja fgetc:

int fgetc( FILE *stream );

• Funkcja pobiera następny znak ze strumienia identyfikowanego przez stream i uaktualnia wskaźnik bieżącej pozycji w pliku.

• Znak pobierany jest jako unsigned char i przekształcany jest do typu int.

• W przypadku napotkania końca strumienia rezultatem jest wartość EOF oraz ustawiany jest znacznik napotkania końca strumienia.

• W przypadku wystąpienia błędu odczytu rezultatem funkcji jest wartość EOF oraz ustawiany jest znacznik błędu strumienia.

Page 12: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

• Zapis pojedynczego znaku do strumienia realizuje funkcja fputc:

int fputc(int c, FILE *stream);

• Funkcja wyprowadza znak c do strumienia stream zgodnie ze wskaźnikiem bieżącej pozycji w pliku.

• W przypadku, gdy funkcja fputc zakończyła swoje działanie bez błędu, rezultatem funkcji jest znak c. W przeciwnym wypadku wartość EOF.

Page 13: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Przy sekwencyjnym przetwarzaniu plików istotna jest umiejętność testowania np. czy w wyniku ostatniej operacji odczytu napotkano koniec pliku. Służyć do tego może funkcja feof:

int feof( FILE * stream ); Rezultatem funkcji jest wartość różna od zera jeżeli strumień jest w

pozycji końcowej, zero w przeciwnym wypadku. Strumień jest w pozycji końcowej, jeżeli w wyniku ostatnio przeprowadzonej operacji odczytano znacznik końca pliku.

Uwaga – funkcja feof działa inaczej niż jej odpowiednik z języka Pascal – funkcja Eof. Rezultatem funkcji Eof jest wartość True, jeżeli przeczytano ostatni element w pliku. Rezultatem funkcji feof jest wartość różna od zera, jeżeli próbujemy czytać po odczytaniu znacznika końca pliku.

Powoduje to pewne problemy…

Page 14: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

przykład

Załóżmy, że plik d.txt ma następującą zawartość:

123456789

Page 15: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 16: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

efekt

Jak widać program doliczył do rzeczywistej zawartości pliku również znacznik jego końca. Aby tak nie było, można zaproponować inną sekwencję przetwarzania pliku:

Page 17: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Poprawniej jest…

Page 18: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

• Kluczowa jest tutaj sekwencja stanowiąca warunek iteracji while.

• Funkcja fgetc pobiera znak z pliku, jest on zapamiętywany w zmiennej c a następnie porównywany ze stała EOF.

• W przypadku odczytania znacznika końca pliku, trafia on do zmiennej c, lecz iteracja jest zrywana i program prawidłowo zadziała – wykaże 9 znaków w pliku d.txt.

Page 19: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Spróbujmy wykorzystać podobna sekwencje dla wyznaczenia rozmiaru pliku liczonego w bajtach, tym razem wykorzystajmy iteracje for:

if( ( fp = fopen( "d.txt", "rt" ) ) != NULL ) { for( counter = 0; fgetc( fp ) != EOF; counter++ ) ; fclose( fp ); printf( "\nRozmiar pliku: %ld bajtow", counter ); } Niestety weryfikacja działania tego programu pokaze, iz działa

on błednie, zobacz Rysunek 3.

Page 20: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 21: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Przyczyną wadliwego działania programu są konwersje znaczników końca linii w trybie tekstowym.

W systemach DOS/Windows znacznik końca linii to para \r i \n (czyli CR i LF). W trakcie odczytu w trybie tekstowym, każda para \r\n zamieniana jest na pojedynczy znak \n.

Analogicznie jest w przypadku zapisu – pojedynczy znacznik \n zapisywany jest do pliku fizycznie w postaci pary \r\n.

Page 22: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Konwersja znaczników końca wiersza w trybie tekstowym

Page 23: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Konwersje takie nie zachodzą przy otwieraniu pliku w trybie binarnym.

W drugim parametrze wywołania należy zatem użyć litery b, oznaczającej otwarcie w trybie binarnym.

Page 24: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

poprawiona wersja kodu, ujęta w ramy funkcji file_size

long int file_size( char * fname ) { FILE * fp; long int counter = 0; if( ( fp = fopen( fname, "rb" ) ) != NULL ) { for( counter = 0; fgetc( fp ) != EOF; counter++ ) ; fclose( fp ); } return counter; } . . . printf( "\nRozmiar pliku: %ld bajtow", file_size( "d.txt" ) );

Page 25: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 26: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Kopiowanie jednego pliku do innego…

Page 27: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Kopiowanie z zamianą znaków na duże znaki…

Page 28: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Co jeszcze ?

1. W trakcie kopiowania realizuj filtrowanie znaków, np. kopiowanie tylko liter i cyfr

2. Kopiowanie wyłącznie dużych liter

Page 29: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Ćwiczenia w przetwarzaniu plików znak po znaku

1. Napisać program wyznaczający ile w pliku tekstowym jest liter dużych, małych, cyfr oraz znaków interpunkcyjnych (znaki kropki, przecinka, średnika). Program pyta użytkownika o nazwę pliku, dla którego ma przeprowadzić powyższe statystyki.

2. Napisać program wyznaczający liczbę wierszy w pliku tekstowym. Program pyta użytkownika o nazwę pliku, dla którego ma przeprowadzić ta operacje. Wskazówka – każdy wiersz w pliku tekstowym (nawet pusty) kończony jest znakiem \n.

3. Napisać program wyznaczający współczynnik skomentowania programu w jezyku C, tzn. procentowy stosunek liczby znaków w komentarzach do ogólnej liczby znaków w programie. Program pyta użytkownika o nazwę pliku, dla którego ma przeprowadzić tą operację. W statystyce nie biorą udziału tzw. „białe znaki”, czyli znaki spacji, tabulacji i nowego wiersza.

4. Napisać program kopiowania zawartości jednego pliku do drugiego. Program powinien zapytać o nazwy pliku źródłowego i docelowego. W trakcie kopiowania każda duża litera ma być zamieniana na małą, a każda mała na dużą.

5. Napisać program wyznaczający liczbę słów zawartych w pliku tekstowym. Jako słowo traktowane ma być dowolny ciąg liter, cyfr i znaków podkreślenia, rozpoczynający się od litery. Program pyta użytkownika o nazwę pliku wejściowego.

Page 30: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Przetwarzanie plików liniami

• Pliki tekstowe reprezentowane są również jako strumienie bajtów.

• Można je jednak przetwarzać wierszami, od strony programu separatorem wierszy jest znak \n.

• Do przetwarzania pliku tekstowego linia po linii służą funkcje odczytu/zapisu linii — buforem linii są tablice znakowe.

Page 31: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Pliki tekstowe reprezentowane są również jako strumienie bajtów. Można je jednak przetwarzać wierszami, od strony programu separatorem wierszy jest znak \n.

Do przetwarzania pliku tekstowego linia po linii służą funkcje odczytu/zapisu linii — buforem linii są tablice znakowe.

Odczyt linii tekstu z pliku realizuje znana już funkcja fgets, zapis np. fputs, fprintf .

int fputs( const char * s, FILE * stream ); Funkcja fputs wyprowadza napis s do pliku stream, nie

dopisuje znaczników końca wiersza ani końca napisu. Rezultatem funkcji jest ostatni zapisany znak, w przypadku gdy

zapis zakończył się sukcesem lub EOF, gdy wystąpił błąd.

Page 32: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Funkcja fprintf

int fprintf( FILE * stream, const char * format [, argument, ...] );

Funkcja fprintf wyprowadza do pliku stream napis format oraz opcjonalne argumenty, w postaci określonej przez sekwencje formatujące zapisane w napisie format.

Rezultatem funkcji jest liczba wyprowadzonych bajtów, w przypadku gdy zapis zakończył się sukcesem lub EOF, gdy wystąpił błąd..

Wszystkie zasady formatowania znane z wykorzystania funkcji printf obowiązują dla funkcji fprintf.

Zamiast wywołania funkcji printf: fprintf( stdout, "printf to fprintf piszacy do stdout" );

Page 33: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 34: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Funkcja fgets

Pierwszy parametr s określa bufor, do którego mają być zapisane wczytywane dane.

Drugi parametr n określa maksymalną pojemność bufora, uwzględniającą miejsce na znacznik końca napisu.

Trzeci parametr stream określa strumień (plik), z którego funkcja ma odczytywać dane, może to być również standardowy strumień wejściowy ― stdin.

Działanie funkcji kończy się gdy funkcja odczyta n – 1 znaków lub wcześniej zostanie odczytany znak nowego wiersza (Enter).

Znacznik końca napisu dopisywany jest na jego końcu. Funkcja fgets pozostawia w buforze znacznik końca wiersza

Page 35: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec
Page 36: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Wyprowadza do stdout zawartość pliku o nazwie fname.

Page 37: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

ćwiczenia w przetwarzaniu plików linia po linii Napisać program fview - przeglądacz plików tekstowych. Będzie wyświetlać na ekranie zawartość pliku

tekstowego przekazanego parametrem wywołania programu. Jeżeli program zostanie wywołany w linii poleceń:

fview ala.txt

to ma wyświetlić zawartość pliku ala.txt lub sensownie zareagować na przypadek gdy taki plik nie istnieje. Program może być również wywoływany z opcjami:

fview -p ala.txt

gdzie –p (od ang. page) ma powodować wyświetlanie ze stronicowaniem, tzn. z zatrzymaniem co 25 linii

fview -c ala.txt

gdzie –c (od ang. cut) ma powodować obcinanie linii do 80 znaków, tzn. linie dłuższe niż 80 znaków nie będą zawijane do następnej linii ekranowej.

fview -u ala.txt

gdzie –u (od ang. upper) ma powodować wyświetlanie zawartości pliku dużymi literami.

fview -l ala.txt

gdzie –l (od ang. lower) ma powodować wyświetlanie zawartości pliku małymi literami. Opcje mogą być łączone. tzn. jednocześnie -p i -u. Przykładowo wywołanie:

fview –upc ala.txt

Ma spowodować wyświetlenie zawartości pliku tekstowego dużymi literami, ze stronicowaniem i z obcinaniem zbyt długich linii. Oczywiście jednoczesne stosowanie opcji –u i –l sie wyklucza.

Page 38: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Wskazówki… #define MAX_LINE 256 #define MAX_CHARS_IN_LINE 80 void list_file_nowrap( char * fname ) { FILE * fp; char buffer[ MAX_LINE ]; if( ( fp = fopen( fname, "rt" ) ) != NULL ) { while( fgets( buffer, MAX_LINE, fp ) != NULL ) { if( strlen( buffer ) > MAX_CHARS_IN_LINE ) { buffer[ MAX_CHARS_IN_LINE - 1 ] = '>'; buffer[ MAX_CHARS_IN_LINE ] = '\0'; } printf( "%s", buffer ); } fclose( fp ); } }

funkcja list_file nie łamie za długich wierszy a umieszcza na ich końcu symbol informujący, że wiersz jest dłuższy od szerokości ekranu. Realizuje to funkcja list_file_nowrap o następującej postaci:

Stała MAX_CHARS_IN_LINE reprezentuje aktualną szerokość okna konsoli liczoną w znakach. Linia zapisana w tablicy buffer jest obcinana do tej liczby znaków poprzez wstawienie na pozycji MAX_CHARS_IN_LINE znacznika końca napisu. Na znaku poprzednim wstawiany jest symbol '>' sugerujący użytkownikowi, że linia jest dłuższa niż szerokość okna konsoli.

Page 39: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

Numerowanie wierszy

#define MAX_LINE 256 #define MAX_CHARS_IN_LINE 80 void nlist_file_nowrap( char * fname ) { FILE * fp; int counter = 0; char buffer[ MAX_LINE ]; if( ( fp = fopen( fname, "rt" ) ) != NULL ) { while( fgets( buffer, MAX_LINE, fp ) != NULL ) { if( strlen( buffer ) > MAX_CHARS_IN_LINE - 5 ) {buffer[ MAX_CHARS_IN_LINE - 6 ] = '>'; buffer[ MAX_CHARS_IN_LINE - 5 ] = '\0'; } printf( "%03d: %s", ++counter, buffer ); } fclose( fp ); } }

Numerowanie linii opiera sie na zmiennej counter, dla numerów linii zarezerwowano domyślnie trzy cyfry. łącznie ze znakiem dwukropka i jedna spacja daje to 5 znaków. O tyle mniej znaków można zmieścić w linii tekstu, stąd inne niż poprzednio wartości przy obcinaniu zbyt długich linii.

Page 40: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

poszukiwanie linii zawierających określony wzorzec tekstowy. Realizuje to przedstawiona dalej funkcja pattern_list_file. Otrzymuje ona w postaci drugiego parametru wywołania tablice znaków pattern, zawierająca poszukiwany wzorzec.

#define MAX_LINE 256

#define MAX_CHARS_IN_LINE 80

void pattern_list_file( char * fname, char * pattern )

{

FILE * fp;

int counter = 0;

char buffer[ MAX_LINE ];

if( ( fp = fopen( fname, "rt" ) ) != NULL )

{

while( fgets( buffer, MAX_LINE - 1, fp ) != NULL )

{

++counter;

if( strstr( buffer, pattern ) != NULL )

{

if( strlen( buffer ) > MAX_CHARS_IN_LINE - 5 )

{

buffer[ MAX_CHARS_IN_LINE - 6 ] = '>';

buffer[ MAX_CHARS_IN_LINE - 5 ] = '\0';

}

printf( "%03ld: %s", counter, buffer );

}

}

fclose( fp );

}

}

Page 41: Pliki w C++ - Zakład Systemów Informatycznych | …zsi.ii.us.edu.pl/~nowak/plikiC.pdf•Plik jest reprezentowany przez strumień znaków (bajtów) o zmiennej długości. •Koniec

• Dla tej funkcji kluczowe jest wywołanie funkcji strstr, przeszukującej tablice buffer w poszukiwaniu podciągu identycznego z pattern. W przypadku znalezienia takiego podciągu rezultatem funkcji jest wskaźnik na początek podciągu znalezionego w tablicy buffer.

• W naszym przypadku sam fakt znalezienia podciągu (a więc niezerowy rezultat funkcji strstr) wystarcza, by zakwalifikować linie do wyświetlenia.