Yet Another Command Line Argument Parser






4.52/5 (15 votes)
Jan 2, 2005
5 min read

64032

1050
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 theArrayList
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.