4 FUNKCJE I STRUKTURA PROGRAMU_________^
Zmienna jest zewnętrzna, jeśli zdefiniowano ją na zewnątrz wszystkich funkcji. Zatem stos i indeks jego wierzchołka - wspólne dla funkcji push i pop - definiujemy na zewnątrz tych funkcji. Ale funkcja main sama nie odwołuje się do stosu lub jego wierzchołka - ich reprezentację można przed nią ukryć.
Zajmiemy się teraz realizacją funkcji getop. która pobiera z wejścia następny operator lub argument. Jej zadanie jest proste. Najpierw pomija wiodące znaki odstępu i tabulacji. Jeśli kolejny znak nie jest cyfrą lub kropką dziesiętną, to zwraca ten znak. W przeciwnym przypadku z następnych cyfr (i być może kropki dziesiętnej) buduje ciąg cyfr liczby i zwraca NUMBER, co jest sygnałem otrzymania liczby.
#include <ctype.h>
int getch(void); void ungetch(int);
/* getop: pobierz następny operator lub argument */ int getop(char s[ ])
{
int i, c;
while ((s[0] = c = getch()) == * * || c == ’\t’)
i
s[1] = '\o’;
if (! isdigit(c) && c !=
return c; /* to nie liczba */
i = 0;
if (isdigit(c)) /* buduj część całkowitą */ while (isdigit(s[++i] = c = getch()))
>
if (c == I* buduj ułamek */
while(isdigit(s[++i] = c = getch()))
9
s[i] = ’\0’; if (c != EOF) ungetch(c); return NUMBER;
}
Co robią funkcje getch i ungetch? Często zdarza się, że program czytający ^ z wejścia nie może stwierdzić, że przeczytał dość, zanim nie przeczyta za dużo.
rym tego przykładem jest zbieranie znaków, które tworzą liczbę: ku różnego od cyfry, liczba nie jest kompletna. Potem jednak okazuje się, że program przeczytał o jeden znak za dużo - znak, na którego przyjęcie nie był jeszcze przygotowany.
Mi si o1
ip wwiTirzjaafc^
Problem byłby rozwiązany, gdyby istniała możliwość „oddawania” nie chcianego znaku. Wówczas program, który przeczytał o jeden znak za dużo, mógłby go oddać z powrotem na wejście, aby dla reszty programu był nowym, nigdy przedtem nie czytanym znakiem. Na szczęście łatwo można takie oddawanie znaku symulować. Realizują to dwie współpracujące funkcje: getch dostarcza do sprawdzenia następny znak z wejścia, ungetch zapamiętuje oddane z powrotem na wejście znaki tak, aby w kolejnych wywołaniach funkcja getch pobierała je, zanim zacznie czytać nowe znaki z wejścia.
Współpraca tych funkcji jest prosta: ungetch zapamiętuje oddawane znaki we wspólnym buforze - tablicy znaków; getch czyta z bufora wtedy, kiedy coś w nim jest, gdy zaś bufor jest pusty - wywołuje funkcję getchar. Musi istnieć także zmienna indeksująca pozycję bieżącego znaku w buforze.
Ponieważ bufor i indeks znaku są wspólne dla funkcji getch i ungetch, a ponadto muszą zachowywać swoje wartości między wywołaniami tych funkcji, to powinny być zewnętrzne dla nich obu. Możemy więc zdefiniować getch, ungetch i ich wspólne zmienne na przykład tak:
#define BUFSIZE 100 /* maks. rozmiar bufora */
char buf[BUFSIZE]; /* bufor na zwroty z ungetch */
int bufp = 0; /* następne wolne miejsce w buforze */
int getch(void) /* weź znak, być może oddany na wejście */
return (bufp > 0) ? buf[—bufp] : getchar();
void ungetch(int c) /* oddaj znak z powrotem na wejście */
if (bufp >= BUFSIZE)
printf(”ungetch: za wiele zwrotów\n”); else
buf[bufp++] = c;
113
ię/yk ANSI C
8 -