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

Yet Another Command Line Argument Parser

, 2 Jan 2005
Rate this:
Please Sign up or sign in to vote.
A reusable library to obtain command line parameters passed to executables in an orderly manner.

Introduction

When writing applications that require run-time information supplied by a command shell, the best way to communicate the additional information to your executable is via command line parameters. You frequently have to write code to parse the command line parameters looking for specific information to customize execution of your application. I'll show you how to write a reusable library callable from your code to expose the command line arguments as name-value pairs, allowing you to avoid having to write tedious parsing code over and over again in different projects.

Background

In the "C" family of languages, including C, C++ and C#, command line information is conveyed by the command shell to the running executable using a string array passed to the static main() function. The string array is composed of the text that followed the executable name, chopped up into sub-strings delimited by the space character. See the image above.

If you force your users to specify all possible parameters on every execution in a specific order, you ease your parameter reading grief and can just jump to specific indexes of the args[] array to get the parameter values. If you have any consideration at all for your users and allow them to specify parameters in any order they choose, or allow your users to specify optional parameters, you have to write code to identify parameters by their name and then to read the value associated with that variable.

There are several hundred examples of code that does similar work written in C and C++, and a few written in C# (hence the project name prefix "Yet Another..."). This code is different from the others on CodeProject in that it allows you to specify additional information to the parsing process to allow for idiosyncrasies in your command line syntax, and also to allow for the run-time parameters supplied to your applications to be removed into separate files for organization and easy re-use.

Using the code

The project consists of three classes enclosed in a single source code file:

  • ArgParser
  • VVPair
  • VVPairs

ArgParser is the main class you instantiate, handing the constructor the args string array passed to your executable. Optionally, you can specify the character you want to use to mark your argument names and the character you want to use to separate your variable names from their values. It's really a matter of style, but you can configure the class to parse arguments that look like this:

c:\>YACLAPTester.exe /user:kim /test:yes /verbose

or like this:

c:\>YACLAPTester.exe -user=kim -test=yes -verbose

Just pass '/' and ':' to the ArgParser constructor used by your YACLAPTester application in the first case (or don't specify any characters -> these are the defaults) or '-' and '=' to the constructor in the latter case.

The VVPair class holds the name of a variable (user, test and verbose in the examples above) and its value (Kim, yes and a zero length string above). The VVPairs class is a collection class of these custom variable-value pair objects. I considered using one of the intrinsic name-value pair types like StringDictionary and DictionaryEntry but decided against it. The slight amount of extra code allows you to be more flexible in processing.

When instantiated, the ArgParser constructor starts a two-phase process.

Phase I

The constructor iterates over the string array, and compares the initial character of each string in the array to two characters:

  • If the initial character is the variable definition character passed to the constructor, the string gets added as it is in its raw, unparsed form to an ArrayList object.
  • If the initial character is the "@" symbol, the constructor assumes that the string that follows names a file with additional parameters. It attempts to open the file and splits the file on the new line character into another array of strings. The constructor ignores the file name if it can't be found. You have to examine each string and check for the variable definition character in the first position, and if found, you add it to the ArrayList with the other parameters. Lines in the file that begin with characters other than the variable definition character are ignored and assumed to be comments.
  • If the first character of the string in the args array is neither the "@" sign nor the variable name character, it is ignored and not added to the ArrayList object. You can choose to be more assertive and throw an exception if the raw string does not start with the file specifier character, but I chose to just ignore them.

You'll be in good company if you support command parameter files. Microsoft is using this technique in supplying parameters to the C# 2.0 command line compiler through response file specifiers. They use files that are named *.rsp, but I'm not fussy about the extension here.

Phase II

Once phase I is complete, the ArrayList is full of the parameters found in the string array (and any expanded response files). The constructor will then loop through the ArrayList and examine each string. If the string starts with the variable specifier character, it will parse it into a new VVPair object, separating out the name of the variable from the value by the valueDelimiter character parameter, and add it to the VVPairs collection.

Once the VVPairs collection is populated at the end of the ArgParser constructor, you can allow the variables to be read by exposing an indexer property on the ArgParser class that returns a VVPair object based on a string passed to it. When I implemented the indexer property, I chose to return a new VVPair object if the name of the variable was not found in the collection, rather than null so you don't have to constantly test for uninitialized objects, and your code can look like this:

if (argParser["MyVariable"].Value == "true") {
   // Do some processing here
}

rather than like this:

VVPair pair = argParser["MyVariable"];
if (pair != null) {
   if (pair.Value == "true") {
      // Do some processing here
   }
}

Just compile the library, include it in your project (Console or Windows) and you can provide as much flexibility as your users need in initializing your application. The ArgParser class implements IDisposable, so just put it in a using{} block and it will clean up after itself nicely.

Points of interest

Nothing fancy about this code. Just drudge code that you've probably written a thousand times before.

History

  • Jan 1st 2005:
    • Initial revision.
  • Jan 4th 2005:
    • Corrected formatting of some sections.
  • Jan 27th2005:
    • Uploaded demo code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Sean Michael Murphy
Product Manager
Canada Canada
I'm a graduate of the University of Toronto with a degree in zoology. I'm currently a software development manager with a large Canadian financial institution, and a passionate squash player.
 
I am a proud daddy to Alex and Sarah.

Comments and Discussions

 
GeneralI use the class, but.... Pinmemberarie_b1627-Sep-06 5:19 
GeneralSupport for command line switches Pinmembereulernt12-Jul-06 15:02 
GeneralGreat Artical PinmembertareqGamal23-Jan-06 3:42 
thank u Very much about this artical ,
about my code :
I develop program which takes array of paths of files And Directories once and then analysis them inside the program
which can't done by this way ,
for example :
i want to pass :
c:\pics d:\Docs and Settings \my folder c:\MyFile
 
which come in the program as :
arg[0] = c:\pics
arg[1] =d:\docs
arg[2] =and
arg[3] = settings

and so on
 

expected :
arg[0] =c:\pics
arg[1] =d:\Docs and Settings \my folder
and so on
 
have i repair it inside the code?
if yes.. how ?
 
welcome for any comments , Questions
GeneralRe: Great Artical Pinmembereulernt12-Jul-06 12:31 
Generalvalidating args PinmemberBen Incani28-Sep-05 20:28 
GeneralRe: validating args PinmemberMike Russo10-Jul-06 8:26 
GeneralYACLAPTester.exe PinmemberAMFXG27-Jan-05 9:25 
GeneralRe: YACLAPTester.exe PinmemberSean Michael Murphy27-Jan-05 10:26 

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 | Terms of Use | Mobile
Web01 | 2.8.1411028.1 | Last Updated 2 Jan 2005
Article Copyright 2005 by Sean Michael Murphy
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid