1 ELEMENTARZ
Zmienne zewnętrzne dla fukcji main, getline i copy są zdefiniowane na początku programu: ustala się ich typ oraz określa przydzielaną im pamięć. Zewnętrzne definicje są składniowo dokładnie takie same, jak definicje zmiennych lokalnych; ponieważ jednak występują na zewnątrz funkcji, więc wprowadzają zmienne zewnętrzne. Zanim funkcja będzie mogła użyć zmiennej zewnętrznej, nazwa tej zmiennej musi stać się jej znana. Jednym ze sposobów jest napisanie w funkcji deklaracji extern, która ma taką
samą postać, jak zwykła deklaracja, z wyjątkiem dodanego słowa kluczowego extern.l
# !
W pewnych przypadkach deklarację extern można pominąć. Jeśli definicja zmiennej zewnętrznej pojawia się w pliku źródłowym przed użyciem zmiennej w konkretnej funkcji, to nie ma potrzeby umieszczania w tej funkcji deklaracji extern. Deklaracje te w funkcjach main, getline i copy są więc zbędne. W rzeczywistości definicje! wszystkich zmiennych zewnętrznych zwykle umieszcza się na początku pliku źródłowego, a następnie w całym pliku pomija deklaracje extern. j
Jeśli program jest zawarty w kilku plikach źródłowych, a zmienna została zdefiniowana np. w plikul i korzysta się z niej w pliku2 oraz w pliku3, to deklaracje extern w pliku2 i w pliku3 są niezbędne do połączenia wszystkich wystąpień zmiennej.! W praktyce zwykle zbiera się wszystkie deklaracje extern dotyczące zmiennych oraz funkcji i umieszcza je w oddzielnym pliku, historycznie zwanym nagłówkiem. jest on bowiem wstawiany na początku każdego pliku źródłowego za pomocą polecenia #include. Typowym zakończeniem nazwy pliku nagłówkowego jest przyrostek .h. Funkcje z biblioteki standardowej są zadeklarowane w takich plikach, np. <stdio.h>. Kwestię tę omówiono szczegółowo w rozdz. 4, a samą bibliotekę w rozdz. 7 i dodatku B. 1
Specjalne wersje funkcji getline i copy są bezargumentowe, logicznie byłoby więc zaproponować, aby na początku programu ich prototypy miały postać getline() i copy(). Ze względu na zgodność ze starymi programami w języku C w standardzie przyjmuje się jednak, że pusta lista parametrów jest deklaracją w starym stylu, i wyłącza wszelką kontrolę listy argumentów. Dlatego też dla wyraźnego zaznaczenia, że lista parametrów ma być pusta, należy użyć słowa void. Dalszą dyskusję na ten tema! kontynuujemy w rozdz. 4. ||
Powinieneś zauważyć, że w tym rozdziale z rozwagą używamy słów definicja i deklara* cja przy omawianiu zmiennych zewnętrzych. „Definicja” odnosi się do miejsca, w którym zmienna jest faktycznie tworzona, tj. gdzie ma przydzielaną pamięć. „Deklaracja*
• ‘l
dotyczy miejsca, w którym określa się naturę zmiennej, lecz nie przydziela jej pamięci
Przy okazji jeszcze jedna uwaga. Istnieje tendencja do tworzenia wszystkiego z użycie# zmiennych zewnętrznych, wydaje się bowiem, że to upraszcza komunikację - list)' argumentów są krótkie, a zmienne są dostępne wszędzie tam, gdzie są potrzebne. Lec? zmienne zewnętrzne występują zawsze - nawet wtedy, gdy ich nie potrzebujesz. Zby1 mocna wiara w zmienne zewnętrzne jest pełna niebezpieczeństw, ponieważ prowadź1
, ^ I powered by
1.10 ZMIENNE ZEWNĘTRZNE I ZASIĘG ZMIENNYCH _______■_.__
do powstawania programów, w których powiązania między danymi nie obiekty mogą być zmieniane w nieoczekiwany, a nawet nieumyślny, sposób. Taki program trudno jest zmienić. Druga wersja programu wypisującego najdłuższy wiersz jest gorsza od poprzedniej częściowo z tych powodów, a częściowo dlatego, że psuje ogól-1 ność dwóch bardzo pożytecznych funkcji przez wpisanie do nich nazw zmiennych, którymi mają się posługiwać.
Wyczerpaliśmy już to, co umownie można nazwać rdzeniem języka C. Z tej garści klocków można tworzyć wiele pożytecznych programów o niebagatelnych rozmiarach i chyba dobrym pomysłem jest zrobienie w tym celu przerwy. W następujących ćwiczeniach proponujemy napisanie programów trochę bardziej skomplikowanych niż programy prezentowane wcześniej w tym rozdziale.
Ćwiczenie 1.20. Napisz program detab zastępujący znaki tabulacji odpowiednią liczbą znaków odstępu, określoną przez następny punkt tabulacyjny. Przyjmij stały zbiór punktów tabulacyjnych, przypuśćmy co n pozycji. Czy n powinno być zmienną, czy raczej parametrem symbolicznym?
Ćwiczenie 1.21. Napisz program entab, który zastąpi ciągi znaków odstępu przez minimalną liczbę znaków tabulacji i znaków odstępu tak, aby odstępy zostały zachowane. Użyj tych samych punktów tabulacyjnych, co w programie detab.
Jeśli zarówno znak tabulacji, jak i jeden znak odstępu wystarczy do osiągnięcia punktu tabulacyjnego, to który z nich powinien mieć pierwszeństwo?
Ćwiczenie 1.22. Napisz program, który „łamie'’ długie wiersze wejściowe na dwa lub więcej krótszych wierszy po ostatnim znaku różnym od znaku odstępu i tabulacji, mieszczącym się przed n-tą pozycją wejścia. Zapewnij, aby Twój program postępował inteligentnie z bardzo długimi wierszami oraz wtedy, gdy przed wskazaną pozycją nie wystąpi żaden znak odstępu lub tabulacji.
✓
Ćwiczenie 1.23. Napisz program usuwający wszystkie komentarze z dowolnego programu w języku C. Nie zapomnij o właściwym traktowaniu stałych znakowych i napisowych. Komentarze języka C nie mogą być zagnieżdżone.
Ćwiczenie 1.24. Napisz program, który sprawdza szczątkową poprawność składniową dowolnego programu w języku C, tj. sygnalizuje błędy w rodzaju brakujących nawiasów okrągłych, kwadratowych czy klamrowych. Nie zapomnij także o apostrofach i cudzysłowach oraz o sekwencjach specjalnych i komentarzach. (Ten program byłby bardzo trudny, gdybyś napisał go w pełni ogólnie.)