I see there are several articles on this subject. At the time I needed an object oriented command line parser (about 2 years ago), there were less of them. I remember I liked C#/.NET Command Line Arguments Parser. I used it and improved it a bit. (Hmm, maybe I should post this too.) But I needed something for C++. I do not say it didn't exist, just that I got tired of searching, on CodeProject and elsewhere, and started programming, and I haven't got tired of programming soon enough to switch back to searching.
My notion of it was that is should be something like
WScript.arguments object, something I was used to, since I used it a lot in my WSH (i.e. JScript and VBcript) scripts, and kind of liked it.
It is really very much like
WScript.arguments plus it keeps track of how the named arguments (options) are used.
I hope this makes it different enough from other parsers for C++ to be interesting and that it will find its users.
WScript.arguments the option names and its values have to be separated with '
:' (but unlike WSH, it does not have to be
: but any character of your choice):
etc., but not with spaces or tabs. This is not supported:
argument1 argument2 /option1 its_value /option2 its_value
Just like in WSH, the options may be what we could call simple, i.e. without value:
The options (named arguments) can be given in any order and can be mixed with (unnamed) arguments. Long options (i.e. the ones beginning with 2 or more characters, like with --) are not supported.
WScript.arguments, this parser in the time of its instantiation does not demand any information about desired command line arguments. That's why I added keeping track of named arguments usage. Any time you can retrieve the number or named arguments not yet accessed, and the list of them.
It is actually quite a natural approach. Why would we have to tell the parser what options we expect when it can conclude that itself by watching us using that option in our code???
It serves as some kind of additional debugging information too. We are no more warned only when the code is trying to use some options that are not given on the command line, but the other way round too.
I hope people will find this approach handy and interesting.
It's other most important characteristics:
- It's a template class that can be used with
- When used with
wchar_t, it works flawlessly with Unicode characters, I test it all the time. (Printing them properly to the Windows console is another matter. One way to do it is to print directly to console using functions from conio.h like
_tcprintf. For the other way, see my article on this matter Unicode output to the Windows console.)
- If you compile it on Linux, you should of course use
char. (Thanks to the consistent usage of UTF-8, Linux has no problems with Unicode characters so, if you want to print them out to the console, simply using
cout will do the job.)
- It is so similar to
WScript.arguments that, if you have any experience with
WScript.arguments, you can start using it right away. There are some additional features (keeping track of named arguments usage), but you can study them if and when you will need them.
- It can be used on Windows non-console applications, i.e. those that have
WinMain) function instead of
main) function. Can be instantiated anywhere in the program, not only in
- You can choose whether the options should begin with '
/' or '
-', or any other character.
- You can choose whether the options names should be separated from their values with '
:' or '
=', or any other character.
Note: I explained everything as you would use
TCHAR are the same thing. I sometimes write
TCHAR and sometimes
_TCHAR. I apologize for confusing you by this.) Therefore strings are written as
_T("foo"). But you can of course use
wchar_t directly. In that case, string literals would be written as
You will probably first try to use the parser inside of the example project. To use it in your project, you will of course have to put my header files into your project folder or somewhere in the include path of your compiler.
There are 3 classes:
CStlCmdLineArgs is the very parser. It needs
argv to be passed as arguments in the constructor.
CArgList creates that argument using the Windows function
CStlCmdLineArgsWin connects them by inheritance and containment respectively, so that you can instantiate the parser in the most easy way. Having included CStlCmdLineArgsWin_4.h:
Since you are not dependent on
argc, you can instantiate it this way easily anywhere in the code. It is the most recommended way for Windows applications.
CArgList makes no sense so you must instantiate
CStlCmdLineArgs directly using
argv. This approach can also be used in Windows command line applications. On Linux, the template argument should be
char instead of
TCHAR. Having included CStlCmdLineArgs4.h:
CStlCmdLineArgs<TCHAR> cma(argc, argv);
The Very Basic Usage
You use them just like
WScript.arguments. The only differences are that in
WScript.arguments, you would use round brackets and here you use square brackets:
You can access plain arguments (i.e., unnamed arguments) with:
... and that, unlike
cma.unnamed starts with the 0th command line argument so that
cma.unnamed gives you what you would get retrieving
argv in the
If the index is out of bounds, i.e. if you try to access more arguments than present on the command line, it will simply return
You can access options (i.e., named arguments) with:
If the particular option is not present on the command line, it will return
If the option is given without a value, it will return empty string. This is how you check if a "simple" option, i.e. an option that does not require a value is present.
You Can Also
See how many unnamed arguments were on the command line with (something you will need in every program):
See how many named arguments were on the command line with (something you will probably never use :
Advanced Use - If You Want to Give the User More Precise Error Messages
This is something
WScript.arguments hasn't got. The class keeps track of named arguments you access. The information about arguments that were present on the command line and are not accessed can be retrieved with:
That will give you their number, and...
... that will give you all of them in a single string, quoted and separated by spaces.
There is More
Till now, we have treated command line options like in Windows Script: they all begin with '
/' and '
:' separates values from names. This is the default. But class constructors accept additional arguments, so that we can for example do this:
CStlCmdLineArgsWin<TCHAR> cma('-', '=');
Now the command line options are expected to begin with '
-' and '
=' will separate its names from its values.
Let's say you have chosen the default and you need to have an unnamed argument beginning with '
/arg1, you can escape it like this:
/:/arg1. If you have chosen '
-' and have an argument beginning with '
-', you would escape it like this:
- 21st March, 2009: Initial post