razzzar
17.02.2008, 03:25
Наверное все сталкивались с проблемой когда надо разбить строку по разделителям в многопоточном приложении. Функция strtok(); для этого не подходит, так как она использует статические элементы и при одновременом вызове в двух или более потоках работать будет некоректно ( я говорю о потоках, вызваных с помощью WinApi фун-ции CreateThread();, при использовании _beginthread она будет работать корректно, см. Рихтера ). Недавно я столкнулся с такой проблеме в одном из своих проектов, и для таких целей написал класс токенайзера.
Объявление:
class Tokenize
{
public:
Tokenize();
~Tokenize();
void SetOriginalString(char * szString);
char * GetOriginalString();
void SetTokens(char * szToken);
char * GetNextToken();
char * GetCurrentToken();
private:
std::string strOriginalString;
std::string strToken;
std::string strString;
bool bFinished;
int nCurrentPointer;
};
Описание:
Tokenize::Tokenize()
{
strString.assign("");
bFinished = false;
}
Tokenize::~Tokenize()
{
}
void Tokenize::SetOriginalString(char * szString)
{
strOriginalString.assign(szString);
strString.assign("");
strToken.assign("");
bFinished = false;
nCurrentPointer = -1;
}
char * Tokenize::GetOriginalString()
{
return (char *) strOriginalString.c_str();
}
void Tokenize::SetTokens(char * szToken)
{
strToken.assign(szToken);
}
char * Tokenize::GetNextToken()
{
if ( bFinished == true )
{
return NULL;
}
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find_first_of(strToken, 0);
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find("\0", 0);
bFinished = true;
if ( nCurrentPointer == -1 )
{
return NULL;
}
return (char *) strOriginalString.c_str();
}
strString.assign(strOriginalString.substr(0, nCurrentPointer));
return (char *) strString.c_str();
}
else
{
int nPrevPointer = nCurrentPointer + 1;
nCurrentPointer = (int) strOriginalString.find_first_of(strToken, nPrevPointer);
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find("\0", nPrevPointer);
bFinished = true;
if ( nCurrentPointer == -1 )
{
return NULL;
}
strString.assign(strOriginalString.substr(nPrevPoi nter, nCurrentPointer));
return (char *) strString.c_str();
}
strString.assign(strOriginalString.substr(nPrevPoi nter, nCurrentPointer - nPrevPointer));
return (char *) strString.c_str();
}
}
char * Tokenize::GetCurrentToken()
{
return (char *) strString.c_str();
}
Пример использования:
Tokenize tok;
tok.SetOriginalString("qwe|asd,zxc.ghj");
tok.SetTokens("|,.");
while ( tok.GetNextToken() != NULL )
{
MessageBox(0, tok.GetCurrentToken(), "Tokenize", 0);
}
Объявление:
class Tokenize
{
public:
Tokenize();
~Tokenize();
void SetOriginalString(char * szString);
char * GetOriginalString();
void SetTokens(char * szToken);
char * GetNextToken();
char * GetCurrentToken();
private:
std::string strOriginalString;
std::string strToken;
std::string strString;
bool bFinished;
int nCurrentPointer;
};
Описание:
Tokenize::Tokenize()
{
strString.assign("");
bFinished = false;
}
Tokenize::~Tokenize()
{
}
void Tokenize::SetOriginalString(char * szString)
{
strOriginalString.assign(szString);
strString.assign("");
strToken.assign("");
bFinished = false;
nCurrentPointer = -1;
}
char * Tokenize::GetOriginalString()
{
return (char *) strOriginalString.c_str();
}
void Tokenize::SetTokens(char * szToken)
{
strToken.assign(szToken);
}
char * Tokenize::GetNextToken()
{
if ( bFinished == true )
{
return NULL;
}
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find_first_of(strToken, 0);
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find("\0", 0);
bFinished = true;
if ( nCurrentPointer == -1 )
{
return NULL;
}
return (char *) strOriginalString.c_str();
}
strString.assign(strOriginalString.substr(0, nCurrentPointer));
return (char *) strString.c_str();
}
else
{
int nPrevPointer = nCurrentPointer + 1;
nCurrentPointer = (int) strOriginalString.find_first_of(strToken, nPrevPointer);
if ( nCurrentPointer == -1 )
{
nCurrentPointer = (int) strOriginalString.find("\0", nPrevPointer);
bFinished = true;
if ( nCurrentPointer == -1 )
{
return NULL;
}
strString.assign(strOriginalString.substr(nPrevPoi nter, nCurrentPointer));
return (char *) strString.c_str();
}
strString.assign(strOriginalString.substr(nPrevPoi nter, nCurrentPointer - nPrevPointer));
return (char *) strString.c_str();
}
}
char * Tokenize::GetCurrentToken()
{
return (char *) strString.c_str();
}
Пример использования:
Tokenize tok;
tok.SetOriginalString("qwe|asd,zxc.ghj");
tok.SetTokens("|,.");
while ( tok.GetNextToken() != NULL )
{
MessageBox(0, tok.GetCurrentToken(), "Tokenize", 0);
}