1 ELEMENTARZ
/* copy: przepisz from do to; */
/* to musi być dostatecznie duże */ void copy(char to[], char fromU)
int i;
i = 0;
while ((to[i] = from[i]) != * \0’)
++i;
Funkcje getline i copy są zadeklarowane na początku programu, który z założenia mieści się w jednym pliku źródłowym.
Funkcje main i getline komunikują się między sobą za pomocą pary argumentów i zwracanej wartości. Parametry funkcji getline są zadeklarowane w wierszu
int getline(char s[ ], int lim) j
który mówi, że pierwszy parametr (s) jest tablicą a drugi (lim) liczbą całkowitą. Powodem, dla którego w deklaracji tablicy podaje się jej rozmiar, jest rezerwacja pamięci. W funkcji getline długość tablicy s nie jest potrzebna, ponieważ rozmiar tablicy jest określony w main. Instrukcja return służy funkcji getline do odesłania wartości w miejsce wywołania tak samo, jak w przypadku funkcji power. Przytoczony wiers; deklaruje również, że getline zwraca wartość typu int. Tę część deklaracji można p< minąć, gdyż int jest domyślnym typem zwracanej wartości.
Jedne funkcje zwracają wartości użyteczne; inne - jak copy - są stosowane tylko dli efektów ich działania i nie zwracają żadnej wartości. Deklarowanym typem copy je* więc void, który wyraźnie stwierdza, że funkcja nie zwraca żadnej wartości.
Funkcja getline wstawia znak ’\0’ (znak nuli: nic, którego wartością jest zero) na k< nieć tworzonej przez siebie tablicy, aby zaznaczyć koniec ciągu znaków. Ta konwei cja obowiązuje także dla języka C: gdy w programie źródłowym w języku C poją* się stała napisowa, np.
”ahoj\n”
wówczas taką stałą zapamiętuje się jako tablicę zawierającą ciąg znaków stałej i '/& znacza jej koniec znakiem *\0\
a |
h |
o |
j |
\n |
\o |
1.10 ZMIENNE ZEWNĘTRZNE I ZASIĘG ZMIENNYCH
Mi siol
lJoU '■
Format %s w funkcji printf wymaga, aby odpowiedni argument był o takiej właśnie postaci. Funkcja copy także liczy na to, że jej argument wejściowy jest zakończony znakiem ’\0’ i znak ten przepisuje do argumentu wyjściowego. (Z tego wszystkiego wynika, że ’\0’ nie jest częścią normalnego tekstu.)
Przy okazji warto jeszcze wspomnieć, że nawet w tak małym programie, jak ten, występują trudne problemy projektowe. Co na przykład powinna zrobić funkcja main po napotkaniu wiersza dłuższego niż podane ograniczenie? Funkcja getline pracuje bezpiecznie, to znaczy przerywa zbieranie znaków po wypełnieniu tablicy nawet wtedy, gdy nie wystąpił znak nowego wiersza. Funkcja main może sprawdzić, czy wiersz był za długi przez zbadanie długości wiersza i ostatnio zapamiętanego znaku, a następnie postąpić według własnego uznania. Dla zwięzłości programu zignorowaliśmy jednak to zagadnienie.
Użytkownik funkcji getline nie jest w stanie z góry przewidzieć, jak długie będą wiersze wejściowe, funkcja sprawdza zatem przepełnienie. Z drugiej strony, użytkownik funkcji copy już zna (lub może poznać) długości napisów, postanowiliśmy więc nie dodawać do niej kontroli błędów.
Ćwiczenie 1.16. Popraw główną funkcję programu szukającego najdłuższego wiersza tak, aby program zawsze poprawnie wypisywał rozmiar dowolnie długich wierszy i tylko tyle tekstu, ile jest możliwe.
Ćwiczenie 1.17. Napisz program wypisujący wszystkie wiersze wejściowe dłuższe niż 80 znaków.
Ćwiczenie 1.18. Napisz program, który będzie pomijać początkowe znaki odstępu i tabulacji oraz usuwać całkowicie białe (puste) wiersze.
Ćwiczenie 1.19. Napisz funkcję reverse(s) odwracającą kolejność znaków tekstu w argumencie s. Zastosuj ją w programie odwracającym kolejno wszystkie wiersze wejściowe.
Takie zmienne w funkcji main, jak linę, longest itd., są prywatne lub lokalne dla tej funkcji. Żadna inna funkcja nie może mieć do nich bezpośredniego dostępu, ponieważ są one zadeklarowane wewnątrz funkcji main. To samo dotyczy zmiennych zadeklarowanych w innych funkcjach; np. zmienna i w funkcji getline nie jest związana ze zmienną i w funkcji copy. Każda zmienna lokalna funkcji zaczyna istnieć
55