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.