Introduction
Well, I'm finally dragging myself kicking and screaming into the world of C#
and .Net. I've decided that in order to stay employable, I have to move away
from C++. Toward that end, I recently accepted a C# programming position, and
since I didn't want to start a new job cold, I figured I'd get some additional C#
experience by porting one or more of my C++/MFC articles to the .Net platform.
Update 21 Dec 2008: A recent comment about this code caused me to revisit it and resulted in a substantial rewrite of the
class in question. This article and the downloadable code have been updated to reflect these changes.
What the StringParser Class Is
Essentially, the StringParser
class accepts a delimited string, breaks it down into its delimited elements according
to the specified delimiter string (or character), and stores it in a string list. You can also add to, insert into, or delete fro
the list of parsed elements. Further it supports quoted strings.
While you might be inclined to say say that the string.Split()
method does the same thing, I agreee - to a point. It
does indeed allow you to split a string using a character or a string as a delimiter, but it doesn't support quoted elements, nor
does it (readily) provide a method for changing the list of elements.
Personally, I don't see much use for a delimiter string, but someone requested such a feature in my original MFC/VC6 article, and
the string.Split()
method provides the functonality, so I figured I'd give it a shot in this version of the class.
Another new feature (over and above what was provide din the C++ version of the article) is that when deleting a field, the
programmer has the choice of deleting all instances of a given string, the first instance, or the last instance.
In the original version of this article, I put the class into a class library project because it seemed to be the right thing to
do, but for the most recent version, I put it into the executing assembly just to keep things simple.
One item of note - this class is CLS compliant, so it can be put into its own asembly and used by any language supported by
dotNet.
The StringParser Class
The class itself isn't really that fancy, and can essentially be considered a wrapper around the string.Split()
method. The real action happens in the Parse()
method:
protected int ParseString(string text)
{
string[] parts = text.Split(m_delimiter.ToCharArray(), StringSplitOptions.None);
string combinedParts = "";
bool quoted = false;
foreach (string part in parts)
{
if (CharacterCount(m_quoteChar, part) == 1)
{
quoted = (quoted) ? false : true;
}
combinedParts += part;
if (quoted)
{
combinedParts += m_delimiter;
}
if (!quoted)
{
m_elementList.Add(combinedParts);
combinedParts = "";
}
}
return m_elementList.Count;
}
This version of the method is MUCH shorter than the original one because dave.dolan recently informed me of the fact that the
string.Split()
method supports delimiter strings. This in turn caused me to re-evaluate the code, and I came up with a
much lower-impact version and fixed a quote string bug in the process. In a nutshell, the method splits the string according to the
specified delimiter character, and the adds the individual parts to the internally maintained list. If the string is a quoted string
(and if the StringParser
object was told to handle quoted strings), the previously split parts are re-combined to for
the quoted string.
Note: In the interest of maintaining an accurate historical record, I left the original download in this article, and added
a new downoad with the much-improved code. The original code is an embarassment, but I think it's important for new programmers to
see how important it is to become as familiar as possible with the dotNet framework as possible.
The Sample Application
The sample application took three times longer to write than the actual class (again, due entirely to my lack of exposure to the
.Net framework. There's no real validation being done, so if you experience any quirks, let me know and I'll try to post updated
code. Better yet, be a programmer, fix them yourself, and then posrt your findings here.
Class Reference
namespace StringParserLib
{
public enum eDeleteAction { DeleteAll, DeleteFirst, DeleteLast };
public class StringParser
{
public List<string> Elements
public string Delimiter
public char QuoteCharacter
public StringParser()
public StringParser(string value)
public StringParser(string value, string delimiter)
public StringParser(string value, string delimiter, char quote)
protected void ProtectedInit()
protected void Clear()
protected bool IndexInRange(int index)
protected int ParseString(string text)
public int ResetOriginalString(string text, string delimiter, char quote)
public string ReassembleOriginalString()
public string GetField(int index)
public string GetField(int index, string textToRemove)
public int Find(string textToFind)
public int Find(int startingIndex, string textToFind)
public int FindExact(string textToFind)
public int FindExact(int startingIndex, string textToFind)
public int FindReverse(string textToFind)
public int FindReverseExact(string textToFind)
public void AddField(string textToAdd)
public int InsertField(int index, string textToInsert)
public bool DeleteField(int index)
public bool DeleteField(string textToDelete, bool exactMatch, DeleteAction deleteAction)
}
}
</string>
As you can see, the class is fairly straightforward, and using it is a simple matter for even the most novice of .Net
programmers (and don't forget - it's CLS compliant).
Change History
21 Dec 2008 (update inspired by comment from CP user dave.dolan - Thanks Dave!)
- Significant change to
StringParse
method. It's much shorter, and much more reliable. - Proper XML comments added.
- The original string is no longer stored in the object, so all
GetField
calls are now zero-based (the old version
was one-based). - Added new constructor overloads.
- Added new
Find
and FindExact
overloads that let you start the search at a specified index. - Added proper exception handling.
31 Jul 2007 - (based on comments submitted after initial article upload)
- Changed class to use .Net naming convention
- Renamed namespace and class to comply with first change describe above
- Eliminated hungarian notation (I feel somehow dirty as a result)
- Changed from using ArrayList to generic List
- Changed function comments to Intellisense-compatible summary tags
- Moved enum declaration outside the class
- Changed demo app to use .Net naming convention, including control names.
- Changed demo app to provide basic validation.
30 Jul 2007
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.