|
//------------------------------------------------------------------------------
// FILE NAME: StringParser.cpp
// HEADER: StringParser.h
//
// PURPOSE: Implementation of the CStringParser class.
//
// DESCRIPTION: This class acepts a string and immediately parses it into
// separate fields based on the delimiter character specified by
// the programmer. The separated fields are stored in a
// CStringArray, and the 0th element in the array contains the
// original string. Access to the separated fields is 1-based
// (the first field is in index 1, and so on).
//
// If you are parsing quoted strings, it is IMPARATIVE that the
// quoted strings be formatted correctly. Otherwise you will get
// what appears to be bizarre results.
//
// DISCLAIMER: At first glance, it may seem like the code is somewhat verbose
// and I might have taken the long way around to perform some
// tasks, but I think it makes it easier for someone else to follow
// when I do that. Maintainability is probably the most important
// aspect of coding (after reliability of course).
//
// CHANGE HISTORY:
// DATE INIT CHANGE DESCRIPTION
// -------- ---- --------------------------------------------------------
// 07/20/2000 jms Initial code completed.
// 08/09/2000 jms Added a way to submit a new string to facilitate the use
// of the same object instance when a subsewquent string
// needs to be parsed.
// 01/12/2001 jms Added a way to find strings withion the parsed results.
// 01/20/2001 jms Added support for quoted strings.
//------------------------------------------------------------------------------
#include "stdafx.h"
#include "StringParser.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//------------------------------------------------------------------------------
// NAME: CStringParser::CStringParser()
//
// PURPOSE: Constructor - initializes the array of strings and calls the
// ParseString() function.
//
// PARMETERS: CString sString The string to be parsed
// char cDelimiter The delimiter character used to parse the
// string
//
// RETURNS: N/A
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 07/20/2000 jms Initial development.
//------------------------------------------------------------------------------
CStringParser::CStringParser(CString sString, char cDelimiter)
{
m_aStrings.SetSize(0,10);
ResetOriginalString(sString, cDelimiter);
}
//------------------------------------------------------------------------------
// NAME: CStringParser::CStringParser()
//
// PURPOSE: Constructor - initializes the array of strings and calls the
// ParseString() function.
//
// PARMETERS: CString sString The string to be parsed.
// char cDelimiter The delimiter character used to parse the
// string.
// char cQuoter The quote character we should be looking
// for.
//
// RETURNS: N/A
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- --------------------------------------------------------
// 01/20/2001 jms Added overloaded version of constructor to support
// quoted strings.
//------------------------------------------------------------------------------
CStringParser::CStringParser(CString sString, char cDelimiter, char cQuoter)
{
m_aStrings.SetSize(0,10);
ResetOriginalString(sString, cDelimiter, cQuoter);
}
//------------------------------------------------------------------------------
// NAME: CStringParser::~CStringParser()
//
// PURPOSE: Destructor - removes all of the array elements from the
// CStringArray.
//
// PARMETERS: None
//
// RETURNS: None
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 07/20/2000 jms Initial development.
// 08/09/2000 jms Added call to new Clear() function.
//------------------------------------------------------------------------------
CStringParser::~CStringParser()
{
Clear();
}
//------------------------------------------------------------------------------
// NAME: CStringParser::Clear()
//
// PURPOSE: Clears the string table.
//
// PARMETERS: None
//
// RETURNS: None
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 08/09/2000 jms Added function.
//------------------------------------------------------------------------------
void CStringParser::Clear()
{
if (m_nCount > 0)
{
m_aStrings.RemoveAll();
}
}
//------------------------------------------------------------------------------
// NAME: CStringParser::ResetOriginalString()
//
// PURPOSE: Clears the string table.
//
// PARMETERS: None
//
// RETURNS: None
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 08/09/2000 jms Added function.
//------------------------------------------------------------------------------
void CStringParser::ResetOriginalString(CString sString, char cDelimiter)
{
Clear();
m_aStrings.Add(sString);
m_cDelimiter = cDelimiter;
m_cQuoter = '\0';
m_nCount = 0;
ParseString();
}
//------------------------------------------------------------------------------
// NAME: CStringParser::ResetOriginalString()
//
// PURPOSE: Clears the string table.
//
// PARMETERS: None
//
// RETURNS: None
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 08/09/2000 jms Added function.
//------------------------------------------------------------------------------
void CStringParser::ResetOriginalString(CString sString, char cDelimiter, char cQuoter)
{
Clear();
m_aStrings.Add(sString);
m_cDelimiter = cDelimiter;
m_cQuoter = cQuoter;
m_nCount = 0;
ParseStringWithQuoter();
}
//------------------------------------------------------------------------------
// NAME: CStringParser::GetField()
//
// PURPOSE: Returns the CString stored in the array element specified by
// the nIndex parameter. If the specified index is greater than
// the number of elements, it is an error.
//
// PARMETERS: int nIndex The index of the desired array item.
//
// RETURNS: CString sBuffer the string retrieved from the array.
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 07/20/2000 jms Initial development.
//------------------------------------------------------------------------------
CString CStringParser::GetField(int nIndex)
{
CString sBuffer;
sBuffer.Empty();
if (m_nCount >= nIndex)
{
sBuffer = m_aStrings.GetAt(nIndex);
}
else
{
sBuffer = "ERROR: Array index out of range.";
}
return sBuffer;
}
//------------------------------------------------------------------------------
// NAME: CStringParser::ParseString()
//
// PURPOSE: Separates the fields out of a copy of the original string by
// searching for the specified delimiter character. As the string
// is searched, it becomes shorter by deleting the most recently
// found field (and the next delimiter, if one exists) from the
// beginning of itself.
//
// PARMETERS: None
//
// RETURNS: int The number of fields found in the original string.
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 07/20/2000 jms Initial development.
//------------------------------------------------------------------------------
int CStringParser::ParseString()
{
// get a copy of the string
CString sWorkString = GetOriginalString();
CString sBuffer;
int pos = 0;
m_nCount = 0;
// while the string is not empty...
while (!sWorkString.IsEmpty())
{
// find the position of the next delimiter
pos = sWorkString.Find(m_cDelimiter);
// if a delimiter is found
if (pos >= 0)
{
// store the field
sBuffer = sWorkString.Left(pos);
// delete the field and the found delimiter
sWorkString = sWorkString.Mid(pos + 1);
}
// otherwise, if a delimiter isn't found
else
{
// the rest of the string is a field
sBuffer = sWorkString;
// and make the string empty
sWorkString.Empty();
}
// add the field to the CStringArray
m_aStrings.Add(sBuffer);
// increment the counter
m_nCount++;
}
return m_nCount;
}
//------------------------------------------------------------------------------
// NAME: CStringParser::ParseStringWithQuoter()
//
// PURPOSE: Separates the fields out of a copy of the original string by
// searching for the specified delimiter character. As the string
// is searched, it becomes shorter by deleting the most recently
// found field (and the next delimiter, if one exists) from the
// beginning of itself.
//
// This version of ParseString handles a quoted string. A quoted
// string may have the specified delimiter in an embedded between
// quote characters, and this instance of the delimiter must be
// ignored.
//
// PARMETERS: None
//
// RETURNS: int The number of fields found in the original string.
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 01/20/2001 jms Added this function.
//------------------------------------------------------------------------------
int CStringParser::ParseStringWithQuoter()
{
// get a copy of the string
CString sWorkString = GetOriginalString();
CString sBuffer;
int pos = 0;
m_nCount = 0;
// while the string is not empty...
while (!sWorkString.IsEmpty())
{
// find the position of the next delimiter
pos = sWorkString.Find(m_cDelimiter);
// if a delimiter is found
if (pos >= 0)
{
// if the first character is the specified quoter
if (sWorkString.GetAt(0) == m_cQuoter)
{
// we have work to do
sBuffer.Empty();
int nLength = 0;
BOOL bDone = FALSE;
do
{
//add the next character
sBuffer += CString(sWorkString.GetAt(nLength));
nLength++;
// if string is longer than one char and both ends are the quote char
if (nLength > 1 && sBuffer.GetAt(nLength - 1) == m_cQuoter)
{
// we are done
bDone = TRUE;
}
} while (!bDone);
// adjust our work string
sWorkString = sWorkString.Mid(nLength + 1);
}
else
{
sBuffer = sWorkString.Left(pos);
sWorkString = sWorkString.Mid(pos + 1);
}
}
// otherwise, if a delimiter isn't found
else
{
// the rest of the string is a field
sBuffer = sWorkString;
// and make the string empty
sWorkString.Empty();
}
// add the field to the CStringArray
m_aStrings.Add(sBuffer);
// increment the counter
m_nCount++;
}
return m_nCount;
}
//------------------------------------------------------------------------------
// NAME: CStringParser::FindExact()
//
// PURPOSE: Searches the entire array (excluding item 0) for an exact match
// of the specified string.
//
// PARMETERS: CString sText The string we're looking for
// int& nElement The element number of the found string
// or SP_NOTFOUND if not found.
// BOOL bCaseSensitive Case sensitivity matters
//
// RETURNS: CString The matching string if any.
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// ---------- ---- -----------------------------------------------------------
// 01/12/2001 jms Added function.
//------------------------------------------------------------------------------
CString CStringParser::FindExact(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/)
{
if (!bCaseSensitive)
{
sText.MakeUpper();
}
*nElement = SP_NOTFOUND;
CString sResult = "";
BOOL bFound = FALSE;
for (int i = 1; i <= m_nCount; i++)
{
sResult = m_aStrings.GetAt(i);
if (!bCaseSensitive)
{
sResult.MakeUpper();
}
if (sResult == sText)
{
*nElement = i;
sResult = m_aStrings.GetAt(i);
bFound = TRUE;
break;
}
sResult.Empty();
}
return sResult;
}
//------------------------------------------------------------------------------
// NAME: CStringParser::Find()
//
// PURPOSE: Searches the entire array (excluding item 0) for any string that
// contains the specified string.
//
// PARMETERS: CString sText The string we're looking for
// int& nElement The element number of the found string
// or SP_NOTFOUND if not found.
// BOOL bCaseSensitive Case sensitivity matters
//
// RETURNS: CString The matching string if any.
//
// CHANGE LOG:
// DATE INIT DESCRIPTION
// -------- ---- -------------------------------------------------------------
// 01/12/01 jms Added function.
//------------------------------------------------------------------------------
CString CStringParser::Find(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/)
{
if (!bCaseSensitive)
{
sText.MakeUpper();
}
*nElement = SP_NOTFOUND;
CString sResult = "";
BOOL bFound = FALSE;
for (int i = 1; i <= m_nCount; i++)
{
sResult = m_aStrings.GetAt(i);
if (!bCaseSensitive)
{
sResult.MakeUpper();
}
if (sResult.Find(sText) >= 0)
{
//save the position at which we found the string
*nElement = i;
// get it again (so we can get it in it's native form)
sResult = m_aStrings.GetAt(i);
bFound = TRUE;
break;
}
sResult.Empty();
}
return sResult;
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.
My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.