Using getopt in C for command line arguments
Asked Answered
C

1

0

I am working on trying to take in command line arguments. If I want to have multiple optional command line arguments how would I go about doing that? For example you can run the program in the following ways: (a is required every instance but -b -c -d can be given optionally and in any order)

./myprogram -a
./myprogram -a -c -d
./myprogram -a -d -b

I know that getopt()'s third argument is options. I can set these options to be "abc" but will the way I have my switch case set up causes the loop to break at each option.

Carrier answered 24/1, 2015 at 18:56 Comment(3)
Can you show your switch case?Elvyn
Please show your loop and switch block since it is your loop that is being terminated prematurely. Normally the loop only checks whether getopt returned -1, assigning the return value to a variable for use in the switch statement.Frottage
IMO: the best way to retrieve command line arguments is to use make use of argc to retrieve the total count of arguments and to use *argv[] to retrieve the arguments. Where argc is the number of items in argv and argv[0] is the program number and argv[argc] will be the a null pointer indicating the end of the list of command line argumentsBranchia
J
6

The order doesn't matter so far as getopt() is concerned. All that matters is your third argument to getopt() (ie: it's format string) is correct:

The follow format strings are all equivalent:

"c:ba"
"c:ab"
"ac:b"
"abc:"

In your particular case, the format string just needs to be something like "abcd", and the switch() statement is properly populated.

The following minimal example¹ will help.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main (int argc, char **argv)
{
  int aflag = 0;
  int bflag = 0;
  char *cvalue = NULL;
  int index;
  int c;

  opterr = 0;

  while ((c = getopt (argc, argv, "abc:")) != -1)
  {
    switch (c)
      {
      case 'a':
        aflag = 1;
        break;
      case 'b':
        bflag = 1;
        break;
      case 'c':
        cvalue = optarg;
        break;
      case '?':
        if (optopt == 'c')
          fprintf (stderr, "Option -%c requires an argument.\n", optopt);
        else if (isprint (optopt))
          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
        else
          fprintf (stderr,
                   "Unknown option character `\\x%x'.\n",
                   optopt);
        return 1;
      default:
        abort ();
      }
  }

  printf ("aflag = %d, bflag = %d, cvalue = %s\n",
          aflag, bflag, cvalue);

  for (index = optind; index < argc; index++)
    printf ("Non-option argument %s\n", argv[index]);
  return 0;
}

¹Example taken from the GNU manual

Janusfaced answered 24/1, 2015 at 19:37 Comment(4)
I wouldn't write the while loop without braces around its body, even though the switch is logically a single statement. That's a point of detail though, and to some extent preference. The code is pretty good otherwise. Your attention to detail in the reporting of unknown options is impressive! (I'm not normally as careful as that. OTOH, I normally let getopt() report the error — I don't set opterr = 0;.) It is a good idea to report the expected usage: fprintf(stderr, "Usage: %s [-ab][-c name] [file ...]\n", argv[0]); when the error is detected.Ethelyn
Sorry, I am new to C what is the purpose of the variable aflag bflag etcCarrier
Also I suppose I dont understand how it is able to handle multiple flags if there is a break? for example if I am calling -a -b -c wont it hit -a then break the loop before hitting b and c 's case statement?Carrier
@Carrier The break statement will only break out of a single level/depth of a loop or a switch statement. The break statements in the example above will break out of the switch statement, but not out of the while loop that encompasses it.Janusfaced

© 2022 - 2024 — McMap. All rights reserved.