Click here to Skip to main content
Click here to Skip to main content

Parsing Command Line Arguments

, 18 Sep 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
Provide access to command line arguments via a SortedList

Introduction

At one time or another, most of us have to create a command console application that reads keys and key/value pairs from the command line. Fortunately, there's a Split function to help with parsing the text command line value. Unfortunately, it doesn't support text qualifiers or assignment operators.

In a previous article, I described how to make a Split Function that Supports Text Qualifiers. In this article, we will add additional support for command assignment operators. Additionally, we will provide access to the values via a SortedList to increase our ability to control the command line parameters.

Background

A SortedList is used to make it obvious that our key/value pairs will not be stored in the order in which they are listed in the command line. None of the collections based on the DictionaryBase object can guarantee that the values will be returned in the order in which they are added. Dictionaries nearly always reorder the data they contain. Using a SortedList makes this point obvious to beginners. This approach insulates beginners allowing them to make safe assumptions about how the collection will behave.

The SortedList Abstract Class

The following diagram shows the SortedList base class and the new TextParser abstract class. The properties and methods with an asterisk next to them are overridden or shadowed by the abstract class. For the sake of this article, we will only focus on the critical routines. If you want to see the completed class, you will need to download the samples.

Class Diagram

Sorting the Expression Property

One feature this class will provide is that it will sort the actual text expression. We begin by creating the Sort routine which will sort the Expression property. Since all of our values are already sorted in the list this will be a fairly simple task.

C#

private void Sort()
{
    string _KeyValue;

    m_Expression = string.Empty;

    if (this.Count>0)
    {
        foreach (string _KeyName in GetKeyList())
        {
            _KeyValue = System.Convert.ToString
                    (this.GetByIndex(base.IndexOfKey(_KeyName)));

            if ((_KeyValue==null) | (_KeyValue.Length==0))
            {
                m_Expression += this.Delimiter + _KeyName;
            }
            else
            {
                m_Expression += this.Delimiter + _KeyName + this.Operator + _KeyValue;
            }
        }
    }

    m_Expression = m_Expression.Trim();
}

VB.NET

Private Sub Sort()
    Dim _KeyValue As String

    m_Expression = String.Empty

    For Each _KeyName As String In GetKeyList()
        _KeyValue = Item(_KeyName)

        If _KeyValue Is Nothing _
        OrElse _KeyValue.Length = 0 Then
            m_Expression &= Delimiter & _KeyName
        Else
            m_Expression &= Delimiter & _KeyName & Operator & _KeyValue
        End If
    Next

    m_Expression = m_Expression.Trim
End Sub

Splitting and Parsing the Expression Property

We will create a Parse routine responsible for transferring the key/value pairs into the base class. It will use the Split function and extract the key/value pairs from the Expression property. For additional details about the Split function, refer to the article, "Split Function that Supports Text Qualifiers".

C#

private void Parse()
{
    string[] _Commands = Split(Expression, Delimiter, Qualifier, IgnoreCase);
    string _Key;
    string _Value;
    int _AOLoc;

    base.Clear();

    if (_Commands!=null)
    {
        foreach (string _Command in _Commands)
        {
            if (IgnoreCase)
            {
                _AOLoc = _Command.ToUpper().IndexOf(Operator.ToUpper());
            }
            else
            {
                _AOLoc = _Command.IndexOf(Operator);
            }

            if (_AOLoc > 0)
            {
                _Key = _Command.Substring(0, _AOLoc).Trim();
                _Value = _Command.Substring(_AOLoc + 1).Trim();
            }
            else
            {
                _Key = _Command.Trim();
                _Value = null;
            }

            if (!(base.ContainsKey(_Key)))
                base.Add(_Key, _Value);
        }
    }
}

VB.NET

Private Sub Parse()
    Dim _Commands() As String = Split(Expression, Delimiter, Qualifier, IgnoreCase)
    Dim _Key As String
    Dim _Value As String
    Dim _AOLoc As Integer

    MyBase.Clear()

    If Not _Commands Is Nothing Then
        For Each _Command As String In _Commands
            If IgnoreCase Then
                _AOLoc = _Command.ToUpper.IndexOf(Operator.ToUpper)
            Else
                _AOLoc = _Command.IndexOf(Operator)
            End If

            If _AOLoc > 0 Then
                _Key = _Command.Substring(0, _AOLoc).Trim
                _Value = _Command.Substring(_AOLoc + 1).Trim
            Else
                _Key = _Command.Trim
                _Value = Nothing
            End If

            'Duplicate keys are ignored suppressing error messages.
            If Not MyBase.ContainsKey(_Key) Then
                MyBase.Add(_Key, _Value)
            End If
        Next
    End If
End Sub

Finally... The Expression Property Itself

Whenever a value is assigned to the Expression property, we will need to parse the value and sort the expression.

C#

public string Expression
{
    get 
    {
        return m_Expression;
    }
    set
    {
        if (value==null) value = string.Empty;
        m_Expression = value.Trim();
        Parse();
        Sort();
    }
}

VB.NET

Public Property Expression() As String
    Get
        Return m_Expression
    End Get
    Set(ByVal Value As String)
        If Value Is Nothing Then Value = String.Empty
        m_Expression = Value.Trim
        Parse()
        Sort()
    End Set
End Property

Adding New Key/Value Pairs

Whenever we need to add a new value to the list, we can simply append the key/value pair to the Expression property and it will do the rest of the work for us.

It is important to verify that the value contains a delimiter so we know how to build the expression. We will rely on the consumer to provide a properly formatted string value that will support text qualifiers.

C#

public void Add(string key, string value)
{
    if (this.ContainsKey(key))
    {
        throw new ArgumentException("The specified key already exists");
    }
    else if ((value==null) | (value.Trim().Length==0))
    {
        Expression += Delimiter + key;
    }
    else if (((IgnoreCase) & (value.ToUpper().IndexOf(Delimiter.ToUpper()) > 0))
        | ((IgnoreCase) & (value.ToUpper().IndexOf(Qualifier.ToUpper()) >= 0))
        | (!(IgnoreCase) & (value.IndexOf(Delimiter) > 0))
        | (!(IgnoreCase) & (value.IndexOf(Qualifier) >= 0)))
    {
        Expression += Delimiter + key + Operator + Qualifier + value + Qualifier;
    }
    else
    {
        Expression += Delimiter + key + Operator + value;
    }
}

VB.NET

Public Shadows Sub Add(ByVal key As String, ByVal value As String)
    If Me.ContainsKey(key) Then
        Throw New ArgumentException("The specified key already exists")
    ElseIf value Is Nothing _
    OrElse value.Trim.Length = 0 Then
        Expression &= Delimiter & key
    ElseIf IgnoreCase AndAlso value.ToUpper.IndexOf(Delimiter.ToUpper) > 0 _
    OrElse IgnoreCase AndAlso value.ToUpper.IndexOf(Qualifier.ToUpper) >= 0 _
    OrElse Not IgnoreCase AndAlso value.IndexOf(Delimiter) > 0 _
    OrElse Not IgnoreCase AndAlso value.IndexOf(Qualifier) >= 0 Then
        Expression &= Delimiter & key & Operator & Qualifier & value & Qualifier
    Else
        Expression &= Delimiter & key & Operator & value
    End If
End Sub

Removing Values

Removing key/value pairs has become a straight forward task. All we need to do is remove the key/value from the base class and resort the expression. To Clear the class is even easier. We clear the values from the base class and reset the Expression property to an empty string.

C#

public void Remove(string key)
{
    if (this.ContainsKey(key))
    {
        base.Remove(key);
        Sort();
    }
}

public override void RemoveAt(int index)
{
    if (this.Count>index)
    {
        base.RemoveAt(index);
        Sort();
    }
}

public override void Clear()
{
    base.Clear();
    Expression = string.Empty;
}

VB.NET

Public Shadows Sub Remove(ByVal key As String)
    If Me.ContainsKey(key) Then
        MyBase.Remove(key)
        Sort()
    End If
End Sub

Public Overrides Sub RemoveAt(ByVal index As Integer)
    If Me.Count > index Then
        MyBase.RemoveAt(index)
        Sort()
    End If
End Sub

Public Overrides Sub Clear()
    MyBase.Clear()
    Expression = String.Empty
End Sub

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

LSteinle
Web Developer
United States United States
Larry Steinle is a systems analyst for HDR, Inc, a nationally recognized architecture, engineering, and consulting firm. He graduated with a certificate in Biblical Studies, an Associate in Computer Programming, and a Bachelor Degree in Management Information Systems.

Comments and Discussions

 
General"Is a" PinmemberJörgen Sigvardsson29-Aug-06 1:29 
GeneralRe: "Is a" PinmemberLSteinle29-Aug-06 17:27 
GeneralRe: "Is a" PinmemberRama Krishna Vavilala18-Sep-06 17:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 18 Sep 2006
Article Copyright 2006 by LSteinle
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid