Różnice między wybraną wersją a wersją aktualną.
| Next revision | Previous revision | ||
| tokenizer [2008/04/12 13:45] mplacht1 utworzono | tokenizer [2008/04/14 08:45] (aktualna) mplacht1 | ||
|---|---|---|---|
| Linia 1: | Linia 1: | ||
| ====== Biblioteka boost Tokenizer ====== | ====== Biblioteka boost Tokenizer ====== | ||
| - | Biblioteka boost Tokenizer zapewnia elastyczny i łatwy w użyciu mechanizm dzielenia dowolnych łańcuchów znakowych na serię tokenów, grup znaków o podanych cechach. Biblioteka umożliwia wybór metody podziału łańcucha poprzez parametryzowane funktory TokenizerFunction.  | + | Biblioteka boost Tokenizer zapewnia elastyczny i łatwy w użyciu mechanizm dzielenia dowolnych łańcuchów znakowych na serię podciągów (tokens), grup znaków o podanych cechach. Biblioteka umożliwia wybór metody podziału łańcucha poprzez parametryzowane funktory ''TokenizerFunction''.\\ | 
| ===== Klasa Tokenizer ===== | ===== Klasa Tokenizer ===== | ||
| - | Powyższa klasa umożliwia widok na sekwencję znaków jak na kontener zawierający tokeny. Dostęp do tokenów zawartych w takim kontenerze zapewniony jest za pomocą iteratorów zdefiniowanych w bibliotece. Klasa tokenizer jest klasą szablonową pozwalającą tworzyć obiekty dzielące sekwencje znakowe określonego typu według okrślonego sposobu podziału. Warto zauważyć,że podany łańcuch znakowy nie jest dzielony w czasie inicjalizacj obiektu, lecz na żądanie. | + | Powyższa klasa umożliwia widok na sekwencję znaków jak na kontener zawierający podciągi. Dostęp do podciągów zawartych w takim kontenerze zapewniony jest za pomocą iteratorów zdefiniowanych w bibliotece. Klasa ''tokenizer'' jest klasą szablonową pozwalającą tworzyć obiekty dzielące sekwencje znakowe określonego typu według określonego sposobu podziału. Warto zauważyć,że podany łańcuch znakowy nie jest dzielony w czasie inicjalizacj obiektu, lecz na żądanie.\\ | 
| <code cpp> | <code cpp> | ||
| Linia 13: | Linia 13: | ||
| class tokenizer | class tokenizer | ||
| </code> | </code> | ||
| - | Parametrami szablonu są: | + | Parametry szablonu: | 
| * TokenizerFunc - funktor używany do dzielenia sekwencji | * TokenizerFunc - funktor używany do dzielenia sekwencji | ||
| * Iterator - typ iteratora specyfikującego sekwencję | * Iterator - typ iteratora specyfikującego sekwencję | ||
| - | * Type - typ sekwencji | + | * Type - typ sekwencji\\ | 
| - | ---- | + | \\ | 
| Prosty przykład użycia biblioteki: | Prosty przykład użycia biblioteki: | ||
| <code cpp> | <code cpp> | ||
| Linia 28: | Linia 27: | ||
| using namespace boost; | using namespace boost; | ||
| - | string str = "To jest, prosty przyklad"; | + | string str = "To jest, przyklad"; | 
| int main(){ | int main(){ | ||
| Linia 39: | Linia 38: | ||
| cout << *beg << "\n"; | cout << *beg << "\n"; | ||
| } | } | ||
| + | return 0; | ||
| } | } | ||
| </code> | </code> | ||
| Linia 45: | Linia 45: | ||
| To | To | ||
| jest | jest | ||
| - | prosty | ||
| przyklad | przyklad | ||
| </code> | </code> | ||
| + | Lista konstruktorów oraz funkcji składowych: | ||
| + | <code cpp> | ||
| + | //konstuktory | ||
| + | tokenizer(Iterator first, Iterator last,const TokenizerFunc& f = TokenizerFunc())  | ||
| - | ===== Iteratory Token Iterator ===== | + | template<class Container> | 
| + | tokenizer(const Container& c,const TokenizerFunc& f = TokenizerFunc()) | ||
| + | //fukcja zmieniająca iteratory wskazujące na początek i za koniec sekwencji na nowe | ||
| + | void assign(Iterator first, Iterator last) | ||
| - | ===== Funktory TokenizerFunction ===== | + | //fukcja zmieniająca iteratory wskazujące na początek i za koniec sekwencji oraz funkce podziału na nowe | 
| + | void assign(Iterator first, Iterator last, const TokenizerFunc& f) | ||
| + | //fukcja zmieniająca kontener przechowujący sekwencję na nowy | ||
| + | template<class Container> | ||
| + | void assign(const Container& c) | ||
| + | //fukcja zmieniająca kontener przechowujący sekwencję oraz funkcję podziału na nowe | ||
| + | template<class Container> | ||
| + | void assign(const Container& c, const TokenizerFunc& f) | ||
| + | |||
| + | //iterator wskazujący na pierwszy podciąg | ||
| + | iterator begin() const | ||
| + | |||
| + | //iterator wskazujący za ostatni podciąg | ||
| + | iterator end() const | ||
| + | |||
| + | /* c - kontener zawierający sekwencję do podziału | ||
| + | * f - funktor służący do podziału sekwencji | ||
| + | * first - iteraor wskazujący na początek dzielonej sekwencji | ||
| + | * last - iteraor wskazujący za dzieloną sekwencję | ||
| + | */ | ||
| + | </code> | ||
| + | |||
| + | ===== Klasa Token Iterator ===== | ||
| + | Klasa zapewnia dostęp do podciągów dzielonej sekwencji jak przy użyciu zeykłego iteratora. | ||
| + | <code cpp> | ||
| + | template < | ||
| + | class TokenizerFunc = char_delimiters_separator<char>,  | ||
| + | class Iterator = std::string::const_iterator, | ||
| + | class Type = std::string | ||
| + | > | ||
| + | class token_iterator_generator  | ||
| + | </code> | ||
| + | Parametry szablonu: | ||
| + | * TokenizerFunc - funktor używany do dzielenia sekwencji | ||
| + | * Iterator - typ iteratora specyfikującego sekwencję | ||
| + | * Type - typ sekwencji\\ | ||
| + | \\ | ||
| + | W celu utorzenia iteratora musimy podać iterator wskazujący na początek dzielonej sekwencji ''begin'', iterator wskazujący dokładnie za dzieloną sekwencję ''end'' oraz funkcję podziału sekwencji ''fun''. | ||
| + | <code cpp> | ||
| + | template<class Type, class Iterator, class TokenizerFunc> | ||
| + | typename token_iterator_generator<TokenizerFunc,Iterator,Type>::type  | ||
| + | make_token_iterator(Iterator begin, Iterator end,const TokenizerFunc& fun) | ||
| + | </code> | ||
| + | \\ | ||
| + | Przykład użycia przy wykorzystaniu funktora ''offset_separator'' (opisanego dalej) dzielącego łańcuch znakowy na podciągi o określonej długości. | ||
| + | <code cpp> | ||
| + | #include<iostream> | ||
| + | #include<boost/token_iterator.hpp> | ||
| + | #include<string> | ||
| + | |||
| + | using namespace std; | ||
| + | using namespace boost; | ||
| + | |||
| + | string s = "12252001"; | ||
| + | int offsets[] = {2,2,4}; | ||
| + | |||
| + | int main(){ | ||
| + | offset_separator f(offsets, offsets+3); | ||
| + | typedef token_iterator_generator<offset_separator>::type Iter; | ||
| + | Iter beg = make_token_iterator<string>(s.begin(),s.end(),f); | ||
| + | Iter end = make_token_iterator<string>(s.end(),s.end(),f);  | ||
| + | for(;beg!=end;++beg){ | ||
| + | cout << *beg << "\n"; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | ===== Funktory TokenizerFunction ===== | ||
| + | TokenizerFunction  jest funktorem, którego zadaniem jest dzielenie podanej sekwencji znaków dopóki zostanie znaleziony dokładnie jeden podciąg lub osiągnięty koniec sekwencji. Następnie uaktualnia podciąg i informuje o położeniu w sekwencji elementu znajdującgo się dokładnie za za znalezionym podciągiem.\\ | ||
| + | |||
| + | Biblioteka zawiera trzy klasy funktorów TokenizerFunction: | ||
| + | * char_separator | ||
| + | * escaped_list_separator | ||
| + | * offset_separator\\ | ||
| + | \\ | ||
| ==== Klasa char_separator ==== | ==== Klasa char_separator ==== | ||
| + | Klasa char_separator dzieli sekwencje znaków w sposób podobny do funkcji ''strtok()'' używając w tym celu określonych znaków rozdzielających. Klasa ta jest używana w połączeniu z ''token_iterator'' oraz ''tokenizer'' w celu podziału na podciągi.\\ | ||
| + | \\ | ||
| + | Funkcja ''strtok()'' po dokonaniu podziału sekwencji nie umieszcza znaków rodzielających poszczególne podciągi. Jednak czasami okazuje się przydatnym posiadanie znaków rozdzielających pojawiających się w wyjściowej sekwencji podciągów, dlatego ''char_separator'' zapewnia takie rozwiązanie.\\ | ||
| + | Kiedy dwa znaki rozdzielające znajdują sie w sekwencji jeden za drugim. funkcja ''strtok()'' pomija je, natomiast ''char_separator'' pozwala również w takiej sytuacji na utworzenie pustego podciągu, w zależności od wyboru.\\  | ||
| + | \\ | ||
| + | Poniższy przykład pokazuje jak zastąpić funkcję ''strtok()'' za pomocą ''char_separator''. Określone są trzy znaki rozdzielające, które nie pojawią się w wyjściowych podciągach, puste podciągi będą ignorowane. | ||
| + | <code cpp> | ||
| + | #include <iostream> | ||
| + | #include <boost/tokenizer.hpp> | ||
| + | #include <string> | ||
| + | using namespace std; | ||
| + | using namespace boost; | ||
| + | |||
| + | string str = ";;Hello|world||-foo--bar;yow;baz|"; | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | typedef tokenizer<boost::char_separator<char> > | ||
| + | tokenizer; | ||
| + | char_separator<char> sep("-;|"); //utworzenie funktora z określonymi znakami rozdzielającymi | ||
| + | tokenizer tokens(str, sep); | ||
| + | for (tokenizer::iterator tok_iter = tokens.begin(); | ||
| + | tok_iter != tokens.end(); ++tok_iter){ | ||
| + | std::cout << "<" << *tok_iter << "> "; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | Wynikiem działania programu będzie sekwencja: | ||
| + | <code cpp> | ||
| + | <Hello> <world> <foo> <bar> <yow> <baz>  | ||
| + | </code> | ||
| + | Zmiana argumentów konstruktora funktora na: | ||
| + | <code cpp> | ||
| + | boost::char_separator<char> sep("-;", "|", boost::keep_empty_tokens); | ||
| + | </code> | ||
| + | Wynikiem powyżej modyfikacji są puste podciągi oraz podciągi zawierające znak rozdzielający "|", co obrazuje wynik działania programu: | ||
| + | <code cpp> | ||
| + | <> <> <Hello> <|> <world> <|> <> <|> <> <foo> <> <bar> <yow> <baz> <|> <> | ||
| + | </code> | ||
| + | \\ | ||
| + | Lista konstruktorów oraz funkcji składowych: | ||
| + | <code cpp> | ||
| + | //kostruktor tworzący obiekt char_separator, który może być następnie użyty do utworzenie token_iterator albo tokenizer  | ||
| + | //w celu podziału sekwencji na podciągi. Argumenty dropped_delims i kept_delims określają kolejno odrzucane i zachowywane  | ||
| + | //znaki rozdzielające. Jeżeli empty_tokens ma przypisane drop_empty_tokens, to puste podciągi będą odrzucane, a w wypadku  | ||
| + | //keep_empty_tokens będą zachowywane. | ||
| + | explicit char_separator(const Char* dropped_delims, | ||
| + | const Char* kept_delims = "", | ||
| + | empty_token_policy empty_tokens = drop_empty_tokens) | ||
| + | |||
| + | //konstruktor bezargumentowy, który tworzy obiekt w którym funkcja std::isspace() służy do identyfikacji odrzucanych znaków, | ||
| + | //a funkcja std::ispunct() do identyfikacji zachowyanych znaków rozdielających. Puste podciągi są odrzucane. | ||
| + | explicit char_separator() | ||
| + | |||
| + | //funkcja wywoływana przez token_iterator w celu podziału sekwencji | ||
| + | template <typename InputIterator, typename Token> | ||
| + | bool operator()(InputIterator& next, InputIterator end, Token& tok) | ||
| + | </code> | ||
| ---- | ---- | ||
| ==== Klasa escaped_list_separator ==== | ==== Klasa escaped_list_separator ==== | ||
| + | Klasa ''escaped_list_separator'' jest jedną z implementacji funktora TokenizerFunction. ''escaped_list_separator'' formatuje dane typu ''csv'' (''Comma Separated Values'' - wartości rozdzielone przecinkiem). Poniższy przykład obrazuje format, w którym użyto domyślnych znaków separatora, cytowania oraz znaku przywracającego znaczenie. | ||
| - | ---- | + | ''Pole 1,Pole 2,Pole 3''\\ | 
| - | ==== Klasa offset_separator ==== | + | ''Pole 1,"Pole2, z przecinkiem",Pole3''\\ | 
| + | ''Pole1,Pole2 z\"otoczony cytowaniem\",Pole3''\\ | ||
| + | ''Pole1, Pole2 z \n nowa linią,Pole3''\\ | ||
| + | ''Pole1, Pole2 z otoczonym \\,Pole3''\\ | ||
| + | Pola są domyślnie oddzielane przez przecinki. W celu wstawienia przecinka do pola, należy otoczyć go cytowaniem. Sekwencje trzech znaków przywracających znaczenie są wspierane. | ||
| + | \\ | ||
| + | Przykład użycia: | ||
| + | <code cpp> | ||
| + | #include<iostream> | ||
| + | #include<boost/tokenizer.hpp> | ||
| + | #include<string> | ||
| + | using namespace std; | ||
| + | using namespace boost; | ||
| + | string s = "Pole1,\"wstawianie cytowania dookola pola umozliwia, uzywanie przecinkow\",Pole3"; | ||
| + | int main(){ | ||
| + | tokenizer<escaped_list_separator<char> > tok(s); | ||
| + | for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg){ | ||
| + | cout << *beg << "\n"; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | Wynikiem działania programu będzie sekwencja:  | ||
| + | <code> | ||
| + | Pole1 | ||
| + | wstawianie cytowania dookola pola umozliwia, uzywanie przecinkow | ||
| + | Pole3 | ||
| + | </code> | ||
| + | \\ | ||
| + | Klasa ''escaped_list_separator'' posiada dwa następujące konstruktory: | ||
| + | <code cpp> | ||
| + | explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"') | ||
| + | </code> | ||
| + | Parametry konstruktora: | ||
| + | * e - określa znak, który przywraca pierwotne znaczenie znaku następującego po nim | ||
| + | * c - określa znak używany jako separator | ||
| + | * q - określa znak oznaczający cytowanie | ||
| + | \\ | ||
| + | <code cpp> | ||
| + | escaped_list_separator(string_type e, string_type c, string_type q): | ||
| + | </code> | ||
| + | Parametry konstruktora: | ||
| + | * e - znaki z łańcucha określaja znaki, które przywracają pierwotne znaczenie znaku następującego po nim, pusty łańcuch określa brak takiego znaku | ||
| + | * c - każdy znak z łańcucha określa znak używany jako separator, pusty łańcuch określa brak takiego znaku | ||
| + | * q - znaki z łańcucha określaja znak oznaczający cytowanie, pusty łańcuch określa brak takiego znaku | ||
| + | \\ | ||
| + | ---- | ||
| + | ==== Klasa offset_separator ==== | ||
| + | Klasa ''offset_separator'' jest kolejną z implementacji funktora TokenizerFunction, która może być użyta w celu podziału sekwencji na podciągi. ''offset_separator'' dzieli sekwencję znaków ''char'' na łańcuchy znakowe o określonej długości bazując na zdefiniowanych przesunięciach.\\ | ||
| + | Poniższy przykład dzieli sekwencję "12252001" przy użyciu przesunięc(2,2,4) na podciągi 12 25 2001: | ||
| + | <code cpp> | ||
| + | #include<iostream> | ||
| + | #include<boost/tokenizer.hpp> | ||
| + | #include<string> | ||
| + | using namespace std; | ||
| + | using namespace boost; | ||
| + | |||
| + | string s = "12252001"; | ||
| + | int offsets[] = {2,2,4}; | ||
| + | |||
| + | int main(){ | ||
| + | offset_separator f(offsets, offsets+3); | ||
| + | tokenizer<offset_separator> tok(s,f); | ||
| + | for(tokenizer<offset_separator>::iterator beg=tok.begin(); beg!=tok.end();++beg){ | ||
| + | cout << *beg << "\n"; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | \\ | ||
| + | Klasa ''offset_separator'' posiada tylko jeden użyteczny konstruktor: | ||
| + | <code cpp> | ||
| + | template<typename Iter> | ||
| + | offset_separator(Iter begin,Iter end,bool bwrapoffsets = true, bool breturnpartiallast = true) | ||
| + | </code> | ||
| + | Parametry konstruktora: | ||
| + | * begin, end - określają początek i koniec sekwencji przesunięć typu ''int'' | ||
| + | * bwrapoffsets - określa, czy przesunięcia po dojściu do końca ich sekwencji, mają być powtarzane cykilcznie ''true'', czy użyte tylko raz ''false'' | ||
| + | * breturnpartiallast - określa, czy podciąg mający mniej znaków niż wymaga to dane przesunięcie, ma być zachowywany ''true'', czy odrzucany ''false'' | ||
| + | \\ | ||
| + | \\ | ||
| + | --- //[[mplacht1@stud.elka.pw.edu.pl|Michał Płachta H1ISI]]// | ||