====== Biblioteka boost Tokenizer ======
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 =====
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.\\
template <
class TokenizerFunc = char_delimiters_separator,
class Iterator = std::string::const_iterator,
class Type = std::string
>
class tokenizer
Parametry szablonu:
* TokenizerFunc - funktor używany do dzielenia sekwencji
* Iterator - typ iteratora specyfikującego sekwencję
* Type - typ sekwencji\\
\\
Prosty przykład użycia biblioteki:
#include
#include
#include
using namespace std;
using namespace boost;
string str = "To jest, przyklad";
int main(){
//utorzenie domyślnego obiektu klasy tokenizer, w którym ciąg znaków string
//dzielony jest na podstawie odstępów i znaków interpunkcyjnych
tokenizer<> t(s);
//dostęp do pojedyńczych tokenówjest realizowany przy użyciu iteratorów
for(tokenizer<>::iterator beg=t.begin(); beg!=t.end();++beg){
cout << *beg << "\n";
}
return 0;
}
Wynikiem działania programu będzie sekwencja:
To
jest
przyklad
Lista konstruktorów oraz funkcji składowych:
//konstuktory
tokenizer(Iterator first, Iterator last,const TokenizerFunc& f = TokenizerFunc())
template
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)
//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
void assign(const Container& c)
//fukcja zmieniająca kontener przechowujący sekwencję oraz funkcję podziału na nowe
template
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ę
*/
===== Klasa Token Iterator =====
Klasa zapewnia dostęp do podciągów dzielonej sekwencji jak przy użyciu zeykłego iteratora.
template <
class TokenizerFunc = char_delimiters_separator,
class Iterator = std::string::const_iterator,
class Type = std::string
>
class token_iterator_generator
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''.
template
typename token_iterator_generator::type
make_token_iterator(Iterator begin, Iterator end,const TokenizerFunc& fun)
\\
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.
#include
#include
#include
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::type Iter;
Iter beg = make_token_iterator(s.begin(),s.end(),f);
Iter end = make_token_iterator(s.end(),s.end(),f);
for(;beg!=end;++beg){
cout << *beg << "\n";
}
return 0;
}
===== 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 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.
#include
#include
#include
using namespace std;
using namespace boost;
string str = ";;Hello|world||-foo--bar;yow;baz|";
int main()
{
typedef tokenizer >
tokenizer;
char_separator 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;
}
Wynikiem działania programu będzie sekwencja:
Zmiana argumentów konstruktora funktora na:
boost::char_separator sep("-;", "|", boost::keep_empty_tokens);
Wynikiem powyżej modyfikacji są puste podciągi oraz podciągi zawierające znak rozdzielający "|", co obrazuje wynik działania programu:
<> <> <|> <|> <> <|> <> <> <|> <>
\\
Lista konstruktorów oraz funkcji składowych:
//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
bool operator()(InputIterator& next, InputIterator end, Token& tok)
----
==== 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''\\
''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:
#include
#include
#include
using namespace std;
using namespace boost;
string s = "Pole1,\"wstawianie cytowania dookola pola umozliwia, uzywanie przecinkow\",Pole3";
int main(){
tokenizer > tok(s);
for(tokenizer >::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
return 0;
}
Wynikiem działania programu będzie sekwencja:
Pole1
wstawianie cytowania dookola pola umozliwia, uzywanie przecinkow
Pole3
\\
Klasa ''escaped_list_separator'' posiada dwa następujące konstruktory:
explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"')
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
\\
escaped_list_separator(string_type e, string_type c, string_type q):
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:
#include
#include
#include
using namespace std;
using namespace boost;
string s = "12252001";
int offsets[] = {2,2,4};
int main(){
offset_separator f(offsets, offsets+3);
tokenizer tok(s,f);
for(tokenizer::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
return 0;
}
\\
Klasa ''offset_separator'' posiada tylko jeden użyteczny konstruktor:
template
offset_separator(Iter begin,Iter end,bool bwrapoffsets = true, bool breturnpartiallast = true)
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]]//