Języki i paradygmaty programowania 1 studia stacjonarne 2018/19 Lab 3. Stałe i zmienne znakowe. Tablice. Wskaźniki do tablic. Operacje na wskaźnikach. Instrukcja switch, case. Wyrażenie przecinkowe. Funkcje tekstowe. Tablice znakowe o dwóch indeksach, przekazywanie tablic do funkcji, dynamiczna alokacja pamięci, funkcje przetwarzające ciągi znakowe. Projekt nr 2. 1. char jest to typ znakowy, umożliwiający zapis znaków ASCII. Może też być traktowany jako liczba z zakresu 0..255 (Oznacza to, że każdy znak jest reprezentowany w pamięci przez swój kod. Kody znaków alfanumerycznych to liczby z przedziału *32 127+ pozostałe liczby są również kodami znaków, ale mogą być one różnie definiowane nie odpowiadają standardowi ASCII). Znaki zapisujemy w pojedynczych cudzysłowach (czasami nazywanymi apostrofami), by odróżnić je od łańcuchów tekstowych (pisanych w podwójnych cudzysłowach). Np. 'a';'7';'!'; '$'. i. Stała znakowa ma postać: 'znak' ii. Deklaracja zmiennej znakowej poprzez podanie kodu znaku spacji char i = 32; // i znak spacji iii. b. Deklaracja zmiennej znakowej poprzez podanie znaku char i = ' '; // i znak spacji //Zmienne znakowe wyprowadzanie znaków, ++i /* Kody ASCII */ int i = 32; /* int i=' '; jest poprawne */ while (++i < 128) printf("%3d %c ", i, i); if (!((i - 32) % 4)) printf("\n"); printf("\n"); //Zmienne znakowe wyprowadzanie znaków, i++ /* Kody ASCII */ char i = ' '; /* char i=32; jest poprawne */ while (i++ < 127) printf("%3d %c ", i, i); if (!((i - 32) % 4)) printf("\n"); printf("\n"); 2. Typ char to zwykły typ liczbowy i można go używać tak samo jak typu int (zazwyczaj ma jednak mniejszy zakres). Co więcej literały znakowe (np. 'a') są traktowane jak liczby i w języku C są typu int (w języku C++ są typu char). 3. Stała tekstowa dowolny ciąg znaków, zapisany w postaci: to jest stała tekstowa. Jeśli w stałej chcemy umieścić cudzysłów należy wtedy poprzedzić znak znakiem \ tzn. umieścić w tekście sekwencję \. Kompilator umieszcza tekst w odpowiedniej grupie bajtów (1B na symbol). Na końcu stałej tekstowej dopisywany jest znak o kodzie zero, czyli symbol \0. to jest stała tekstowa = 22 znaki łącznie ze spacjami. W pamięci komputera stała ta zajmie 23B razem ze znakiem \0. 4. Tablice znakowe używane są do zapisu ciągu znaków w pamięci komputera. Ciąg znaków (wiersz tekstowy) jest umieszczany w kolejnych bajtach pamięci. Każdy znak tego ciągu to odpowiedni element tablicy znakowej. Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 1
Definicja tablicy znakowej: char tekst[num]; gdzie: tekst to nazwa (identyfikator) tablicy, num maksymalna liczba znaków minus jeden tzw. rozmiar tablicy; musi być zdefiniowany jako stała. Elementy tablicy numerowane są od 0 do n-1 (numery elementów to tzw. indeksy tablicy) tekst[0], tekst[1],, tekst[n-2], tekst[n-1] przy czym tekst[n-1] -> '\0', pamięć zarezerwowana na num elementów: num >= n. Odwołanie do elementu tablicy o indeksie i następuje poprzez użycie operatora [ ] np.: tekst[i], a w każdym elemencie można zapisać tylko jeden znak np. : tekst[1]= 'a'. //Liczba powtórzeń litery a (1)-tablice tekstowe /*Ile razy litera a powtarza sie w tekscie*/ char d[max_line], b; int k, l; k = 0; l = 0; gets(d); while ((b = d[k])!= '\0') if (b == 'a') l++; k++; printf("%s\n%d\n", d, l); //Liczba powtórzeń litery a (2) - tablice tekstowe /*Ile razy litera a powtarza sie w tekscie*/ char d[max_line], b; int k = 0, l = 0; gets(d); while ((b = d[k++])!= '\0') if (b == 'a') l++; printf("%s\n%d\n", d, l); 5. Funkcja gets() - czyta linię ze standardowego wejścia (usuwa ją stamtąd) i umieszcza ją w tablicy znakowej wskazywanej przez str. Ostatni znak linii (znak nowego wiersza - '\n') zastępuje zerem (znakiem '\0'). Wartością zwracaną funkcji jest str (wskaźnik do tekstu) w przypadku sukcesu lub NULL w przypadku błędu lub natrafienia na koniec pliku. Funkcja nie sprawdza, czy jest miejsce do zapisu w tablicy str. Deklaracja: char *gets(char *str); 6. Wskaźnik do tablicy definicja tablicy rezerwuje odpowiednią grupę bajtów w pamięci i przypisuje nazwie (identyfikatorowi) tekst adres zerowego elementu. Nie wolno zmieniać wartości tekst jest to stała, wskaźnik początku tablicy. Dodatkowo identyfikator tekst nie jest L-value, tzn. że nie można go używać po lewej stronie instrukcji przypisania. Przykład 1: char str1[] = "abcde"; //debuger information: str1 = 0x0012fe44 "abcde" //str1[0] = 97 a, &str1[0] 0x0012fe44 "abcde" //str1[1] = 98 b &str1[1] 0x0012fe45 "bcde" Przykład 2: char str[256]; char *ptr = NULL; ptr = gets(str); //Przy wyjściu z gets str zawiera ciąg znaków, //wprowadzonych z monitora, ptr to jest wskaźnik do str: str 0x0012fe60 "abcdef" char[256] ptr 0x0012fe60 "abcdef" char * Przykład 3: Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 2
char *ptr = NULL; //ptr 0x00000000 ptr = "abcdefg"; //ptr 0x0041563c "abcdefg" char * //Uwaga! Pamięć pozostała wydzielona w obszarze roboczym. Ta informacja nie będzie chroniona. //Kod poprawny: ptr = (char *)malloc(256 * sizeof(char)); //dynamiczne wydzielenie pamięci w stercie (heap) if (!ptr) printf("błąd \n"); exit(1); sprintf(ptr, "abcdefg"); //... //jeżeli ptr jest już nie potrzebne zwolnij pamięć! if (ptr) free(ptr); ptr = NULL; //Liczba powtórzeń litery a (3) - tablice a wskaźniki /*Ile razy litera a powtarza sie w tekscie*/ char d[max_line], *dd; int l; l = 0; dd = gets(d); while (*dd!= '\0') if (*dd == 'a') l++; dd++; printf("%s\n%d\n", d, l); //Liczba powtórzeń litery a (4) - krótko /*Ile razy litera a powtarza sie w tekscie*/ char d[max_line], *dd; int l; l = 0; dd = gets(d); while (*dd) if (*dd++ == 'a') l++; printf("%s\n%d\n", d, l); 7. Instrukcja switch, case - tzw. warunek wielokrotnego wyboru lub przełącznik. Dzięki tej instrukcji możemy wykonywać decyzje tylko i wyłącznie na podstawie wartości jednej zmiennej. Możliwości instrukcji switch są nieporównywalnie mniejsze od możliwości funkcji if, jednak używanie jej w niektórych przypadkach jest znacznie korzystniejsze dla szybkości działania programu i estetyki kodu niż użycie funkcji if. Składnia: switch (zmienna) case wartosc_1: //jakiś kod case wartosc_2: //jakiś kod //... case wartosc_n: //jakiś kod default: //jakiś kod Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 3
Algorytm działania: 1. Obliczenie wartości zmienna 2. Jeśli zmienna == wartosc_i - wykonanie ciągu instrukcji (i + 1).ciąg instrukcji n, goto 3; jeśli zmienna!= wartosc_i - ciąg instrukcji default, goto 3 ; 3. Pierwszy operator poza blokiem switch W przypadku gdy operator default jest pominięty w deklaracji instrukcji switch: 1. Obliczenie wartości zmienna 2. Jeśli zmienna == wartosc_i - wykonanie ciągu instrukcji (i + 1).ciąg instrukcji n; pierwszy operator poza blokiem switch Ostatnim operatorem ciągu instrukcji i może być - przerywa on działanie switch i przekazuje sterowanie do pierwszego operatora poza blokiem switch. switch (i) case -1: n++; case 0: z++; case 1: p++; 8. Przykład: liczba wystąpień liter a, b oraz liter od b do y. //Instrukcje switch, case, break, continue /* Liczba wystąpień liter a, b oraz liter od b do y */ char d[max_line], *dd, b; int l, k, m; l = k = m = 0; dd = gets(d); while (b = *dd++, b!= '\0') if (!(b >= 'a' && b <= 'y')) continue; switch (b) case 'a': l++; case 'b': k++; default: m++; printf("%d %d %d\n", l, k, m); Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 4
9. Operator przecinkowy, wyrażenie przecinkowe. Operator przecinkowy jest operatorem o najniższym priorytecie i jest lewostronnie łączny. Wyrażenie przecinkowe to wrażenie postaci: wyrazenie_1, wyrazenie_2 Wartością wyrażenia przecinkowego jest wartość wyrazenie_2. 10. Przykład: liczba słów w jednej linii tekstu. //Liczba słów w linii tekstu (1) char d[max_line], *dd, p = ' ', b; dd = gets(d); printf("%s\n", dd); /* Tu zostanie wyprowadzony cały wczytany tekst */ while ((b = *dd)!= '\0') if (b!= ' ') if (p == ' ') l++; p = b; dd++; /* A tu zostanie wyprowadzony pusty tekst */ printf("%s\n", dd); 11. Przykład: liczba słów w jednej linii tekstu tablice w argumentach funkcji. //Liczba słów w linii tekstu (2) - tablice w argumentach funkcji int ile_slow_1(char *), ile_slow_2(char *), ile_slow_3(char *), ile_slow(char *); char d[max_line], *dd; int l; dd = gets(d); /* Tu zostanie wyprowadzony caly wczytany tekst */ printf("%s\n", dd); l = ile_slow_1(d); l = ile_slow_2(dd); /* I tu zostanie wyprowadzony caly wczytany tekst */ printf("%s\n", dd); l = ile_slow_3(d); Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 5
l = ile_slow(dd); int ile_slow_1(char te[]) /* Ile jest slow w linii tekstu. Tablice w argumentach funkcji*/ char p = ' ', b; int l = 0, i = 0; while (b = te[i++]) if (b!= ' ') if (p == ' ') l++; p = b; return l; int ile_slow_2(char *te) /* Ile jest slow w linii tekstu. Wskaźniki w argumentach funkcji*/ char p = ' ', b; while (b = *te) if (b!= ' ') if (p == ' ') l++; p = b; te++; return l; int ile_slow_3(char *te) /* Ile jest slow w linii tekstu. Elementy tablic == wskazanie pośrednie*/ char p = ' ', b; int l = 0, i = 0; while (b = te[i]) if (b!= ' ') if (p == ' ') l++; p = b; i++; return l; int ile_slow(char *te) char p, b = ' '; while (p = b, b = *te++) if (b!= ' ' && p == ' ') l++; return(l); 12. Operacje na tekstach wybrane funkcje. Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 6
Funkcja strcpy() Funkcja kopiuje łańcuch znaków (src) do tablicy znaków (dest). Funkcja nie sprawdza czy łańcuch kopiowany zmieści się w tablicy docelowej. Nie istnieje wartość, która wskazywałaby na błędne wykonanie. Deklaracja: char * strcpy(char * dest, const char * src); Funkcja strcat() Dopisuje ciąg znaków (string) strfrom na końcu bufora (string) strto i zamyka symbolem końca \0. Zachowanie funkcji jest nieokreślone, jeśli bufory strto oraz strfrom wzajemnie się pokrywają. Funkcja zwraca wskaźnik do strto. Nie istnieje wartość, która wskazywałaby na błędne wykonanie. Deklaracja: char * strcat(char * strto, const char * strfrom); Funkcja strcmp() (znajduje się w bibliotece <string.h>) Porównuje ciągi znaków string1 i string2. Zwraca wartość (RetVal) typu int. RetVal: < 0 string1 < string2 = 0 string1 == string2 jeśli każdy znak ze string1 jest równy odpowiedniemu znakowi ze string2 > 0 string1 > string2 Deklaracja: int strcmp(const char * string1, const char * string2); Relacja nierówności: w języku C przyjęto, że string1 > string2, jeśli kod pierwszego symbolu ze string1 jest większy od kodu pierwszego symbolu ze string2. Jeśli pierwsze znaki są równe, porównujemy drugie itd. Funkcja strlen() (<string.h>) - oblicza długość łańcucha str. Jej działanie polega na zliczaniu znaków aż do napotkania 0 (znaku '\0'). 0 nie jest wliczane do długości. W przypadku łańcuchów nie zakończonych 0 jej działanie jest nieokreślone. Zwraca długość łańcucha str. Deklaracja: int strlen(char *str); Funkcja getchar() - czyta znak ze standardowego wejścia i go stamtąd usuwa. Wywołanie getchar() jest równoważne wywołaniu getc(stdin). Deklaracja: int getchar(void); Funkcja putchar ( ) - wysyła znak na standardowe wyjście. Wywołanie putchar ( c ) jest równoważne wywołaniu putc(c, stdout). Deklaracja: int putchar(int c); 13. Znajdź pozycję wybranego znaku w tekście. 14. Usuń z tekstu pierwsze wystąpienie wybranego znaku. 15. Zamień każde wystąpienie wybranego znaku na inny znak. 16. Dołącz tekst do innego tekstu. 17. Dołącz tekst od znaku o podanej pozycji na koniec innego teksu. 18. Zaproponuj i zaimplementuj algorytm, który przesunie zawartość N-elementowej tablicy cyklicznie o jedną pozycję w górę. (tzn. pierwszy element na miejsce drugiego, drugi na trzeci,..., ostatni na pierwszy). Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 7
19. Tablice możemy deklarować na kilka sposobów. W przypadku alokacji statycznej możemy je zadeklarować m.in. następująco: int tab1[5]; int tab2[5] = 2, 5, 3, 2, 5 ; int tab3[5] = 2, 2, 1 ; int tab4[5] = 0; int tab5[] = 1, 2, 3, 4, 5 ; Czym różnią (jeśli się różnią) powyższe sposoby? Zadeklaruj tablicę statyczną (bez inicjalizacji jej wartości - pierwszy sposób), podobnie tablicę globalną - jakie wartości przyjmują poszczególne elementy tablicy? Język C pozwala w sposób analogiczny na deklarację tablic wielowymiarowych. Przykłady tablic dwuwymiarowych: int matrix1[2][2]; int matrix2[2][2] = 1, 2, 3, 4 ; int matrix3[2][2] = 0; Czym jest nazwa tablicy - jaką przyjmuje wartość? Udowodnij swoją odpowiedź krótkim przykładem. 20. Tablice mogą być przekazywane do funkcji na dwa sposoby: poprzez referencję lub poprzez wskaźnik. Oznacza to, że przekazując tablicę nie jest tworzona jej kopia, a działania są wykonywane bezpośrednio na oryginalnej tablicy. Przekazywanie przez wartość jest niemożliwe. void myfun(int *tab) void myfun(int tab[]) 21. Tablica dwuwymiarowa to jednowymiarowa tablica wskaźników do jednowymiarowych tablic danego typu. char d[200][256]; rezerwuje miejsce w pamięci dla 200*256 zmiennych typu char; identyfikator d jest stałą o wartości równej adresowi elementu d[0][0]; wartość d[0] wskazuje na element d[0][0], wartość d[1] wskazuje na element d[1][0], itd.; wartości d, d[0], &d[0][0] są takie same. d, d[0], d[1], d[2], są stałymi nie wolno zmieniać ich wartości. Przykład: //Liczba słów w wielu liniach tekstu (1) - tablice o dwóch indeksach #pragma warning (disable: 4996) #include <string.h> #define MAX_LINES 200 FILE *fd = NULL; int ile_slow(char *); char d[max_lines][max_line]; int i, l; if (!(fd = fopen("dane.txt", "r"))) printf("blad otwarcia zbioru\n"); exit(2); Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 8
i = 0; l = 0; while (i < MAX_LINES && fgets(d[i], MAX_LINE, fd)!= (char*)null) l += ile_slow(d[i]); i++; fclose(fd); fd = NULL; /* TU funkcja ile_slow */ int ile_slow(char *te) char p, b = ' '; while (p = b, b = *te++) if (b!= ' ' && p == ' ') l++; return(l); 22. Funkcja fgets() czyta kolejne znaki ze strumienia stream i umieszcza je w tablicy znakowej wskazywanej przez str. Czytanie przerywa, gdy przeczyta size - 1 znaków, natrafi na koniec pliku lub znak końca linii (znak ten jest zapisywany do str). Na końcu fgets() dopisuje znak '\0'. W przypadku błędu lub natrafienia na koniec pliku wartością funkcji jest NULL. Deklaracja: char *fgets(char *str, int size, FILE *stream); 23. Dynamiczna alokacja pamięci - tworząc aplikacje zazwyczaj nie znamy z góry rozmiarów tablic jakie będą nam potrzebne. Często pamięć zarezerwowana przez stos jest niewystarczająca. Możemy wtedy skorzystać z dynamicznej alokacji pamięci. Język C dostarcza w tym celu funkcję malloc, która jako argument przyjmuje rozmiar bloku pamięci, który ma zaalokować, natomiast zwraca wskaźnik do zaalokowanej pamięci lub NULL w przypadku błędu. Przykładowo alokację 10 elementowej tablicy typu double możemy zapisać następująco: double *tab; tab = (double *)malloc(sizeof(double) * 10); if (!tab) //błąd alokacji Język C nie posiada mechanizmów automatycznego "odśmiecania pamięci" (tzw. garbage collecting). Procedura zarówno alokacji jak i dealokacji spoczywa na programiście. W celu zwolnienia pamięci korzystamy w funkcji free. Zwolnienie może być wykonane tylko raz. Pamiętajmy, aby po każdym użyciu funkcji free "zniszczyć" wskaźnik poprzez przypisanie wartości NULL. if (tab) free(tab); tab = NULL; Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 9
24. W przypadku tablic wielowymiarowych ich przekazywanie do funkcji znacznie się komplikuje. Aby przekazać tablicę wielowymiarową w sposób podobny do tablic jednowymiarowych musimy z góry znać stały rozmiar tablicy: void myfun(int tab[2][2]) void myfun(int (*tab)[2]) Rozwiązaniem powyższego problemu może być zapis tablicy dwuwymiarowej w jednym wymiarze - jednak nie zawsze jest to pożądane rozwiązanie. 25. Dynamiczna alokacja pamięci dla tablic wielowymiarowych - cały proces wygląda analogicznie do alokacji tablic jednowymiarowych - należy jedynie pamiętać, że musimy zaalokować każdy wiersz z osobna (podobnie w przypadku zwalniania pamięci). Przykładowa tablica 10x5 o elementach typu double: double **tab; tab = (double **)malloc(sizeof(double) * 10); if (!tab) //błąd alokacji for (int i = 0; i < 10; i++) tab[i] = (double *)malloc(sizeof(double) * 5); if (!tab[i]) //błąd alokacji if (tab) for (int i = 0; i < 10; i++) if (tab[i]) free(tab[i]); free(tab); tab = NULL; 26. Przykład dla tablic tekstowych: //Liczba słów w wielu liniach tekstu (2) - alokacja pamięci #pragma warning (disable: 4996) #include <string.h> #define MAX_LINES 200 FILE *fd = NULL; int ile_slow(char *); /* Ile slow w wielu liniach tekstu, alokacja pamieci */ char *d[max_lines], bufor[max_line]; int len, i, l; if (!(fd = fopen("dane.txt", "r"))) Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 10
printf("blad otwarcia zbioru\n"); exit(2); i = 0; l = 0; while (i < MAX_LINES && fgets(bufor, MAX_LINE, fd)) len = strlen(bufor); bufor[len - 1] = '\0'; if ((d[i] = (char *)malloc((unsigned)len)) == (char*)null) printf("brak pamieci\n"); exit(3); strcpy(d[i], bufor); l += ile_slow(d[i]); i++; fclose(fd); fd = NULL; /* Tekst w pamięci, tablica d przechowuje wskaźniki do linii tekstu */ int ile_slow(char *te) char p, b = ' '; while (p = b, b = *te++) if (b!= ' ' && p == ' ') l++; return(l); 27. Czym różnią się funkcje: malloc, calloc, realloc? 28. Korzystając z funkcji fgets napisz program, który będzie zaczytywał linia po linii tekst zapisany w pliku tekstowym, a następnie wyświetlał numer linii, liczbę dużych liter, liczbę małych liter i liczbę pozostałych znaków. Dla uproszczenia załóżmy, że tekst nie zawiera polskich znaków oraz maksymalna liczba znaków w pojedynczej linii wynosi 256. 29. Biblioteka stdlib.h dostarcza funkcji konwertujących ciąg znaków na liczbę (atoi, atof, atol, atoll) oraz liczby na ciąg znaków (itoa, _ecvt, _fcvt) - więcej informacji w dokumentacji MSDN oraz na wykładzie. 30. Tablice dwuwymiarowe w argumentach funkcji. Zmodyfikuj program z przykładu nr 26 tak, by algorytm liczenia liczby słów nie był zapisany w funkcji main() ale w funkcji o nazwie licz_slowa_1. W której zostanie wykorzystana funkcja ile_slow. Do funkcji licz_slowa_1 winien być przekazany cały przeczytany tekst przekażemy jedynie tablice wskaźników do poszczególnych linii tekstu. //Liczba słów w wielu liniach tekstu (3) - tablice 2-indeksowe w argumentach - argumenty funkcji main() #pragma warning (disable: 4996) #include <string.h> #define MAX_LINES 200 FILE *fd; Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 11
int ile_slow(char *), licz_slowa(char **), licz_slowa_1(char **); int main(int argc, char **argv) /* Ile slow w ielu liniach tekstu */ char *d[max_lines], bufor[max_line]; int len, i, l; if (argc!= 2) printf("zła liczba argumentów\n"); exit(1); if (!(fd = fopen(argv[1], "r"))) printf("blad otwarcia zbioru\n"); exit(2); i = 0; l = 0; while (i < MAX_LINES && fgets(bufor, MAX_LINE, fd)) len = strlen(bufor); bufor[len - 1] = '\0'; if (!(d[i] = (char*)malloc((unsigned)len))) printf("brak pamieci\n"); exit(3); strcpy(d[i], bufor); i++; d[i] = (char *)0; //znacznik końca tablicy wskaźników l = licz_slowa_1(d); /* Tekst w pamieci, tablica d - wskazniki do linii tekstu */ /* Tu funkcja ile_slow */ int ile_slow(char *te) char p, b = ' '; while (p = b, b = *te++) if (b!= ' ' && p == ' ') l++; return(l); int licz_slowa_1(char *te[]) int i, l = 0; i = 0; while (te[i]!= (char *)0) l += ile_slow(te[i]); i++; return l; Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 12
31. Przekazywanie tablic dwuindeksowych sprowadza się do przekazywania jednoindeksowej tablicy wskaźników do jej wierszy, czyli adresu początkowego elementu tablicy wskaźników. Poniższa funkcja licz_slowa jest modyfikacją funkcji licz_slowa_1. Deklaracje identyfikatora te w obu wersjach funkcji są w pełni równoważne. Bez względu na sposób deklarowania można odwoływać się do tekstów przez elementy tablic lub przez wskazanie pośrednie. int licz_slowa(char **te) while (*te) l += ile_slow(*te++); return l; 32. Zamień miejscami tekst z dwóch wybranych linii. 33. Wybierz z tekstu składającego się z wielu linii te linie, w których na początku znajduje się wybrany tekst. 34. Wstaw jedną linię teksu po linii o numerze n. 35. Wybierz z teksu słowo o podanej pozycji. Załóż, że ogranicznikiem słowa jest dwukropek. 36. Napisz program kodujący i dekodujący dowolne teksty posługując się alfabetem Morse a. W rozwiązaniu możesz wykorzystać poniższe tablice. char litery[] = 'a',165,'b','c',134,'d','e',169,'f','g','h','i','j','k','l',136, 'm','n',228,'o',162,'p','q','r','s',152,'t','u','v','w','x','y','z',190,1 71,'A',164,'B','C',143,'D','E',168,'F','G','H','I','J','K','L',157,'M','N ',227,'O',224,'P','Q','R','S',151,'T','U','V','W','X','Y','Z',189,141,' ','.',',','?',':','-','0','1','2','3','4','5','6','7','8','9','!','\0' ; char *mors[] = ".-",".-.-","-...","-.-.","-.-..","-..",".","..-..","..-.","--.","...","..",".---","-.-",".-..",".-..-","--","-.","--.--","---","---.",".--.","--.-",".-.","...","...-...","-","..-","...-",".--","-..-","-.- -","--..","--..-","--",".-",".-.-","-...","-.-.","-.-..","-..",".","..-..","..-.","--.","...","..",".---","-.-",".-..",".-..-","--","-.","--.-- ","---","---.",".--.","--.-",".-.", "...","...-...","-","..-","...-",".-- ","-..-","-.--","--..","--..-","--"," ",".-.-.-","--..--","..--..","---...","-...-","-----",".----","..---","...--","...-","...","-...","--...","---..","----.","!",0 ; 37. Przeanalizuj w trybie pracy krokowej następujące przykłady do wykładu 3: Wszystkie przykłady dostępne pod adresem: http://torus.uck.pk.edu.pl/~fialko/text/cc/przykl/ *Treści oznaczone kursywą pochodzą z różnych źródeł internetowych. Wydział Fizyki, Matematyki i Informatyki Politechniki Krakowskiej 13