PARSING COMMAND LINE IN C++

 

There is a lot of command line parsing libraries, classes and other stuff. I also contributed to this movement creating my own class TCommandLineParser, doing command line processing work. This is not for self advertisement but I successfully used TCommandLineParser with different compilers: Borland C++, Visual C++, Compaq C++ (former DEC C++), aCC (C++ for HP-UX) and found this tool really convenient.

Let start with simple example:

#include <stdio.h>
#include "commandlineparser.h"

int main(int argc, char **argv)
{
  // create object
  TCommandLineParser commandline;

  // declare options that may appear in command line
  commandline.AddVoid("void");
  // mandatory string parameter
  commandline.AddChar("text", true);
  // optional integer parameter
  commandline.AddInt("integer", );

  // here declaration part ends

  // parse command line
  commandline.AddArguments(argc, argv);
  // is everything ok with command line
  if(!commandline.CheckCommandLine())
  {
    printf("Invalid command line!\n");
    return 1;
  }

  // access options and their values
  if(commandline.FindKey("void"))
  {
    printf("Option /void found in command line.\n");
  }
  // option /text is mandatory, so we are sure - it is here
  printf("Option /text=%s\n", commandline.GetChar("text"));
  // option /integer isn't mandatory. We must check does it present in command line
  if(commandline.FindKey("integer"))
  {
    printf("Option /integer=%d\n", commandline.GetInt("integer"));
  }

Command line syntax declaration methods Comment
bool AddVoid(const char *option, bool amust=false); Declares option that has no value. Parameter amust says is this option mandatory or no.
For example call AddVoid("help") declares non-mandatory option that may appear in command line as "/help"
bool AddBool(const char *option, bool amust=false); Declares boolean-valued option. TCommandLineParser understands different ways of boolean value declaration:
true/false, on/off, yes/no, 1/0.
Examples:
/debug=on
/=on
/debug=on
bool AddInt(const char *option, bool amust=false); Declares integer option. Example:
AddInt("limit_of_iterations", true);
/limit_of_iterations=100
bool AddPosInt(const char *option, bool amust=false); Integer option that accepts only positive integer values.
bool AddBoundedInt(const char *option, int lwr, int upr, bool amust=false); Declares bounded integer-valued option. For example
AddBoundedInt("loglevel", 0, 4) declares integer option /loglevel that accepts values: 0,1,2,3,4.
/loglevel=5 will fail.
bool AddChoiceInt(const char *option, int choice, bool amust=false); Declares integer-valued option that accepts values from list.
For example:
AddChoiceInt("speed", 1200, true);
AddChoiceInt("speed", 2400, true);
AddChoiceInt("speed", 4800, true);
AddChoiceInt("speed", 9600, true);
AddChoiceInt("speed", 19200, true);
These calls declare option integer-valued "speed" that may accept only values: 1200,2400,4800,9600 and 19200.
bool AddChar(const char *option, bool amust=false); Declares option that accepts text.
For example:
AddChar("name")
declares option "name" that accepts text. /name=Alex or /name=John
bool AddIntDup(const char *option, bool amust=false);
bool AddPosIntDup(const char *option, bool amust=false);
bool AddBoundedIntDup(const char *option, int lwr, int upr, bool amust=false);
bool AddChoiceIntDup(const char *option, int choice, bool amust=false);

This set of methods declare integer-valued option that may appear in command line several times.
bool AddCharDup(const char *option, bool amust=false); Declares integer-valued option that may appear in command line several times.
Option Value Access Methods Comment
bool FindKey(const char *key) const; This method lets you know does option present in command line. It's important to realize that if option is not mandatory before accessing option value you must make sure that it presents in command line. For example:
TCommandLineParser commandline;

commandline.AddInt("Number");
.....
// here
if(commandline.FindKey("Number"))
{
// now, safely access option value
printf("Number=%d\n", commandline.GetInt("Number"));
}
bool IsEmpty(const char *key) const; This method is doing the same stuff as FindKey.
size_t Count(const char *key) const; Returns the number of option named by key parameter instances in command line. Useful for multiple options. For example:
 TCommandLineParser commandline;

 commandline.AddDupInt("Number");
 .....
 // here
 if(int N = commandline.Count("Number"))
 {
  // now, access N times option "Number" values
  while(N--)
  {
   printf("Number=%d\n", commandline.GetInt("Number", N));
  }
 }
int GetInt(const char *key, size_t i=0) const; Provides access to integer option value(s). The second parameter is used in multiple option case. For example:

TCommandLineParser commandline;
commandline.AddIntDup("N1", true);
.........
commandline.AddArguments(argc, argv);
int N = commandline.Count("N1");
printf("Option \"N1\" was used %d times in command line.\n");
for(int j=0; j<N; j++)
  printf("/N1=%d\n", commandline.GetInt("N1", j));


Now, if application was started with command line:

test1.exe /N1=3 /N1=1 /N1=4 /N1=1

We will have ouput like that:

Option "N1" was used 3 times in command line.
/N1=3
/N1=1
/N1=4
/N1=1
bool GetBool(const char *key, size_t i=0) const;

Provides access to boolean option value(s).

const char *GetChar(const char *key, size_t i=0) const; Provides access to text option value(s).
bool CheckCommandLine() const; Checks command line syntax against its declaration.
const char *GetBadArgument() const; Gives the name of option where the first error occurred.
Methods Comment
bool AddArgument(const char *arg); feeds TCommandLineParser with one command line item For example:
 commandline.AddArgument("/debug=on");

or

 for(int j=1; j<argc; j++)
   commandline.AddArgument(argv[j]);
bool AddArgument(const char *key, const char *value); Gives TCommandLineParser already parsed command line item (key and value separately) For example:
 commandline.AddArgument("debug", "on");
bool AddArguments(int argc, char **argv); Gives TCommandLineParser all command line items at once.


Now, one more example from real life:

///////////////////////////////////////////////////////////////////////////////////////////////////////

int main(int argc, char **argv)
{
  TCommandLineParser commandline;
  commandline.AddChar("on");
  commandline.AddPosInt("id", true);
  commandline.AddChar("app", true);
  commandline.AddVoid("trace");
  commandline.AddVoid("authenticate");
  commandline.AddBoundedInt("port", 12300, 12600);
  commandline.AddChar("assoc");

  commandline.AddArguments(argc, argv);

  if(!commandline.CheckCommandLine())
  {
    printf("Invalid command line!\n");
    Usage();
    return 1;
  }

  if(strlen(commandline.GetChar("app")) > 11)
  {
    printf("Invalid application name %s (Too long)!\n", commandline.GetChar("app"));
    return 1;
  }

  // if port number isn't specified in command line - set default value
  if(!commandline.FindKey("port"))
    commandline.AddArgument("/port=12300");

And example of valid command line for above code:


dml_server /port=12310 /on=NODE_001 /id=1 /app=MASTER_APP /trace /authenticate

Download TCommandLineParser code and sample program.

Back