The Pointer
The Pointer

Reputation: 2386

getopt() function - optind not incrementing/behaving as expected

Depending on the format with which I pass options to this program, the variable optind will either increment properly to reflect the next option value or it will not.

If I use ./cfind -aru, I get the following (strange) output.

optind: 1
aflag detected
optind: 1
optind: 1
rflag detected
optind: 1
optind: 2
uflag detected
optind: 2

Notice that optind does not increment from aflag to rflag but it does increment from rflag to uflag.

However, when I use the format ./cfind -a -r -u, I get the following (expected) output.

optind: 2
aflag detected
optind: 2
optind: 3
rflag detected
optind: 3
optind: 4
uflag detected
optind: 4

This is the output I desire.

My code for this function is as follows.

#include "cfind.h"
#define OPTLIST "acdirstu" // list of valid options

void ProcOpt(int argc, char *argv[]) {
    int opt = 0; // default value
    opterr = 0; // prevent getopt from passing error message to stderr buffer
    // char *filenm = NULL; // pointer to the path name
    while((opt = getopt(argc, argv, OPTLIST)) != -1) {
        switch (opt) {
            case 'a':
                fprintf(stdout, "optind: %i\n", optind);
                aflag = true;
                assert(aflag == true);
                fprintf(stdout, "aflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 'c':
                fprintf(stdout, "optind: %i\n", optind);
                cflag = true;
                assert(cflag == true);
                fprintf(stdout, "cflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 'd':
                fprintf(stdout, "optind: %i\n", optind);
                dflag = true;
                assert(cflag == true);
                fprintf(stdout, "dflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 'i':
                fprintf(stdout, "optind: %i\n", optind);
                iflag = true;
                assert(iflag == true);
                fprintf(stdout, "iflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 'r':
                fprintf(stdout, "optind: %i\n", optind);
                rflag = true;
                assert(rflag == true);
                fprintf(stdout, "rflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 's':
                fprintf(stdout, "optind: %i\n", optind);
                sflag = true;
                assert(sflag == true);
                fprintf(stdout, "sflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 't':
                fprintf(stdout, "optind: %i\n", optind);
                tflag = true;
                assert(tflag == true);
                fprintf(stdout, "tflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);
            break;      
            case 'u':
                fprintf(stdout, "optind: %i\n", optind);
                uflag = true;
                assert(uflag == true);
                fprintf(stdout, "uflag detected\n");
                fprintf(stdout, "optind: %i\n", optind);        
            break;
            default:
                usage();
        }   
    }   
}

Am I doing something wrong? Is there something I am misunderstanding about getopt() and how it increments optind?

Thank you.

Upvotes: 0

Views: 1325

Answers (4)

Ernie Sender
Ernie Sender

Reputation: 414

#include <stdio.h> #include <unistd.h>
      extern char *optarg;
      extern int optind;
      int main (int argc, char** argv) {
        int c;
      printf("--------- options: ---------\n");
      while ((c = getopt (argc,argv,"abcd:")) != -1) {
          printf("opt: %c arg %s\n", (char)c, optarg);
      }
      argc -= optind - 1;
      argv += optind - 1; 
      printf("------ remaining args: ------\n");
      for (int i = 1; i < argc; i++) {
      printf("argv[%d] = %s\n", i, argv[i]); 
     } 
    }

Upvotes: 0

dave
dave

Reputation: 4922

Put this at the start of your program to see what is going on:

for (int i = 0; i < argc; ++i)
     printf("Param %d: %s\n", i, argv[i]);

Upvotes: 0

Andy Schweig
Andy Schweig

Reputation: 6739

That output looks right to me.

optind is the index of the next argument to be processed. When you have all the options together, they're all in argv[1], so optind remains at 1 until you've processed the u option. At that point, since everything in argv[1] has been consumed, optind is set to 2.

When the options are all in separate elements of argv, optind is always the index of the next argument to be processed.

See http://man7.org/linux/man-pages/man3/getopt.3.html.

Upvotes: 1

kaylum
kaylum

Reputation: 14044

The getopt man page says (emphasis mine):

The variable optind is the index of the next element to be processed in argv.

Your invocation options -aru are all contained as a single string in argv[1].

Upvotes: 2

Related Questions