Discovering Command Line Options, Part III

Continuing from last week’s Lesson, to read multiple command line arguments, you must put the getopt() function in a loop. Specifically, you set the function as the looping condition. The loop’s guts evaluate the switches found.

Here’s how the looping condition can look:

while( (r=getopt(argc,argv,"ABC")) != -1 )

The getopt() function is nestled at the heart of the while loop’s condition. Its return value is saved in int variable r. This expression is enclosed in parentheses, which evaluates to the value of r. This value is compared with -1. As long as the getopt() function returns values other than -1, the loop continues. Here is the full code:

2021_07_10-Lesson-a.c

#include <stdio.h>
#include <unistd.h>

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

    /* suppress getopt()'s error message */
    opterr = 0;

    /* process multiple command line arguments */
    count = 0;
    while( (r=getopt(argc,argv,"ABC")) != -1 )
    {
        if( r=='?' )
            printf("Unknown option specified\n");
        else
            printf("Option '%c' found\n",r);
        count++;
    }
    printf("%d arguments processed\n",count);

    return(0);
}

The program digests command line arguments -A, -B, and -C in any combination. Invalid arguments are output as such. Here is a sample run with all the arguments specified:

$ ./a.out -A -B -C
Option 'A' found
Option 'B' found
Option 'C' found
3 arguments processed

Here is a sample run specifying legitimate argument -B and a bogus argument -Z:

$ ./a.out -B -Z
Option 'B' found
Unknown option specified
2 arguments processed

To further examine the unknown option, use the global optind variable. This variable is an index used by the getopt() function as it churns through the command line arguments. The optind “options index” value is one greater than the element number in the argv[] array.

The following code presents a modification that spits out invalid arguments by name:

2021_07_10-Lesson-b.c

#include <stdio.h>
#include <unistd.h>

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

    /* suppress getopt()'s error message */
    opterr = 0;

    /* process multiple command line arguments */
    count = 0;
    while( (r=getopt(argc,argv,"ABC")) != -1 )
    {
        if( r=='?' )
            printf("Unknown option '%s' specified\n",
                    argv[optind-1]
                  );
        else
            printf("Option '%c' found\n",r);
        count++;
    }
    printf("%d arguments processed\n",count);

    return(0);
}

Here’s a sample run:

$ ./a.out -A -O -B
Option 'A' found
Unknown option '-O' specified
Option 'B' found
3 arguments processed

Easier than using the optind value, global variable optopt holds the character value (decimal) of the invalid switch. To update the code, replace argv[optind-1] with optopt, and change the printf() format string placeholder from %s to %c, as is done in this code:

2021_07_10-Lesson-c.c

#include <stdio.h>
#include <unistd.h>

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

    /* suppress getopt()'s error message */
    opterr = 0;

    /* process multiple command line arguments */
    count = 0;
    while( (r=getopt(argc,argv,"ABC")) != -1 )
    {
        if( r=='?' )
            printf("Unknown option '%c' specified\n",
                    optopt
                  );
        else
            printf("Option '%c' found\n",r);
        count++;
    }
    printf("%d arguments processed\n",count);

    return(0);
}

The output from the above code’s program and the preceding program are identical.

Remember that both optind and optopt are external variables defined in the unistd.h header file.

In next week’s Lesson, I cover how the getopt() function read’s option values. For example: -a 177, where -a is the switch and 177 is specified as the switch’s value (or string).

Leave a Reply