Это должно быть идеальным случаем не изобретения велосипед, но до сих пор мой поиск был напрасно.
Вместо того, чтобы писать тот самостоятельно, я хотел бы использовать существующий токенизатор C++. Маркеры должны использоваться в индексе для полнотекстового поиска. Производительность очень важна, я проанализирую много гигабайтов текста.
Править: Обратите внимание на то, что маркеры должны использоваться в поисковом индексе. Создание таких маркеров не является точной наукой (afaik) и требует некоторой эвристики. Это было сделано в тысячу раз прежде, и вероятно тысячей различных способов, но я не могу даже найти одного из них :)
Какие-либо хорошие указатели?
Спасибо!
Я написал свой собственный токенизатор как часть системы индексации и поиска с открытым исходным кодом SWISH ++ .
Если производительность является основной проблемой, вам, вероятно, следует придерживаться старого доброго strtok , который обязательно будет быстрым:
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
Библиотека регулярных выражений может хорошо работать, если ваши токены не слишком сложны для анализа.
Я мог бы изучить std :: stringstream
из
. C-style strtok
имеет ряд проблем с удобством использования, а строки в C-стиле просто неприятны.
Вот ультратривиальный пример преобразования предложения в слова:
#include <sstream>
#include <iostream>
#include <string>
int main(void)
{
std::stringstream sentence("This is a sentence with a bunch of words");
while (sentence)
{
std::string word;
sentence >> word;
std::cout << "Got token: " << word << std::endl;
}
}
janks@phoenix:/tmp$ g++ tokenize.cc && ./a.out
Got token: This
Got token: is
Got token: a
Got token: sentence
Got token: with
Got token: a
Got token: bunch
Got token: of
Got token: words
Got token:
Класс std :: stringstream
является «двунаправленным» в том смысле, что он поддерживает ввод и вывод. Вы, вероятно, захотите сделать только один или другой, поэтому вы должны использовать std :: istringstream
или std :: ostringstream
.
Их прелесть в том, что они также являются std :: istream
и std :: ostream
соответственно, поэтому вы можете использовать их так же, как std. :: cin
или std :: cout
, которые, надеюсь, вам знакомы.
Некоторые могут возразить, что использование этих классов дорого; std :: strstream
из
в основном то же самое, но построено на основе более дешевых строк в стиле C с завершением 0. Возможно, это будет быстрее для вас. Но в любом случае я бы не стал сразу беспокоиться о производительности. Получите что-нибудь работающее, а затем протестируйте его. Скорее всего, вы сможете получить достаточную скорость, просто написав хорошо написанный C ++, который минимизирует создание и уничтожение ненужных объектов. Если все еще недостаточно быстро, вы можете поискать в другом месте. Однако эти классы, вероятно, достаточно быстрые. Ваш ЦП может тратить тысячи циклов на чтение блока данных с жесткого диска или сети.
Ну, я бы начал с поиска Boost и ... hop: Boost.Tokenizer
Хорошая вещь? По умолчанию он разбивается на пробелы и знаки препинания, потому что он предназначен для текста, поэтому вы не забудете символ.
Из введения:
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "This is, a test";
tokenizer<> tok(s);
for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
// prints
This
is
a
test
// notes how the ',' and ' ' were nicely removed
И есть дополнительные возможности:
итераторами
, поэтому вы можете использовать его с istream
напрямую ... и, следовательно, с ifstream
и несколькими опциями (например, сохранение пустых токенов и т. д.)
Проверьте это!
Вы можете использовать Ragel State Machine Compiler для создания токенизатора (или лексического анализатора).
Сгенерированный код не имеет внешних зависимостей.
Я предлагаю вам посмотреть на пример clang.rl для получения соответствующего примера синтаксиса и использования.