The Pointer The Pointer - 1 month ago 12
C Question

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.

Answer

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.

Comments