7 WEJŚCIE I WYJŚCIE
#include <stdio.h>
/* cat: sklej zawartość plików, wersja 2 */ main(int argc, char *argv[])
FILE *fp;
void filecopy(FILE *, FILE *);
char *prog = argv[0]; /* nazwa programu do komunikatów */
if (argc == 1) /* bez argumentów: kopiuj std. wejście */ filecopy(stdin, stdout); else
while (—argc > 0)
if ((fp = fopen(*-H-argv, ”r”)) == NULL) {
fprintf(stderr, "%s: nie mogę otworzyć %s\n”, próg, *argv); exit(1);
} else {
filecopy(fp, stdout); fclose(fp);
if (ferror(stdout)) {
fprintf(stderr, ”%s: błąd pisania do stdout\n”, próg); exit(2);
exit(0);
Program ten sygnalizuje błędy na dwa sposoby. Po pierwsze, komunikaty produkowane przez funkcję fprintf są kierowane do pliku stderr. Znajdą zatem drogę, aby pojawić się na ekranie, zamiast ugrzęznąć gdzieś wśród danych wyjściowych lub w potoku. W komunikatach uwzględniliśmy nazwę, z jaką ten program został wywołany (argv[0j), znane więc będzie źródło błędu, gdy pracuje on wśród innych programów
Po drugie, w programie skorzystaliśmy ze standardowej funkcji exit, której wywołanie powoduje zatrzymanie programu. Argument funkcji exit będzie dostępny dla każdego procesu wywołującego ten program jako swój podproces. Badając tę wartość możemy dowiedzieć się o sukcesie lub porażce naszego programu. Przyjęto, że wartość zero świadczy o poprawnym wykonaniu programu, natomiast jakakolwiek niezerowa wartość sygnalizuje sytuację awaryjną. Funkcja exit wywołuje funkcję fclose dla wszystkich otwartych plików wyjściowych w celu wypisania danych pozostałych w buforach
Wewnątrz funkcji main instrukcja return wyr jest równoważna wywołaniu exit(wyr) Funkcja exit ma tę przewagę, że można ją wywołać w dowolnej innej funkcji. Takie
1.7 WPROWADZANIE I WYPROWADZANIE WIERSZY TEKSTU -_
wywołania często można spotkać w programach wyszukiwania według nasz program z rozdz. 5.
funkcja terror zwraca wartość niezerową wówczas, gdy dla strumienia danych fp wystąpił jakiś błąd.
int ferror(FILE *fp)
\Vprawdzie błędy dotyczące wyjścia są sporadyczne, ale jednak się zdarzają (np. przepełnienie dysku), więc program produkujący dane powinien również sprawdzać ich wystąpienie.
Funkcja feof(FILE*) działa podobnie do funkcji terror: zwraca wartość niezerową po napotkaniu końca pliku wskazanego argumentem fp.
int feof(FILE *fp)
W naszych małych programach ilustracyjnych zazwyczaj nie martwiliśmy się o stan zakończonego programu, ale w poważnym programie koniecznie trzeba dbać o zwracanie sensownych, użytecznych wartości opisujących ten stan.
Biblioteka standardowa zawiera wejściową funkcję fgets, bardzo podobną do używanej przez nas w poprzednich rozdziałach funkcji getline:
char *fgets(char *line, int maxline, FILE *fp)
Funkcja fgets czyta kolejny wiersz (łącznie ze znakiem nowego wiersza) z pliku wskazanego przez wskaźnik fp i wstawia ten wiersz do tablicy znakowej linę. Funkcja fgets czyta co najwyżej maxline-1 znaków. Wynikowy wiersz będzie zakończony znakiem ’\0\ Normalnie funkcja ta zwraca wartość wskaźnika linę; po napotkaniu końca pliku lub po wykryciu błędu jej wartością funkcyjną jest NULL. (Nasza funkcja getline zwraca długość wczytanego wiersza, co jest informacją bardziej użyteczną; zero oznacza koniec pliku.)
Wyjściowa funkcja fputs wypisuje do wskazanego pliku tekst (który nie musi zawierać znaku nowego wiersza):
int fputs(char *line, FILE *fp)
Zwracaną przez funkcję wartością jest zero, a w przypadku błędu - EOF.
Działanie funkcji bibliotecznych gets i puts jest podobne do fgets i fputs, ale operu-J4one na strumieniach standardowych stdin oraz stdout. Mętlik wprowadza tylko to, te gets usuwa kończący znak nowego wiersza ’\n,» a puts dopisuje go do tworzonego wiersza.
219