15.6 Command-Line Arguments

I l @ ve RuBoard

The procedure main actually takes two arguments. They are called argc and argv . (They don't have to be called argc and argv ; however, 99.99% of C++ programs use these names .)

 int main(int argc, char *argv[])  { 

It's easy to remember which comes first when you realize that they are in alphabetical order.

The parameter argc is the number of arguments on the command line (including the program name ). The array argv contains the actual arguments. For example, if the program args were run with the command line:

 args this is a test 

then:

 argc       = 5  argv[0]       = "args"  argv[1]       = "this"  argv[2]       = "is"  argv[3]       = "a"  argv[4]       = "test" 

The Unix shell expands wildcard characters like *, ?, and [] before sending the command line to the program. See your sh or csh manual for details.

Borland-C++ will expand wildcard characters if the file WILDARG.OBJ is linked with your program. See the Borland-C++ manual for details.

Almost all Unix commands use a standard command-line format. This "standard" has carried over into other environments. A standard UNIX command has the form:

 command options file1 file1 file3 ... 

Options are preceded by a hyphen (-) and are usually a single letter. For example, the option -v might turn on verbose mode. If the option takes a parameter, the parameter follows the letter. For example, the switch -- m1024 sets the maximum number of symbols to 1024, and -- ooutfile sets the output file name to outfile .

You have been given the assignment to write a program that will format and print files. Part of the documentation for the program looks like:

 print_file [-v] [-l<length>] [-o<name>] [file1] [file2] ... 

In this line, -v sets verbose options, which turns on a lot of progress information messages. The option -l<length> sets page size to <length> lines (default = 66), and -o<name> sets the output file to <name> (default = print.out ). A list of files to print follows these options ( [file1], [file2] , etc.). If no files are specified, print the file print.in .

The while loop cycles through the options. The actual loop is:

 while ((argc > 1) && (argv[1][0] == '-')) { 

There is always one argument, the program name. The expression (argc > 1) checks for additional arguments. The first one will be numbered 1. The first character of the first argument is argv[1][0] . If this character is a dash, you have an option.

At the end of the loop is the code:

 --argc;          ++argv;      } 

This consumes an argument. The number of arguments is decremented to indicate one fewer option, and the pointer to the first option is incremented, shifting the list to the left one place. (Note that after the first increment, argv[0] no longer points to the program name.)

The switch statement is used to decode the options. Character 0 of the argument is the hyphen (-). Character 1 is the option character, so you use the following expression to decode the option:

 switch (argv[1][1]) { 

The option -v has no arguments; it just causes a flag to be set.

The -l option takes an integer argument. The library function atoi is used to convert the string into an integer. From the previous example, you know that argv[1][2] starts the string containing the number. This string is passed to atoi .

The option -o takes a filename. Rather than copy the whole string, you set the character pointer out_file to point to the name part of the string. By this time you know that:

argv[1][0] = '-'
argv[1][1] = 'o'
argv[1][2] = first character of the file name

You set out_file to point to the string with the statement:

 out_file = &argv[1][2]; 

Finally all the options are parsed, and you fall through to the processing loop. This merely executes the function do_file for each file argument.

Example 15-8 contains the complete option-decoding program.

Example 15-8. print/print.cpp
 /********************************************************  * print -- format files for printing                   *  ********************************************************/ #include <iostream> #include <cstdlib>       int verbose = 0;                // verbose mode (default = false)  char *out_file = "print.out";   // output file name  char *program_name;             // name of the program (for errors)  int line_max = 66;              // number of lines per page  /********************************************************  * do_file -- dummy routine to handle a file            *  *                                                      *  * Parameter                                            *  *      name -- name of the file to print               *  ********************************************************/ void do_file(const char *const name) {     std::cout << "Verbose " << verbose << " Lines " << line_max <<              " Input " << name << " Output " << out_file << '\n'; } /********************************************************  * usage -- tell the user how to use this program and   *  *              exit                                    *  ********************************************************/ void usage(  ) {     std::cerr << "Usage is " << program_name <<          " [options] [file-list]\n";     std::cerr << "Options\n";     std::cerr << "  -v          verbose\n";     std::cerr << "  -l<number>  Number of lines\n";     std::cerr << "  -o<name>    Set output file name\n";     exit (8); } int main(int argc, char *argv[]) {     // save the program name for future use      program_name = argv[0];     /*       * loop for each option.        *   Stop if we run out of arguments      *   or we get an argument without a dash.      */     while ((argc > 1) && (argv[1][0] == '-')) {         /*          * argv[1][1] is the actual option character.          */         switch (argv[1][1]) {             /*              * -v verbose               */             case 'v':                 verbose = 1;                  break;             /*              * -o<name>  output file              *    [0] is the dash              *    [1] is the "o"              *    [2] starts the name              */             case 'o':                 out_file = &argv[1][2];                 break;             /*              * -l<number> set max number of lines              */             case 'l':                 line_max = atoi(&argv[1][2]);                 break;             default:                 std::cerr << "Bad option " << argv[1] <<'\n';                 usage(  );         }         /*          * move the argument list up one          * move the count down one          */         ++argv;         --argc;     }     /*      * At this point all the options have been processed.      * Check to see if we have no files in the list      * and if so, we need to list just standard in.      */     if (argc == 1) {         do_file("print.in");     } else {         while (argc > 1) {           do_file(argv[1]);           ++argv;           --argc;         }     }     return (0); } 

This is one way of parsing the argument list. The use of the while loop and switch statement is simple and easy to understand. This method does have a limitation. The argument must immediately follow the options. For example, - odata.out will work, but -o data.out will not. An improved parser would make the program more friendly, but this works for simple programs. (See your system documentation for information on the getopt function.)

I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net