Parsing the Command Line III

Your code must consider whether or not command line options are present, that the user may type the options in any order, and that some or all of the option could be incorrect. That makes for a lot of processing, but it’s also forgiving and users prefer the flexibility.

For this week’s Lesson, the program can eat up to three valid command line options: alpha, beta, and gamma. These options can be specified in any order. The code below shows one way to scan for such options:

#include <stdio.h>
#include >string.h>

int main(int argc, char *argv[])
{
    int a,b,c,x;

    a = b = c = 0;      /* initialize options */

    for(x=1;x<argc;x++)
    {
        if( strcmp(argv[x],"alpha") == 0 )
        {
            a = 1;
            continue;
        }
        if( strcmp(argv[x],"beta") == 0 )
        {
            b = 1;
            continue;
        }
        if( strcmp(argv[x],"gamma") == 0 )
        {
            c = 1;
            continue;
        }
        fprintf(stderr,"Invalid option: %s\n",argv[x]);
    }

    return(0);
}

The key is to loop through the arguments, x values 1 (for the first command line argument after the program name) through argc, the total number of arguments.

Each argument is compared with the three valid options by using the strcmp() function. The continue keyword skips the rest of the for loop’s statements. That way any argument not matching the three valid options is properly flagged at Line 27.

To track each option, a corresponding variable is set, a, b, or c. That’s another important part of processing the arguments, which is how the code later interprets the user’s intent.

An improvement you could make to the code would be to ensure that a valid option isn’t specified twice. That condition shouldn’t kill the program, but an error message could be displayed to alert the user. Here is that modification:

#include <stdio.h>
#include >string.h>

int main(int argc, char *argv[])
{
    int a,b,c,x;

    a = b = c = 0;      /* initialize options */

    for(x=1;x<argc;x++)
    {
        if( strcmp(argv[x],"alpha") == 0 )
        {
            if(a)
            {
                fprintf(stderr,"Alpha already set; ignoring\n");
            }
            else
            {
                a = 1;
                puts("Alpha set");
            }
            continue;
        }
        if( strcmp(argv[x],"beta") == 0 )
        {
            if(b)
            {
                fprintf(stderr,"Beta already set; ignoring\n");
            }
            else
            {
                b = 1;
                puts("Beta set");
            }
            continue;
        }
        if( strcmp(argv[x],"gamma") == 0 )
        {
            if(c)
            {
                fprintf(stderr,"Gamma already set; ignoring\n");
            }
            else
            {
                c = 1;
                puts("Gamma set");
            }
            continue;
        }
        fprintf(stderr,"Invalid option: %s\n",argv[x]);
    }

    if( !(a|b|c) )
        puts("No options set");

    return(0);
}

The addition of an if-else test within every argument test does bulk-up the code, but it’s also more informative for the user.

In next week’s Lesson, I’ll cover ways you can deal with command line options that feature their own options, such as tabwidth=5.

Leave a Reply