Command line option
Handling command line options from
int main(int argc, char *argv[])
program_name [-d] [-h] [-v] [-o output_file] [-l limit_value]
file_name [ file_name [file_name [ ... ]]]
// valid
prog chap1.doc
prog -l 1024 -o chap1-2.out chap1.doc chap2.doc
prog -d chap3.doc
prog -l 512 -d chap4.doc
- Extract each option in turn from
argv
for (int ix=1; ix<argc; ix++) { // begin at 1
char *pchar = argv[ix];
// ...
}
- Determine the type of option. If it begins with a
hyphen, then it may be one of {h, d, v, l, o}. Otherwise,
it may either the actual limit value associated with
-l
, an output file name associated with
-o
or the name of a file for the program to
process.
switch (pchar[0]) {
case '-': {
switch (pchar[1])
{
case 'd':
// handle debug
break;
case 'v':
// handle version request
break;
case 'h':
// handle help
break;
case 'o':
// prepare to handle output_file
break;
case 'l':
// prepare to handle limit_value
break;
default:
// unrecognized option:
// report it and exit
}
}
default: {
if (ofile_on) {
// handle output_file
// turn off ofile_on
}
else if (limit_on) {
// handle limit_value
// turn off limit_on
}
else {
// handle file_name
}
}
}
- Fill in the handling
bool debug_on = false;
bool ofile_on = false; // if true, next argument is output file
bool limit_on = false; // if true, next argument is limit value
string ofile;
vector<string, allocator> file_names;
switch (pchar[0]) {
case '-': {
switch (pchar[1])
{
case 'd':
debug_on = true;
break;
case 'v':
// displays version number and then exits
cout << program_name << "::" << program_version << endl;
return 0;
case 'h':
usage(); // no break necessary: usage() exits
case 'o':
ofile_on = true;
break;
case 'l':
limit_on = true;
break;
default:
cerr << program_name << " : error : "
<< "unrecognized option: - " << pchar << "\n\n";
usage(-1);
}
}
default: {
if (ofile_on) {
ofile = pchar;
ofile_on = false;
}
else if (limit_on) {
limit = atoi(pchar);
if (limit < 0) {
cerr << program_name << "::"
<< program_version << " : error: "
<< "negative value for limit.\n";
usage(-2);
}
limit_on = false;
}
else
file_names.push_back(string(pchar));
break;
}
}
- Full implementation
const char *const program_name = "comline";
const char *const program_version = "version 0.01 (08/07/97)";
inline void usage(int exit_value = 0)
{
// prints out a formatted usage message and exits using exit_value
cerr << "usage:\n"
<< program_name << " "
<< "[-d] [-h] [-v] \n\t"
<< "[-o output_file] [-l limit] \n\t"
<< "file_name\n\t[file_name [file_name [ ... ]]]\n\n"
<< "where [] indicates optional option:\n\n\t"
<< "-h: help.\n\t\t"
<< "generates this message and exits\n\n\t"
<< "-v: version.\n\t\t"
<< "prints version information and exits\n\n\t"
<< "-d: debug.\n\t\tturns debugging on\n\n\t"
<< "-l limit\n\t\t"
<< "limit must be a non-negative integer\n\n\t"
<< "-o ofile\n\t\t"
<< "file within which to write out results\n\t\t"
<< "by default, results written to standard output\n\n"
<< "file_name\n\t\t"
<< "the name of the actual file to process\n\t\t"
<< "at least one file_name is required --\n\t\t"
<< "any number may be specified\n\n"
<< "examples:\n\t\t"
<< "$command chapter7.doc\n\t\t"
<< "$command -d -l 1024 -o test_7_8 "
<< "chapter7.doc chapter8.doc\n\n";
exit(exit_value);
}
// pass values by global variables
int parse_options(int arg_count, char **arg_vector);
int main(int argc, char *argv[])
{
int option_status;
option_status = parse_options(argc, argv);
if (file_names.empty()) {
cerr << program_name << " : error : "
<< "no file specified for processing.\n\n";
usage(-3);
}
if (limit != -1)
cout << "User-specifed limit: " << limit << endl;
if (! ofile.empty())
cout << "User-specified output file: " << ofile << endl;
cout << (file_names.size() == 1 ? "File " : "Files ")
<< "to be processed are the following:\n";
for (int inx=0; inx<file_names.size(); inx++)
cout << "\t" << file_names[inx] << endl;
}
// ...
}
Encapsulate the processing within a class
class CommandOpt {
public:
CommandOpt() : _limit(-1), _debug_on(false) {}
int parse_options(int argc, char *argv[]);
string out_file() { return _out_file; }
bool debug_on() { return _debug_on; }
int files() { return _file_names.size(); }
// to access _file_names
string& operator[](int ix);
private:
inline int usage(int exit_value = 0);
bool _debug_on;
int _limit;
string _out_file;
vector<string, allocator> _file_names;
static const char *const program_name;
static const char *const program_version;
};
int main(int argc, char *argv[])
{
CommandOpt com_opt;
int option_status;
option_status = com_opt.parse_options(argc,argv);
// ...
}
Index