📄 tokenizer.cpp
字号:
/* @doc
* @module Tokenizer.cpp | Implementation of a string tokenizer class.
* Example:
* CTokenizer st(_T("\"aaa\";bb;100;200000;33.33;999999999.999999999;true"), _T(";"));
* TRACE(_T("NextString Test<\"aaa\";bb;100;200000;33.33;999999999.999999999;true>"));
* TRACE(_T("NextString=<%s>"), st.NextString(TRUE, _T("dddd")));
* TRACE(_T("NextString=<%s>"), st.NextString(TRUE, _T("eeee")));
* TRACE(_T("NextInt=<%d>"), st.NextInt(55));
* TRACE(_T("NextLong=<%ld>"), st.NextLong(55555555555));
* TRACE(_T("NextFloat=<%g>"), st.NextFloat(66.66));
* TRACE(_T("NextDouble=<%lg>"), st.NextDouble(666666666666.6666666666666));
* TRACE(_T("NextBool=<%d>"), st.NextBool(FALSE));
*/
#include "stdafx.h"
#include "Tokenizer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////////////////
// @mfunc This is an empty constructor
// @rvalue void | not used
//
CTokenizer::CTokenizer()
{
m_nPosition = 0;
}
/////////////////////////////////////
// @mfunc This is an constructor
// @rvalue void | not used
//
CTokenizer::CTokenizer(
const CString string, //@parm String to examine
CString strDelim) //@parm String with single char delimiters
{
m_Copy = string;
m_Delimiter = strDelim;
m_nPosition = 0;
}
/////////////////////////////////////
// @mfunc This is a destructor
// @rvalue void | not used
//
CTokenizer::~CTokenizer()
{
}
/////////////////////////////////////
// @mfunc This is an constructor
// @rvalue void | not used
//
void CTokenizer::SetString(
const CString string) //@parm String to examine
{
m_Copy = string;
m_nPosition = 0;
}
/////////////////////////////////////
// @mfunc Extracts the next String token - empty tokens are allowed
// @rvalue CString | next token
//
CString CTokenizer::Next()
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
return strReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
return strReturn;
}
/////////////////////////////////////
// @mfunc Returns flag if more tokens are available
// @rvalue BOOL | TRUE if next token is available
//
BOOL CTokenizer::HasMoreTokens()
{
if (m_nPosition == m_Copy.GetLength())
return FALSE;
return TRUE;
}
/////////////////////////////////////
// @mfunc Returs next token - if no token available returns default
// Delimiters are allowed within quotes!
// @rvalue CString | next token as string
//
CString CTokenizer::NextString(
BOOL bRemoveQuotes,
CString strDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// at end - return default
if (nLen <= m_nPosition)
return strDefault;
// skip quotes if not wanted
if (bRemoveQuotes)
{
// skip to first quote
while (nLen > m_nPosition && m_Copy.GetAt(m_nPosition) != '\"')
m_nPosition++;
m_nPosition++; // skip quote
// copy
while (nLen > m_nPosition && m_Copy.GetAt(m_nPosition) != '\"')
{
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
m_nPosition++; // skip quote
// skip to next delimiter
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
return strReturn;
}
}
}
return strReturn;
}
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
return strReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
// we did not find any tokens simply return
return strReturn;
}
/////////////////////////////////////
// @mfunc Returns next token translated as int
// @rvalue int | next token converted to int - or default at error
//
int CTokenizer::NextInt(
int nDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
int nReturn = nDefault;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%d"), &nReturn);
return nReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
int nReturn = nDefault;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%d"), &nReturn);
return nReturn;
}
/////////////////////////////////////
// @mfunc Returns next token translated as long
// @rvalue int | next token converted to long - or default at error
//
long CTokenizer::NextLong(
long nDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
long nReturn = nDefault;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%ld"), &nReturn);
return nReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
long nReturn = nDefault;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%ld"), &nReturn);
return nReturn;
}
/////////////////////////////////////
// @mfunc Returns next token translated as float
// @rvalue float | next token converted to float - or default at error
//
float CTokenizer::NextFloat(
float fDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
float fReturn = fDefault;
strReturn.Replace(',','.'); // replace comma with dot for german numbers
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%g"), &fReturn);
return fReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
float fReturn = fDefault;
strReturn.Replace(',','.'); // replace comma with dot for german numbers
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%g"), &fReturn);
return fReturn;
}
/////////////////////////////////////
// @mfunc Returns next token translated as double
// @rvalue float | next token converted to double - or default at error
//
double CTokenizer::NextDouble(
double fDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
double fReturn = fDefault;
strReturn.Replace(',','.'); // replace comma with dot for german numbers
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%lg"), &fReturn);
return fReturn;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
double fReturn = fDefault;
strReturn.Replace(',','.'); // replace comma with dot for german numbers
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%lg"), &fReturn);
return fReturn;
}
/////////////////////////////////////
// @mfunc Returns next token as boolean value where FALSE can be coded as the string "false" or as the number 0
// and TRUE as string "true" or as number != 0.
// @rvalue BOOL | next token as boolean value or default if no token found
//
BOOL CTokenizer::NextBool(
BOOL bDefault)
{
CString strReturn;
int nLen = m_Copy.GetLength();
// if we have more characters in string
while (nLen > m_nPosition)
{
// check all delimiters
for (int i=0;i<m_Delimiter.GetLength();i++)
{
// if we find a delimiter or we find end of string return
if (m_Copy.GetAt(m_nPosition) == m_Delimiter.GetAt(i))
{
m_nPosition++;
int nReturn = 0;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%d"), &nReturn);
// if we cant translate to number try keyword
if (nFields < 1)
{
if (strReturn.CompareNoCase(BOOL_TRUE) == 0)
return TRUE;
else if (strReturn.CompareNoCase(BOOL_FALSE) == 0)
return FALSE;
else
return bDefault;
}
else if (nReturn == 0)
return FALSE;
else
return TRUE;
}
}
// copy char
strReturn += m_Copy.GetAt(m_nPosition);
m_nPosition++;
}
int nReturn = 0;
int nFields = ::sscanf ((LPCSTR)strReturn, _T("%d"), &nReturn);
// if we cant translate to number try keyword
if (nFields < 1)
{
if (strReturn.CompareNoCase(BOOL_TRUE) == 0)
return TRUE;
else if (strReturn.CompareNoCase(BOOL_FALSE) == 0)
return FALSE;
else
return bDefault;
}
else if (nReturn == 0)
return FALSE;
else
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -