Jakob Nielsen
Jakob Nielsen

Reputation: 5198

Correct way to parse (option)arguments, questions about getopt(3) and argv

As an example I want to implement the following function: listtool [-s | -a NUM] < string >

My approach was the following:

int opt;
int opt_s = -1, opt_a = -1, num;
char *optstr ="<not yet set>";
num = -1;

if( argc < 3 || argc > 4 ) {
    fprintf(stderr, "Wrong number of arguments");
    usage();
}

/* Options */
while ((opt = getopt(argc, argv, "sa:")) != -1) {
    switch (opt) {
    case 's': {
        if (opt_s != -1) {
            fprintf(stderr, "opt_s multiple times\n");
            usage();         /* does not return */
        }
        else if (opt_a != -1) {
            fprintf(stderr, "Please only choose one option\n");
            usage();
        }
        else {
            ++opt_s;
            break;
        }
    }
    case 'a': {
        if (opt_a != -1) {
            fprintf(stderr, "opt_a multiple times\n");
            usage();        /* does not return */
        }
        else if (opt_s != -1) {
            fprintf(stderr, "Please only choose one option\n");
            usage();
        }
            ++opt_a;
            ++num; 
            break;
        }
    case '?': {
        usage();
        break;
    }
    // Impossible
    default: {
        assert(0);
    }
    }
}

/* Arguments */
if( num > -1 ) {
    if( (argc - optind) != 2 ) {
        usage();
    }
    num = (int)strtol( argv[optind], NULL, 0 );
    *optstr = argv[optind+1];
}
else {
    if( (argc - optind) != 1 ) {
        usage();
    }
    *optstr = argv[optind];
}

There are a few things about this code which don't work. I want to know why, and what is the right way to do this.

Thank you in advance for every answer

Upvotes: 0

Views: 314

Answers (1)

Sunil Bojanapally
Sunil Bojanapally

Reputation: 12658

Answer to 3rd question the assignment of argv[optind] to optstr throws: warning ? is as follows,

char *optstr; 
*optstr = argv[optind]; // Wrong if LHS is a string rather a char


optstr = argv[optind]; // Correct one

Here, optstr is a pointer to character which can store a single char or a string. Also *optstr refers to char and RHS argv[optind] is a string refers to a pointer. Hence the warning.

Upvotes: 1

Related Questions