Wprowadzenie
Laboratorium poświęcone jest operacjom na napisach (ciągach znaków).
Przypominam, że:
'a'
to stała typuchar
o „wartości" znaku (litery) a małe;"Ala ma kota"
to stała typuchar *
(czyli tablica znakowa) zawierająca napis „Ala ma kota";char z = 'A';
to deklaracja zmiennej o nazwie zet zainicjowanej wartością literą „A wielkie";char napis[]="Ala ma kota";
to deklaracja tablicy znakowej o długości 12 elementów (jedenaście liter i specjalny znak, o kodzie ASCII 0) informujący o końcu napisu; zawartość tablicy może być dowolnie modyfikowana, ale nie możemy przekroczyć sumarycznej długości 11 liter (plus znak końca).char * tekst = "Ala ma kota";
to deklaracja wskaźnika typuchar *
i zainicjowanie go wartością adresu miejsca pamięci, w którym przechowywana jest stała znakowa o wartości „Ala ma kota"; W efekcie jest to też „tablica" o długości 11 znaków (plus znak końca), ale jej zawartość nie może być modyfikowana!na zmiennych znakowych można wykonywać normalne operacje porównywania:
'a' < 'b'
,tekst[0]=='A'
, itd.
Funkcja sprawdzająca czy zmienna ma wartość „odstępu"1, moze wyglądac tak:
int czy_odstęp( char x)
{
return x == ' ' || x == '\n' || x == '\t';
}
Funkcja jako odstępy traktuje spacje, znak nowej linii i znak tabulacji czyli znaki „niewidoczne".
Zadanie do wykonania
Mamy dwa zadania do wyboru:
Funkcja sprawdzająca czy zadany ciąg liczb jest liczbą całkowitą.
Funkcja sprawdzająca czy zadany ciąg liczb jest liczbą rzeczywistą.
(A dokładniej mówiąc, czy liczba zostanie potraktowana właściwie jako dana wejściowa dla programu napisanego w C, albo czy będzie właściwą stałą odpowiedniego typu2.)
Maszyna stanów
Żeby zadanie zrealizować trzeba najpierw zastanowić się jak wygląda (poprawna) liczba całkowita. Nie jest to skomplikowane:
Na jej początku jest (być może) pewna liczba odstępów3 (które nie mają wpływu na poprawność liczby); można je zignorować.
Później jest (nieobowiązkowy) znak (
+-
). Po znaku musi wystąpić co najmniej jedna cyfra.Po pierwszej cyfrze może wystąpić zero lub więcej cyfr.
Zakładamy, że pierwszy odstęp (po cyfrach) kończy liczbę. Kończy ją również znak o kodzie ASCII 0 (zero).
Można sobie życie ułatwić (albo utrudnić) budując maszynę Turinga, która mając na taśmie napis przejrzy go i zdecyduje czy napis jest liczbą czy też nie.
Program nawiązuje do maszyny Turinga. Szerzej opisywana ona była na zajęciach z Technologii Informacyjnych.
Możemy skonstruować maszynę Turinga realizującą algorytm sprawdzania czy napis jest liczbą, zgodnie z powyższymi zasadami. Poniżej przedstawiam proponowany diagram stanów.
Zakładamy, że liczba zapisana jest na taśmie, a głowica znajduje się przed pierwszym znakiem napisu.
Na diagramie tym, podwójne okręgi oznaczają stan początkowy i stany końcowe. Opisy nad krawędziami (lab na prawo od nich) oznaczją ,,kategorie" znaków, które mogę się pojawić:
+
,-
to (ewentualny) znak liczby;pusty oznacza tak zwany ,,biały znak" (czyli w najprostszym przypadku jest to odstęp, w sytuacjach bardziej skomplikowanych może to być nowa linia, znak poziomej lub pionowej tabulacji, wysów strony). Wszystkie takie znaki przed rozpoczęciem cyfry mogą być po cichu zignorowane;
cyfra to dowolna cyfra z zakresu od 0 do 9;
EOT to umowny (symboliczny) zapis znaku o kodzie ASCII zero, oznaczający w języku C koniec napisu;
inny to (ponownie umowny) zapis oanaczajacy znaki poza wymienionymi dotychczas.
Nie gwarantuję, oczywiście, że przedstawione schematy są poprawne.
Każda ścieżka od start od OK powinna opisywać poprawną postać liczby.
Można opisać podobne zasady opisujące wygląd liczby rzeczywistej:
ignorujemy znaki puste na początku;
później może być +/–/cyfra,
pomiędzy cyframi może pojawić się kropka (lub przecinek) dziesiętna,
po cyfrach może pojawić się litera e (lub E albo d lub D) a po niej plus albo minus albo odstęp, a później cyfra/cyfry wykładnika.
Uproszczony (choć niewolny zapewne od błędów) diagram maszyny Turinga sprawdzającej czy napis jest liczbą rzeczywistą zamieściłem poniżej.
Wybieramy jedno z tych zadań i programujemy. Wszystkie czynności sprawdzające powinna wykonywać funkcja (na potrzeby instrukcji nazwę ją czy, wywoływana w sposób następujący:
int czy(char napis[ ]);
na przykład:
if(czy("+123") printf("Liczba!\n");
Funkcja zwraca wartość jeden gdy napis jest liczbą, zero w przeciwnym razie.
Można próbować utrudnić/ułatwić sobie życie programując szereg funkcji pomocniczych sprawdzających czy:
znak jest cyfrą (
int czy_cyfra( char );
)jest znakiem (
+ -
)int czy_znak( char );
odstępem,
…
Uwagi
Uwaga 1: Można zaprogramować funkcję bardziej rozbudowaną, która będzie poprawnie rozpoznawała jako liczby stałe dwójkowe, ósemkowe czy szesnastkowe…
Uwaga 2: Na koniec zajęc należy umieścić na e-portalu.
Uwaga 3: Można zaprogramować oba!
Uwaga 4: Można pokusić się o rozpoznawanie liczb całkowitych zapisanych ósemkowo (zaczynają się od cyfry 0
), później mogą być tylko cyfry z zakresu 0–7 i/lub szesnastkowo (zaczynają się od znaków 0x
lub 0X
)..
Jako odstępy traktuję również znaki nowej linii
\n
i tabulacji\t
. ↩︎Ale rozważamy wyłącznie typy podstawowe! ↩︎
Jako odstępy uważać będziemy dowolne „znaki białe" (to znaczy takie, które nie zostawiają na papierze żadnego czarnego śladu). Będą to odstęp, znak tabulacji (
\t
), znak nowej linii (\n
) i być może jeszcze jakieś… ↩︎