Using getopt in C with non-option arguments

Conor Taylor picture Conor Taylor · Aug 6, 2013 · Viewed 30.3k times · Source

I'm making a small program in C that deals with a lot of command line arguments, so I decided to use getopt to sort them for me.

However, I want two non-option arguments (source and destination files) to be mandatory, so you have to have them as arguments while calling the program, even if there's no flags or other arguments.

Here's a simplified version of what I have to handle the arguments with flags:

while ((c = getopt(argc, argv, "i:d:btw:h:s:")) != -1) {
    switch (c) {
        case 'i': {
            i = (int)atol(optarg);
        }
        case 'd': {
            d = (int)atol(optarg);
        }
        case 'b':
            buf = 1;
            break;
        case 't':
            time = 1;
            break;
        case 'w':
            w = (int)atol(optarg);
            break;
        case 'h':
            h = (int)atol(optarg);
            break;
        case 's':
            s = (int)atol(optarg);
            break;
        default:
            break;
    }
}

How do I edit this so that non-option arguments are also handled?

I also want to be able to have the non-options either before or after the options, so how would that be handled?

Answer

Klas Lindbäck picture Klas Lindbäck · Aug 6, 2013

getopt sets the optind variable to indicate the position of the next argument.

Add code similar to this after the options loop:

if (argv[optind] == NULL || argv[optind + 1] == NULL) {
  printf("Mandatory argument(s) missing\n");
  exit(1);
}

Edit:

If you want to allow options after regular arguments you can do something similar to this:

while (optind < argc) {
  if ((c = getopt(argc, argv, "i:d:btw:h:s:")) != -1) {
    // Option argument
    switch (c) {
        case 'i': {
            i = (int)atol(optarg);
        }
        case 'd': {
            d = (int)atol(optarg);
        }
        case 'b':
            buf = 1;
            break;
        case 't':
            time = 1;
            break;
        case 'w':
            w = (int)atol(optarg);
            break;
        case 'h':
            h = (int)atol(optarg);
            break;
        case 's':
            s = (int)atol(optarg);
            break;
        default:
            break;
    }
    else {
        // Regular argument
        <code to handle the argument>
        optind++;  // Skip to the next argument
    }
}