Wednesday, August 15, 2007

Parsing Command Line Parameters in VC++

One of the most confounding things in the C/C++ programming world is the unnaturalness of C-style "strings." I put quotation marks around "strings," because when you're C-stylin', your dealing actually with arrays of chars, not string-like objects. Chances are if you're coding in C++ what you really want are STL strings, not arrays of chars. This confusing situation is a much bigger problem for novices than old hands, but in either case it's still a bit awkward. Unless you're also using .NET (CLI), arrays of chars are unavoidable when parsing command line parameters--a feature that most sophisticated applications require.

If you're using VC++ (versions VC++2003, VC++2005, or VC++2008) as your IDE, your "main" function, which is actually "t_main" in VC++, confronts you not with char* but _TCHAR*, making things even more cryptic. (The "t" and "T" characters refer to the configurability of VC++2008 to handle unicode or not, depending whether the _UNICODE is defined at compilation. But you knew that.) I'm really puzzled about not yet seeing a book author take on this common chore. You could have a pretty annoying Google-session trying get sample code to parse command line parameters with this version of the main function.

Most Google group queries I found on this topic tend to focus on conversion functions. Though I almost always love a clever, succinct function to do my dirty work, in this case I may pass, because it only takes a few lines of memorable code to slip the chars into a handy vector of strings. In this case, we use wstring (for "wide string") instead of string. The do-while below adds a de-referenced pointer to wchar_t (the "wide" version of char)

wstring a_wstring;
do a_wstring += *argv[i];
while(*argv[i]++);

The key thing to realize is that wstring knows what do with char's.

Here's a short program that stores the parameters in a vector and also displays them to the

#include "stdafx.h"
#include
#include
#include
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
vector args;
for(int i =0;i<argc;i++)
{
wstring a_wstring;
do a_wstring += *argv[i];
while(*argv[i]++);
args.push_back(a_wstring);
cout << i<<"\n";
wcout << args[i] << "\n";
}
return 0;
}

You should be able to do just about whatever you want with the parameters after putting them into a vector of wstrings.

1 comment:

Anonymous said...

Helpful post, but you should know that Blogger ate everything in angle brackets. For anyone else confused, you can look at the page source and do some manual de-mangling.