Majchrzak Karolina Lewandowski Norbert

Podobne dokumenty
1. Podstawowe pojęcia dotyczące przetwarzania tekstów 2. Podstawowe operacje na łańcuchach znakowych 3. Naiwne wyszukiwanie wzorca w tekście 4.

(3 kwiecień 2014) Marika Pankowska Kamila Pietrzak

Liczby całkowite i rzeczywiste

Algorytmy i struktury danych. wykład 8

Anna Sobocińska Sylwia Piwońska

Podstawy Programowania Podstawowa składnia języka C++

INSTRUKCJA PUSTA. Nie składa się z żadnych znaków i symboli, niczego nie robi. for i := 1 to 10 do {tu nic nie ma};

lekcja 8a Gry komputerowe MasterMind

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

C++ wprowadzanie zmiennych

DANE TEKSTOWE W JĘZYKU C/C++ - TABLICE ZNAKOWE

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

wagi cyfry pozycje

Struktura pliku projektu Console Application

Palindromy. Przykładowe rozwiązanie

r. Tablice podstawowe operacje na tablicach

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Programowanie komputerowe. Zajęcia 4

Wykład IV PASCAL - łańcuch znaków, - procedury i funkcje, - sortowanie bąbelkowe

Pascal typy danych. Typy pascalowe. Zmienna i typ. Podział typów danych:

Języki programowania obiektowego Nieobiektowe elementy języka C++

Wstęp do programowania

Informatyka 1. Przetwarzanie tekstów

Ćwiczenie nr 6. Poprawne deklaracje takich zmiennych tekstowych mogą wyglądać tak:

Podstawy programowania w języku C++

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Zasady programowania Dokumentacja

Wykład 6. Wyszukiwanie wzorca w tekście

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

O podstawowych operacjach na tablicach. Mateusz Ziółkowski, MBiU II

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Podstawy programowania

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

ŁAŃCUCHY W JĘZYKU C/C++

1 P roste e t ypy p d a d n a ych c - c ąg ą g d a d l a szy 2 T y T py p z ł z o ł żo ż ne e d a d n a ych c : T BLICE

Podstawy programowania skrót z wykładów:

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Algorytmy i złożoności Wykład 5. Haszowanie (hashowanie, mieszanie)

Podstawy programowania

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Wstęp do programowania

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

dr inż. Jarosław Forenc

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Wykład 2 Składnia języka C# (cz. 1)

Zajęcia 4 procedury i funkcje

Programowanie komputerowe. Zajęcia 1

Programowanie i struktury danych

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

MACIERZE. Sobiesiak Łukasz Wilczyńska Małgorzata

Wstęp do programowania

Reprezentacja symboli w komputerze. Znaki alfabetu i łańcuchy znakowe. Programowanie Proceduralne 1

STL: Lekcja 1&2. Filozofia STL

Języki i metodyka programowania. Wprowadzenie do języka C

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Informatyka 1. Wyrażenia i instrukcje, złożoność obliczeniowa

WYKŁAD 3 (13 MARZEC 2014) LICZBY CAŁKOWITE I RZECZYWISTE. Bartosz Łakomy i Dariusz Dobiesz

Rozwiązanie. #include <cstdlib> #include <iostream> using namespace std;

Temat: Algorytmy wyszukiwania wzorca w tekście

- - Ocena wykonaniu zad3. Brak zad3

Podstawy programowania. 1. Operacje arytmetyczne Operacja arytmetyczna jest opisywana za pomocą znaku operacji i jednego lub dwóch wyrażeń.

Podstawy Programowania

Laboratorium 1. Programowanie II - Kierunek Informatyka. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej

1 Podstawy c++ w pigułce.

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Wykład II PASCAL - podstawy składni i zmienne, - instrukcje wyboru, - iteracja, - liczby losowe

1 abbbaabaaabaa -wzorzec: aaba

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Inicjacja tablicy jednowymiarowej

Algorytmy i struktury danych

Podstawy Programowania

Pliki wykład 2. Dorota Pylak

Wstęp do Informatyki

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wykład II PASCAL - podstawy składni i zmienne, - instrukcje wyboru, - iteracja cz. 1

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Wstęp do programowania

Podstawy programowania w języku C i C++

Wstęp do programowania

Podstawy programowania w C++

Przydatne sztuczki - sql. Na przykładzie postgres a.

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Podstawy algorytmiki i programowania - wykład 6 Sortowanie- algorytmy

Wstęp do programowania. Różne różności

Pytanie 1. Pytanie 2. Pytanie 3 WOJEWÓDZKI KONKURS INFORMATYCZNY. Treść pytania

while(wyrażenie) instrukcja

Pascal - wprowadzenie

Algorytmy i struktury danych. wykład 1

Programowanie 2 - Tablice i łańcuchy

Ilość cyfr liczby naturalnej

LibreOffice Calc VBA

Wstęp do programowania. Wykład 1

Programowanie w językach

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

Programowanie w języku Java

Podstawy programowania

Transkrypt:

Majchrzak Karolina Lewandowski Norbert

Współczesne komputery oprócz liczb przetwarzają również teksty. Teksty zbudowane są z ciągów znakowych, które możemy traktować jako tablice znaków dostęp do poszczególnych liter odbywa się, podobnie jak u tablic, poprzez indeks, czyli numer znaku w ciągu. W rzeczywistości znak przechowywany jest w pamięci komputera w postaci liczby kodu znaku. Rozróżniamy dwa rodzaje takich kodów 8 bitowe(najczęściej są to znormalizowane kody wg standardu ASCII ang. American Standard Code for Information Interchange Amerykański Standardowy Kod do Wymiany Informacji) i 16 bitowe (standard Unicode). Znaki 16 bitowe wprowadzono w celu ominięcia ograniczeń kodów 8 bitowych, które mogą reprezentować jedynie do 256 różnych znaków, co jest niewystarczające do reprezentowania wszystkich znaków narodowych oraz różnych symboli stosowanych w matematyce, fizyce i innych dziedzinach ludzkiej działalności. Jednym z podstawowych problemów znakowych jest problem wyszukiwania wzorca tzn. mając dany pewien ciąg znaków szukamy w innym ciągu znakowym miejsca, w którym występuje ciąg pierwszy. Taki problem często występuje podczas redagowania tekstów, gdy w większym tekście należy wyszukać określoną frazę. Informatycy poświęcili wiele pracy na rozwiązanie tego podstawowego problemy. W efekcie wynaleziono bardzo efektywne algorytmy wyszukiwania wzorca, które znajdują zastosowania również przy rozwiązywaniu innych problemów tekstowych.

W algorytmach tekstowych będziemy stosowali następujące ustalenia i oznaczenia: Alfabetem (ang. alphabet) będziemy nazywali skończony zbiór symboli (ang. the set of symbols) zwykle alfabet jest zbiorem liter, znaków, cyfr, jednakże w przypadku uogólnionym może to być dowolny zbiór obiektów, które można w jakiś sposób sklasyfikować. Skończone ciągi symboli alfabetu nazwiemy łańcuchami (ang. strings). Czasami w tym znaczeniu używa się terminów słowa (ang. words) lub teksty (ang. texts). Przez pusty łańcuch (ang. empty string) rozumiemy łańcuch nie zawierający ani jednego znaku. s[i] oznacza i-ty znak łańcucha s. Umówmy się, iż indeksy w łańcuchach rozpoczynają się od 0. W języku Pascal oraz Basic indeksy startują od wartości 1. Należy to uwzględniać w programach. My wybieramy wartość 0, robiąc ukłon w stronę języka C++, który jest o wiele bardziej popularny niż Pascal i Basic. s oznacza długość łańcucha (ang. string length), czyli liczbę przechowywanych w nim aktualnie znaków. Łańcuch pusty ma długość 0. s[i : j] oznacza fragment łańcucha (ang substring) zawierający kolejne znaki s[i] s[i + 1] s[i + 2]... s[j - 1]. Znak s[j] nie należy do tej sekwencji. Na przykład, jeśli s = "ALA MA BOCIANA", to s[4 : 9] = "MA BO". Taki fragment łańcucha s będziemy nazywali oknem (ang. string window).

Długość podłańcucha wyliczamy ze wzoru: s[i : j] = j - i Podłańcuch s[i : i] jest łańcuchem pustym posiada długość 0, co wynika bezpośrednio z podanego powyżej wzoru. s = t równość dwóch łańcuchów oznacza, iż są one tej samej długości oraz posiadają identyczne znaki na tych samych pozycjach. s[i : i + t ] = t oznacza to, iż fragment łańcucha s od pozycji i-tej do i + t - 1 zawiera dokładnie te same znaki, co łańcuch t. Na przykład, jeśli s = "ALA MA BOCIANA" i t = "MA", to zachodzi s[4 : 6] = t (zwróć uwagę, iż znak s[6] nie jest częścią podłańcucha s[4...6]).

Prefiks łańcucha s jest łańcuchem zbudowanym z k początkowych znaków: Pref(s) = s[0 : k] Sufiks łańcucha s jest łańcuchem zbudowanym z k końcowych znaków: Suff(s) = s[n - k : n] Pref(s) s[0 : k] s[0 : n] s[0 : n] Suff(s) s[n-k : n] Prefiks i sufiks mogą być puste, tzn. mogą nie zawierać żadnego znaku.

Maksymalny prefiks właściwy (ang. maximal proper prefix) obejmuje wszystkie znaki łańcucha s za wyjątkiem ostatniego. Podobnie maksymalny sufiks właściwy (ang. maximal proper sufix)obejmuje wszystkie znaki łańcucha za wyjątkiem pierwszego: max Pref(s) = s[0 : s - 1] max Suff(s) = s[1 : s ] Jeśli istnieje prefiks s, który jest równy sufiksowi s, to mówimy, iż tworzą one tzw. prefikso-sufiks : s Pref(s) Suff(s) Pref(s) = Suff(s) = Border(s)

Jeśli dany łańcuch s posiada prefikso-sufiks o długości k, to okresem (ang. period) nazywamy taką liczbę całkowitą d, że zachodzi warunek: s[0 : k] = s[d : n] Graficznie wygląda to tak: Border(s) s Border(s) d Border(s) s Border(s) Okres można obliczyć wg wzoru: d = s - Border(s) Maksymalny prefikso-sufiks łańcucha s oznacza najdłuższy prefiks i sufiks tego łańcucha, które są sobie równe.

Deklaracja zmiennych znakowych i dostęp do przechowywanych znaków We współczesnych językach programowania znaki są podstawowym typem danych. W pamięci komputera znak jest przechowywany w postaci liczby, którą nazywamy kodem znaku (ang. character code). Każdy znak posiada swój własny kod. Aby różne urządzenia systemu komputerowego mogły w ten sam sposób interpretować kody znaków, opracowano kilka standardów kodowania liter. Lazarus program prg; begin writeln('ąąććęęłłń ńóóśśźźżż'); end. ĄąĆćĘꣳŃńÓóŚśŹźŻ ż Code::Blocks #include <iostream> using namespace std; int main() { cout << "ĄąĆćĘꣳŃńÓóŚśŹźŻż \n"; return 0; } Free Basic Print "ĄąĆćĘꣳŃńÓóŚ śźźżż" End ą ĂŠ ŕú РˡîťĆč» ą ĂŠ ŕú Đ Ëˇîť Ćč» Powyższy program demonstruje niekompatybilność kodowania znaków w Windows ze znakami wyświetlanymi w oknie konsoli znakowej.

Zmienne znakowe deklarujemy w identyczny sposób jak zmienne innych typów: Dekl aracj a zmie nnej znak owej Lazarus Code::Blocks Free Basic... var c : char; wc : wchar;...... char c; wchar_t wc;...... Dim c As String * 1 Dim wc As Wstring * 1... Tak zadeklarowana zmienna c może przechowywać jeden znak ASCII, a zmienna wc jeden znak Unicode. Zmienne znakowe mogą również być zadeklarowane jako tablice znaków. De kla rac ja tab licy zna ko wej Lazarus Code::Blocks Free Basic... var c : array[0..99] of char; wc : array[0..99] of wchar;...... char c[100]; wchar_t wc[100];...... Dim c As String * 100 Dim wc As Wstring * 100...

Program tworzy trzyznakową tablicę i wpisuje do niej wyraz ALO. Następnie literki są wypisywane w kierunku odwrotnym: Lazarus Code::Blocks Free Basic program prg; var s : array[0..2] of char; begin s[0] := 'A'; s[1] := 'L'; s[2] := 'O'; writeln(s[2],s[1],s[0] ); end. #include <iostream> using namespace std; int main() { unsigned char s[3]; s[0] = 'A'; s[1] = 'L'; s[2] = 'O'; cout << s[2] << s[1] << s[0] << endl << endl; return 0; } OLA Wynik Dim s As String * 3 Mid(s,1) = "A" Mid(s,2) = "L" Mid(s,3) = "O" Print Mid(s,3,1); Print Mid(s,2,1); Print Mid(s,1,1) End

Kod znaku Przy przetwarzaniu tekstu często musimy odczytywać kody znaków zawartych w zmiennej znakowej lub zamieniać kody na odpowiadające im znaki na przykład w celu umieszczenia ich w tekście. W każdym z wybranych przez nas języków programowania istnieją odpowiednie do tego zadania narzędzia. Code::Blocks Code::Blocks Free Basic dostęp do kodu znaku ord(znak) (int)znak Asc(znak) zamiana kodu na znak chr(kod) (char) kod Chr(kod)

Konkatencja-łączenie łańcuchów Często zdarza się, iż chcemy połączyć dwa lub więcej tekstów w jeden tekst. Operacja łączenia tekstu nosi nazwę konkatencji (ang. concatenation). W przypadku łańcuchów jest to bardzo proste: Lazarus Code::Blocks Free Basic Łączymy łańcuch s1 z s2 i wynik połączenia umieszczamy w s3 s3 := s1 + s2; s3 = s1 + s2; s3 = s1 + s2

Wstawienie znaku/ciągu znaków do łańcucha Podmiana znaku w łańcuchu jest operacją prostą. Po prostu odwołujemy się do wybranego elementu w zmiennej łańcuchowej może nią być również tablica znaków i zapisujemy go nową zawartością: Lazarus Code::Blocks Free Basic Zamiana znaku na pozycji i- tej w łańcuchu s s[i] := 'znak'; s[i] := char(kod); s[i] = 'znak'; s[i] = kod Mid(s,i,1) = "znak" Mid(s,i,1) = Chr(kod)

Wstawienie znaku wymaga przesunięcia części znaków w zmiennej łańcuchowej, aby udostępnić miejsce na wstawiany znak. Operacja wstawiania znaku lub łańcucha znaków jest obsługiwana przez funkcje biblioteczne: Lazarus Code::Bloc ks Free Basic Wstawiamy łańcuch s1 na pozycję i- tą w łańcuchu s2 insert(s1, s2,i); s2.insert( i,s1); s2 = Left(s2,i-1) + s1 + Right(s2,Len(s2)-i+1) Język FreeBasic nie posiada bezpośredniej funkcji wstawiania znaku lub łańcucha do innego łańcucha. Dlatego posiłkujemy się dwoma funkcjami pomocniczymi: Left(s,i) Right(s,i) zwraca i pierwszych znaków łańcucha s. Jeśli i = 0, to zwraca łańcuch pusty. zwraca i ostatnich znaków łańcucha s. Jeśli i = 0, to zwraca łańcuch pusty.

Program umieszcza w łańcuchu tekstowym zdanie "Rudy lisek", a następnie wstawia łańcuch ", szybki" po słowie "Rudy". Lazarus Code::Blocks program prg; var s : ansistring; begin s := 'Rudy lisek'; writeln(s); insert(', szybki',s,5); writeln(s); writeln; end. #include <iostream> #include <string> } using namespace std; int main() { string s; s = "Rudy lisek"; cout << s << endl; s.insert(4,", szybki"); cout << s << endl << endl; return 0;

Free Basic Dim s As String s = "Rudy lisek" Print s s = Left(s,4) + ", szybki" + Right(s,6) Print s Print End Wynik Rudy Rudy, szybki lisek lisek

Usuwanie znaku z łańcucha Usunięcie znaku z łańcucha/tablicy polega na przesunięciu wszystkich znaków następujących za znakiem usuwanym o jedną pozycję w lewo. W ten sposób znak zostaje nadpisany znakiem sąsiadującym z prawej strony w efekcie zniknie on z łańcucha. Dla łańcuchów znakowych mamy w każdym z wybranych języków programowania gotowe funkcje usuwania znaku lub fragmentu łańcucha. Lazarus Code::Blocks Free Basic Usuwamy z łańcucha s n znaków począwszy od pozycji i-tej delete(s,i,n ); s.erase(i,n); s = Left(s,i-1) + Right(s,Len(s)-i-n+1)

Program umieszcza w łańcuchu tekstowym zdanie "Zielone, stare drzewko", a następnie wymienia wyraz "stare" na "wysokie". program prg; Var Lazarus Code::Blocks Free Basic s : ansistring; Begin s := 'Zielone, stare drzewko'; writeln(s); delete(s,10,5); insert('wysokie',s,10); writeln(s); writeln; end. #include <iostream> #include <string> using namespace std; int main() { string s; s = "Zielone, stare drzewko"; cout << s << endl; s.replace(9,5,"wysokie"); cout << s << end <<endl; } return 0; Wynik Zielone, stare drzewko Zielone, wysokie drzewko Dim s As String s = "Zielone, stare drzewko" Print s s = Left(s,9) + "wysokie" + Right(s,8) Print s End

Porównywanie łańcuchów Łańcuchy tekstowe możemy porównywać przy pomocy typowych operatorów porównań. Jednakże obowiązuje tutaj kilka zasad. Dwa łańcuchy są równe, jeśli składają się z takiej samej liczby znaków oraz zgadzają się ze sobą na każdej pozycji znakowej. Jeśli dwa łańcuchy mają różną długość, lecz krótszy łańcuch zawiera te same początkowe znaki c łańcuch dłuższy, to krótszy jest mniejszy, a dłuższy jest większy. W dwóch łańcuchach porównywane są znaki na odpowiadających sobie pozycjach znakowych aż do napotkania niezgodności kodów. Wtedy mniejszy łańcuch jest tym, który posiada na porównywanej pozycji znak o mniejszym kodzie. Na przykład: "ALA" > "AKACJA" kod literki L jest większy od kodu literki K. Taki sposób porównywania nosi nazwę leksykograficznego.

Naiwne wyszukiwanie wzorca w tekście W łańcuchu znakowym s znaleźć wszystkie wystąpienia wzorca p. Problem Wyszukiwania Wzorca WW (ang. pattern matching) to jeden z podstawowych problemów tekstowych, który intensywnie badali wybitni informatycy. Rozwiązaniem jest wskazanie w ciągu s wszystkich pozycji i takich, że zachodzi równość: s[i : i + p ] = p Oznacza to, iż wzorzec p jest fragmentem łańcucha s występującym na pozycji i-tej. Algorytm N naiwny ustawia okno o długości wzorca p na pierwszej pozycji w łańcuchu s. Następnie sprawdza, czy zawartość tego okna jest równa wzorcowi p. Jeśli tak, pozycja okna jest zwracana jako wynik, po czym okno przesuwa się o jedną pozycję w prawo i cała procedura powtarza się. Algorytm kończymy, gdy okno wyjdzie poza koniec łańcucha. Klasa pesymistycznej złożoności obliczeniowej algorytmu N jest równa O(n m), gdzie n oznacza liczbę znaków tekstu, a m liczbę znaków wzorca. Jednakże w typowych warunkach algorytm pracuje w czasie O(n), ponieważ zwykle wystarczy porównanie kilku początkowych znaków okna z wzorcem, aby stwierdzić, iż są one niezgodne.

Algorytm naiwny wyszukiwania wzorca w łańcuchu tekstowym Wejście s łańcuch znakowy p łańcuch wzorca Wyjście: Wszystkie pozycje wzorca p w łańcuchu s Elementy pomocnicze:w i pozycja okna, i N n długość łańcucha s, n N m długość wzorca p, m N Lista kroków K01: n s ; obliczamy długość łańcucha s K02: m p ; obliczamy długość wzorca p K03: Dla i = 0,1,... n - m wykonuj K04 K04: Jeśli p = s[i : i + m], to pisz i ; okno zawiera wzorzec? K05: Zakończ

Lazarus program prg; var s,p : ansistring; i : integer; begin randomize; // generujemy łańcuch s := ''; for i := 1 to 80 do s := s + chr(65 + random(3)); // generujemy wzorzec p := ''; for i := 1 to 3 do p := p + chr(65 + random(3)); // wypisujemy wzorzec writeln(p); // wypisujemy łańcuch write(s); // szukamy wzorca w łańcuchu for i := 1 to 78 do if p = copy(s,i,3) then write('^') else write(' '); writeln; writeln; end. #include <iostream> #include <string> #include <cstdlib> #include <time.h> using namespace std; int main() { string s,p; Code::Blocks int i; srand((unsigned)time(null)); // generujemy łańcuch s = ""; for(i = 0; i < 80; i++) s += char(65 + (rand() % 3)); // generujemy wzorzec p = ""; for(i = 0; i < 3; i++) p += char(65 + (rand() % 3)); // wypisujemy wzorzec cout << p << endl; // wypisujemy łańcuch cout << s; // szukamy wzorca w łańcuchu for(i = 0; i < 78; i++) cout << (p == s.substr(i,3)? "^" : " "); cout << endl << endl; return 0; }

Free Basic Dim As String s,p Dim As Integer i Randomize ' generujemy łańcuch s = "" For i = 1 To 80: s += Chr(65 + Cint(Rnd * 2)): Next ' generujemy wzorzec p = "" For i = 1 To 3: p += Chr(65 + Cint(Rnd * 2)): Next ' wypisujemy wzorzec Print p ' wypisujemy łańcuch Print s; ' szukamy wzorca w łańcuchu For i = 1 To 78 If p = Mid(s,i,3) Then Print "^";: Else Print " "; Next Print: Print End Wynik CBC AACBBAACCACBCCBABBBBABACAABAAACABCABBCBAAAAAAACCAAACBBAACABC BCCABCBCCBCBCAABACAC ^ ^ ^ ^ ^

Zliczanie słów w łańcuchu W łańcuchu s wyznaczyć liczbę wszystkich słów. Zadanie zliczenia słów (ang. words counting) sprowadza się do wyszukiwania liniowego znaków. Na początku pracy algorytmu ustawiamy znacznik słów t na false. Wartość true tego znacznika oznacza przetwarzanie znaków słowa. Licznik słów ls zerujemy. Teraz w pętli przeglądamy kolejne znaki łańcucha s. Jeśli napotkanym znakiem jest znak litery lub cyfry, to sprawdzamy stan znacznika t. Jeśli jest on ustawiony na false, to znaczy, iż napotkaliśmy w tekście początek słowa. W takim przypadku ustawiamy t na true i zwiększamy o 1 licznik ls. Jeśli znacznik t jest już ustawiony na true, to napotkaliśmy kolejną literę już zliczonego słowa nic nie robimy. Jeśli napotkamy inny znak, to traktujemy go jako separator i znacznik t zawsze zerujemy. Po przeglądnięciu wszystkich znaków łańcucha s w zmiennej ls mamy liczbę słów.

Algorytm zliczania wyrazów Wejście: s łańcuch tekstowy. Wyjście: Liczba słów zawartych w łańcuchu s. Elementy pomocnicze: i indeks znaków w łańcuchu s, i N ls licznik słów, ls N t znacznik słowa Lista kroków K01: ls 0 ; zerujemy licznik słów K02: t false ; zerujemy znacznik słowa K03: Dla i = 0,1,..., s - 1 wykonuj K04...K09 ; przeglądamy znaki łańcucha s K04: Jeśli s[i] = cyfra_lub_litera, idź do K07 K05: t false ; zerujemy znacznik słowa K06: Następny obieg pętli K03 K07: Jeśli t = true, następny obieg pętli K03 ; słowo już zliczone K08: t true ; ustawiamy znacznik słowa K09: ls ls + 1 ; zliczamy słowo K10: Zakończ z wynikiem ls

Program odczytuje wiersz znaków, a następnie zlicza występujące w nim wyrazy i wypisuje ich ilość. Lazarus program prg; var s : ansistring; i,ls : integer; t : boolean; begin readln(s); t := false; ls := 0; for i := 1 to length(s) do if s[i] in ['0'..'9','_','-', 'A'..'Z','a'..'z', 'Ą','ą','Ć','ć','Ę','ę', 'Ł','ł','Ń','ń','Ó','ó', 'Ś','ś','Ź','ź','Ż','ż'] then begin if not t then Begin t := true; inc(ls); end end else t := false; writeln(ls); writeln; end.

#include <iostream> #include <string> using namespace std; int main() { string s; int i,ls,n; unsigned char c; bool t; getline(cin,s); n = s.length(); t = false; ls = 0; for(i = 0; i < n; i++) { c = s[i]; Code::Blocks if(((c >= '0') && (c <= '9')) (c == '_') (c == '-') ((c >= 'A') && (c <= 'Z')) ((c >= 'a') && (c <= 'z')) (c == 164) (c == 165) (c == 143) (c == 134) (c == 168) (c == 169) (c == 157) (c == 136) (c == 227) (c == 228) (c == 224) (c == 162) (c == 151) (c == 152) (c == 141) (c == 171) (c == 189) (c == 190)) { if(!t) { t = true; ls++; } } else t = false; } cout << ls << endl << endl; return 0; }

Free Basic Dim As String s Dim As Uinteger i,ls,n,t,c Line Input s n = Len(s): t = 0: ls = 0 For i = 1 To n c = Asc(Mid(s,i,1)) If(((c >= Asc("0")) And (c <= Asc("9"))) Or (c = Asc("_")) Or (c = Asc("-")) Or _ ((c >= Asc("A")) And (c <= Asc("Z"))) Or((c >= Asc("a")) And (c <= Asc("z"))) Or _ (c = 164) Or (c = 165) Or (c = 143) Or (c = 134) Or (c = 168) Or (c = 169) Or _ (c = 157) Or (c = 136) Or (c = 227) Or (c = 228) Or (c = 224) Or (c = 162) Or _ (c = 151) Or (c = 152) Or (c = 141) Or (c = 171) Or (c = 189) Or (c = 190)) Then If t = 0 Then t = 1: ls += 1 End If Else t = 0 End If Next Print ls Print End Wynik Ala ma krokodyla z plastiku i gumy, ale co to nas obchodzi. 12

Dzielenie łańcucha na słowa Operacja podziału łańcucha znaków na zawarte w nim słowa (ang. splitting into words) jest często wykonywana jako wstęp do różnych algorytmów tekstowych. W naszym prostym algorytmie w pętli będą wydobywane kolejne słowa z łańcucha s. Słowa te mogą być następnie odpowiednio przetworzone przez inny algorytm. Zasada pracy jest następująca: Tworzymy pusty łańcuch ss, w którym będą gromadzone znaki wydobywanego słowa. Na końcu łańcucha s umieszczamy wartownika dowolny znak nie będący literą ani cyfrą może to być np. spacja. Wartownik zagwarantuje nam przetworzenie wszystkich słów łańcucha s. Następnie przeglądamy kolejne znaki łańcucha s. Jeśli przeglądany znak jest literą lub cyfrą, to dołączamy go do łańcucha ss. W przeciwnym razie, jeśli łańcuch ss zawiera znaki, przetwarzamy je jako słowo, po czym łańcuch ss zerujemy będzie on gotowy na przyjęcie nowych znaków dla kolejnego słowa.

Algorytm podziału łańcucha na słowa Wejście: s łańcuch tekstowy. Wyjście: kolejne słowa zawarte w łańcuchu s. Elementy pomocnicze: i indeks znaków w łańcuchu s, i N ss łańcuch zawierający kolejne słowa z łańcucha s K01: ss "" ; zerujemy łańcuch słowa K02: s s + wartownik ; na końcu łańcucha s umieszczamy wartownika K03: Dla i = 0,1,..., s - 1 wykonuj K04...K09 ; przeglądamy kolejne znaki łańcucha s K04: Jeśli s[i] = cyfra_lub_litera, to idź do K09 ; litery i cyfry dołączamy do łańcucha ss K05: Jeśli ss = "", to następny obieg pętli K03 ; sprawdzamy, czy ss zawiera jakieś słowo K06: Przetwarzaj ss ; przetwarzamy wydobyte słowo K07: ss "" ; zerujemy ss dla następnego słowa K08: Następny obieg pętli K03 K09: ss ss + s[i] ; dołączamy znak s[i] do łańcucha ss K10: Zakończ

Wynik Człowiek nie lubi pracować, bo i po co miałby to robić? [Człowiek] [nie] [lubi] [pracować] [bo] [i] [po] [co] [miałby] [to] [robić]