How the arguments are presented in the argv[]
array will depend on the command shell being used. Most command shells follow the generally accepted standard that command line arguments are separated by spaces and if you want to specify an argument with spaces it must be quoted.
So ./foo -l user1 user2 user3 -name foo
is a command line that would be provided to the C run time as seven arguments, the first is the name of the program with the remaining six arguments being -l
, user1
, user2
, user3
, -name
, and foo
.
If at the command line you entered ./foo -l "user1 user2 user3" -name foo
where the list of users (user1, user2, and user3) are in a quoted string, the command line would be provided to the C run time as five arguments, the first is the name of the program with the remaining four arguments being -l
, user1 user2 user3
(the quotes are normally removed by the command shell and all are in the same argument), -name
, and foo
.
Back in the old days of UNIX C command line utilities we would do something like the following for simple command line parsing. The following source does the work that a command line class might do. This was done with C++ but in a C style.
Naturally since this was thrown together, it is not very robust as for instance more than 30 arguments for a particular command line option would cause problems.
// arglist.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
/*
* argument options accepted are as follows:
* -l -> indicates a user list of one or more user names follows
* -name -> indicates a name for the list follows
*
* arguments without a leading dash are considered to be option changes
* and arguments without a leading dash are considered to be arguments
* for the last option.
**/
typedef struct {
int index;
int argListIndex[30];
} argList;
const int indexOptionUnknown = 0;
const int indexOptionL = 1;
const int indexOptionName = 2;
int main(int argc, char * argv[])
{
// the index into the argv[] array. zeroth element of argve[] is ignored.
argList myList[3] = {0};
int iMyList = 0;
// we skip the first argument which is the name of our program
// we then process the remaining command line arguments which the C runtime
// has provided as a series of char strings.
for (int i = 1; i < argc; i++) {
if (*argv[i] == '-') {
// this is an argument option. figure out which one.
if (strcmp (argv[i], "-l") == 0) {
iMyList = indexOptionL;
} else if (strcmp (argv[i], "-name") == 0) {
iMyList = indexOptionName;
} else {
// unknown option so we will ignore it.
iMyList = indexOptionUnknown;
}
} else {
// this is an argument for the last option found
if (iMyList > indexOptionUnknown) {
myList[iMyList].argListIndex[ myList[iMyList].index ] = i;
myList[iMyList].index++;
}
}
}
std::cout << "option -l, count of arguments " << myList[indexOptionL].index << std::endl;
for (int i = 0; i < myList[indexOptionL].index; i++) {
std::cout << " " << i << " is " << argv[myList[indexOptionL].argListIndex[i]] << std::endl;
}
std::cout << "option -name, count of arguments " << myList[indexOptionName].index << std::endl;
for (int i = 0; i < myList[indexOptionName].index; i++) {
std::cout << " " << i << " is " << argv[myList[indexOptionName].argListIndex[i]] << std::endl;
}
return 0;
}
The output for an argument lines such as pgm -l user1 user2 user3 -name foo
is:
option -l, count of arguments 3
0 is user1
1 is user2
2 is user3
option -name, count of arguments 1
0 is foo
And a command line such as pgm -l user1 -l user2 -l user3 -name foo
would be the same output. What this parser does is to build a list of the arguments on the command line for a particular option.
If the command line such as pgm -l "user1 user2 user3" -name foo
is provided the output is changed due to the quoted argument and the result is:
option -l, count of arguments 1
0 is user1 user2 user3
option -name, count of arguments 1
0 is foo