Click here to Skip to main content
15,881,725 members
Articles / Desktop Programming / MFC
Article

Flexible Command Line Arguments Class

Rate me:
Please Sign up or sign in to vote.
4.57/5 (19 votes)
24 Mar 20038 min read 108.2K   1.3K   51   18
Command-line parameters parser.

Introduction

CCommandLineParameters is a C/C++ class to help you process command line arguments.  

Yes, this is yet another "Command Line" processor.  But in my opinion, the others I've seen don't have the flexibility or common usage standards often used command line tools switch options.  CCommandLineParameters is designed to provide the following common/standard requirements:

  • Implicit or explicit help option. 
  • Usage of both slash ("/") or dash ("-") switch characters
  • Support to add more switch characters
  • Switch case sensitivity support
  • Switch abbreviation support
  • Switch default value support
  • First Non Switch Parameter support
  • Support for Quoted parameters

Nomenclature

The following legend is used to describe the CCommandLineParameters class:

Command LineThe string passed to a program including the name of the current program.
Parameter LineThe string passed to a program excluding the name of the current program.
Arguments The words in the parameter line each separated by space. Argument 1 is the first word, argument 2 is the same word, etc.  Argument 0 is the name of the program.  Please note that a double quote (") is used to combine multiple words are one argument.

example: President "George Bush"

The above is 2 arguments separate arguments, president and George Bush.

ParametersSame as arguments
SwitchAn argument or parameter which begins with a switch character. By default, the switch characters are dash ("-" or forward slash ("/")
Abbreviated SwitchA switch that offers an abbreviation shortcut.

Example: /s*end

Allows for /send or /s to be used.
Non-SwitchAn argument or parameter which DOES NOT begin with a switch character.
switch valueThe value assigned to a switch.
argument or parameter indexThe index of the argument on the command line. 

The following is standard command line syntax information which will be helpful to you when you wish to document or describe the possible command line parameters for your application in a help display:

[]When a parameter is surrounded with square brackets, this typically means the parameter is optional.  The parameter is not required for normal operations of your program.

example: program.exe [-p1]
<>When a parameter is surrounded with angle brackets, this typically means the parameter is required for normal operations of your program.

example: program.exe <filename>
|The vertical bar means a choice between one parameter or parameter value is acceptable.

example: program.exe </device:com1|com2>

For example, suppose an application describes the following command line syntax:

program.exe <p1> [-p2 <v2>] [[/p3 [v3]] [/p4]] [/p5 <v5|w5>]

By following the standard syntax, you can easily understand what the required and optional parameters for any application.

In this example, p1 is a required parameter.  The program will not run if it is not passed.  The switches /p2, /p3, /p4 and /p5 are optional.  If p2 is used, then v2 is required.  If p3 is used, then V3 and /p4 are optional.  However, the parameters v3 and /p4  are only valid if /p3 is used in the first place.  If /P5 is used, the valid values are v5 or w5. 

This basic syntax is standard across many platforms.

Using the code

Using CCommandLineParameters is very simple. Simply instantiate or add an object like so to your source code:

CCommandLineParameters clp;

The constructor offer an option to pass the switch characters which are by default, "-/".  If you wish to change the switch characters, you can do so by passing a string defining the characters to the constructor:

CCommandLineParameters clp("-/\\");  <FONT color=#0000ff>/* dash, forward and back slash*/</FONT>

The basic and most common usage at this point is the Switch() function. It will cover 80% of your needs.  All other member functions are based on the Switch() function to give you other capabilities.

Here is a fast "get started" example:

Suppose our program "sendfile.exe" has a command line syntax:

sendfile.exe <filename> <-h*sot <hostname>> [-p*ort <port#>]

then the following code will satisfy the syntax:

void usage()
{  
  print("SendFile v1.0 Copyright (c) 2003 MyCompany.com\n");
  print("usage: <filename> <-h*sot <hostname>> [-p*ort <port#>]\n");
}

void main()
{

  CCommandLineParameters clp;

<FONT color=#0000ff>  // check for ? or if no parameters are passed
</FONT>
  if (clp.Help(TRUE)) {
      usage();
      return;
  }

  CString filename = clp.FirstNonSwitchStr();
  CString hostname = clp.GetSwitchStr("h*ost");
  DWORD deport = clp.GetSwitchInt("p*ort",80);

<FONT color=#0000ff>  // Syntax checking for filename.
  // First parameter must be a non-switch
</FONT>
  if (clp.FirstNonSwitchIndex() != 1) {
      print("! syntax error: filename required\n");
      usage();
      return;
  }

<FONT color=#0000ff>  // Syntax checking for host name. 
</FONT>
  if (hostname.IsEmpty()) {
      print("! syntax error: no host defined\n");
      usage();
      return;
  }

Reference Guide

The following are the members of the CCommandLineParameters class.


BOOL CheckHelp(const BOLO bNoSwitches = 
FALSE);

Return TRUE if parameter #1 is "?", "/?" or   "-?".   If you want to return TRUE when no parameters are passed, then call CheckHelp(TRUE);

Example:

CCommandLineParameters clp; 
if (clp.CheckHelp(TRUE)) {
   ShowHelp();
   exit(1);
}

CString CommandLine();

Return the entire command line as a string, including the current program name.


CString ParamLine();

Return the entire command line as a string, excluding the current program name.


int ParamCount();

Return the total number of parameters or arguments on the command line, including switches. This will always be a minimum of 1, which includes the parameter #0 the name of the current application.


int SwitchCount();

Return the total number of switch options on the command line.


CString ParamStr(int index, const BOOL bGetAll = 
FALSE);

Return the string at parameter #index.  If bGetall is TRUE, then return the string starting at parameter #index.

Example:

program.exe -email user@domain.com -subject NewsLetter #22 March 2 1999

CCommandLineParameters clp; 
CString email = clp.GetSwitchStr("-email");
CString Subject = "";
int i = clp.Switch("subject");
if (i > 0) Subject = clp.ParamStr(i+1,TRUE);

int ParamInt(int index);

Return the integer at parameter #index.


int FirstNonSwitchIndex();

Return the first parameter index where there the first non-switch parameter occurs.


CString FirstNonSwitchStr();

Return the string where there the first non-switch parameter occurs.  See also GetNonSwitchStr().


int Switch(const char *sz, const BOOL bCase = 
FALSE);

Switch() will return the parameter index if the switch exist. Return 0 if not found.

The logic will allow for two types of switches:

    /switch value
    /switch:value

DO NOT PASS THE COLON. IT IS AUTOMATICALLY CHECKED. In other words, the following statements are the same:

    Switch("server");
    Switch("-server");
    Switch("/server");

to handle the possible switch arguments and retrieval of switch values:

    /server:value
    /server value
    -server:value
    -server value

If you wish to have an abbreviation, insert a star "*" character in the switch at the position to indicate the number of abbreviated characters.  If you wish to make it case sensitive, then pass bCase as TRUE.

Example: 

<FONT color=#0000ff>// check for /st or /start switch (not case sensitive) </FONT>
BOOL bStart =  clp.Switch("st*art");  <FONT color=#0000ff>
</FONT>

CString GetSwitchStr(const char *sz, 
<BR>                     
const char *szDefault = "", 
<BR>                     
const BOOL bCase = FALSE);

int GetSwitchInt(const char *sz, 
<BR>                 
const int iDefault = -1, 
<BR>                 
const BOOL bCase = FALSE);

Return the string or integer for a given switch.  Optionally pass the default value and if case sensitivity is to be used.

These functions support two types of switch inputs:

    /switch:data
    /switch data

Either format is acceptable.

CString GetNonSwitchStr(const BOOL bBreakAtSwitch = TRUE, 
<BR>                        
const BOOL bFirstOnly = FALSE);

Return the non switch string(s) depending on the values of bBreakAtSwitch and bFirstOnly.

bBreakAtSwitchbFirstOnlyResult
TRUEFALSEDefault Behavior, returns all strings non-switch strings starting at the first one found, stopping at the first switch found.
TRUETRUEreturns the first non-switch string starting at the first one found.
FALSETRUEreturns the first non-switch string.
FALSEFALSEreturns all the non-switch strings.

Examples:

program.exe  file.txt -p:80 -H www.winserver.com
program.exe  file.txt -p:80 -h 208.247.131.9

int port     = clp.GetSwitchInt("port",25,1);
CString host = clp.GetSwitchStr("HOST,"",1,TRUE);
CString ip   = clp.GetSwitchStr("host,"",1,TRUE);
CString file = clp.GetNonSwitchString(TRUE,TRUE);

In the above example, the switch for H is case sensitive. In one case (upper), it sets the host variable and in the lower case option it sets the ip variable.

program.exe file1.txt file2.txt file2.txt -output out.txt

CString infiles = clp.GetNonSwitchString(TRUE,FALSE);
CString outfile = clp.GetSwitchStr("-output",1)

Points of Interest

This class works under console and GUI applications.  A maximum of 100 parameters are possible.  A possible enhancement is a syntax validation parser. This would help reduce coding of valid parameter syntax.

History

v1.0p  March 5, 2003 - Initial Public Release

About the Author

Hector Santos is the CTO of Santronics Software, Inc,  developer of WINSERVER (Wildcat! Interactive Net Server), an integrated Dialup and Intranet Hosting Client/Server System.   Hector made his mark in the early Off-line Mail Reader/Door days in the Fidonet Mail/File Network with the 1984 debut of the Silver Xpress OffLine Mail Door/Reader System.  Before the internet, we connected with low speed modems and to read or create mail ONLINE was expensive. Silver Xpress and other similar products made it feasible for millions of people world wide to enjoy "BBSing" by downloading mail for offline reading and replying.    In 1992 with the internet coming and online communications becoming more feasible, products like SX were beginning to die.  Hector's next product was Platinum Xpress, a P2P like system (we just didn't call it P2P) for the automatic exchange of Mail and Files in a world wide network of Zones, Nets, Nodes and Points users. This was called FidoNet and believe it not, there is nothing in the market today to compares to the P2P technology found in FidoNet.  In 1996, with the success of PX,  Hector purchased the rights to a brand new product line called WINSERVER, a product way ahead of its time.   WINSERVER is now Santronics's flag ship product line, and it is a leading provider for private intranet solutions, especially in the the Medical, Health and Claims/Collection Industry where mail and files needs to be exchanges in a Intranet manner using all kinds of connection devices, including direct connect modems which still to this day, is probably still the most secured way of transferring data without internet sniffing worries.

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCode Snippets: License Pin
Member 1202031211-Mar-19 23:59
Member 1202031211-Mar-19 23:59 
QuestionFlexible Command Line Arguments Class - License Pin
Member 1086227328-Jul-14 11:57
Member 1086227328-Jul-14 11:57 
GeneralMy vote of 5 Pin
MadhureshK23-Aug-11 23:38
MadhureshK23-Aug-11 23:38 
GeneralCCommandLineParameters license Pin
Transgenic31-Mar-10 5:10
Transgenic31-Mar-10 5:10 
GeneralDoesn't compile under Visual Studio 2003 - with workaround Pin
smt527-Mar-07 16:11
smt527-Mar-07 16:11 
GeneralGetSwitchStr() inconsistent return string values Pin
sbirdasn20-Mar-04 0:57
sbirdasn20-Mar-04 0:57 
Hi there Hector,

This is probably a religous thing, but I found that if the "value" is missing from a switch parameter, then, depending on whether a colon was present or not, the return value may differ.

The original version always returns an empty string if the colon is found but there is no following "value". But if the colon is omitted, then the implication is that a non switch prefixed parameter is supposed to follow, and if that "value" is not present, then the routine always returns the caller specifed default string value (szDefault).

So, my modest change is the middle line below (pardon my lack of indentation):

if (n > -1) {
if ((n+1) < s.GetLength()) // no stuff after colon, use szDefault.
return s.Mid(n+1);
...

Now you get the same result in both cases. I admit that I would be more likely to change my view if there were additional flags that controlled whether colon/non-colon values are allowed.

Thanks to everyone for sharing with this neat little class & patches. It's quite handy for quick little console apps.

Tony.
GeneralProblems compiling source code Pin
Alejandro Masino2-Jul-03 8:18
Alejandro Masino2-Jul-03 8:18 
GeneralRe: Problems compiling source code Pin
hector santos2-Jul-03 11:59
hector santos2-Jul-03 11:59 
GeneralRe: Problems compiling source code Pin
4sure24-Jul-03 4:11
4sure24-Jul-03 4:11 
GeneralAbbreviated switches not working Pin
4sure26-Jun-03 22:46
4sure26-Jun-03 22:46 
GeneralRe: Abbreviated switches not working Pin
Graham Bloice27-Jun-03 2:07
Graham Bloice27-Jun-03 2:07 
GeneralRe: Abbreviated switches not working Pin
4sure27-Jun-03 2:18
4sure27-Jun-03 2:18 
GeneralRe: Abbreviated switches not working Pin
Graham Bloice27-Jun-03 4:59
Graham Bloice27-Jun-03 4:59 
GeneralRe: Abbreviated switches not working Pin
hector santos1-Jul-03 7:04
hector santos1-Jul-03 7:04 
GeneralRe: Abbreviated switches not working Pin
hector santos1-Jul-03 7:00
hector santos1-Jul-03 7:00 
GeneralRe: Abbreviated switches not working Pin
4sure23-Jul-03 0:18
4sure23-Jul-03 0:18 
GeneralRe: Abbreviated switches not working Pin
4sure25-Jul-03 5:43
4sure25-Jul-03 5:43 
GeneralRe: Abbreviated switches not working Pin
sbirdasn19-Mar-04 23:49
sbirdasn19-Mar-04 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.