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.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
sudobangbang
  • 1,406
  • 10
  • 32
  • 55
  • 1
    Can you show your switch case? – IsakBosman Jan 24 '15 at 18:58
  • 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. –  Jan 24 '15 at 19:20
  • 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 arguments – user3629249 Jan 25 '15 at 16:30

1 Answers1

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

ottovon
  • 333
  • 2
  • 10
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • 1
    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. – Jonathan Leffler Jan 24 '15 at 20:30
  • Sorry, I am new to C what is the purpose of the variable aflag bflag etc – sudobangbang Jan 25 '15 at 15:00
  • 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? – sudobangbang Jan 25 '15 at 17:37
  • @sudobangbang 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. – Cloud Jan 25 '15 at 20:55