11

I have a program which takes in multiple command line arguments so I am using getopt. One of my arguments takes in a string as a parameter. Is there anyway to obtain that string through the getopt function or would I have to obtain it through the argv[] array? Also can getopt read args like -file ? All the arguments I have seen till now have only one character such as -a

EDIT

From the below answers I have written a program to use getopt_long(), but the switch statement only recognizes the argument when I use the character argument and not the long argument. I'm not sure why this happening. On passing the arguments -mf -file sample I do not see the print statements.

EDIT

I tried entering the command arguments as --file and then it worked. Is it not possible to do this with just -file ?

static struct option long_options[] =
{
    {"mf", required_argument, NULL, 'a'},
    {"md", required_argument, NULL, 'b'},
    {"mn", required_argument, NULL, 'c'},
    {"mw", required_argument, NULL, 'd'},
    {"lf", required_argument, NULL, 'e'},
    {"ld", required_argument, NULL, 'f'},
    {"ln", required_argument, NULL, 'g'},
    {"lw", required_argument, NULL, 'h'},
    {"rf", required_argument, NULL, 'i'},
    {"rd", required_argument, NULL, 'j'},
    {"rn", required_argument, NULL, 'k'},
    {"rw", required_argument, NULL, 'l'},
    {"df", required_argument, NULL, 'm'},
    {"dd", required_argument, NULL, 'n'},
    {"dn", required_argument, NULL, 'o'},
    {"dw", required_argument, NULL, 'p'},
    {"file", required_argument, NULL, 'q'},
    {NULL, 0, NULL, 0}
};
int ch=0;
while ((ch = getopt_long(argc, argv, "abcdefghijklmnopq:", long_options, NULL)) != -1)
{
    // check to see if a single character or long option came through
        switch (ch){
        case 'a':
            cout<<"title";
            break;
        case 'b':
            
            break;
        case 'c':
            
            break;
        case 'd':
            
            break;
        case 'e':
            
            break;
        case 'f':
            
            break;
        case 'g':
            
            break;
        case 'h':
            
            break;
        case 'i':
            
            break;
        case 'j':
            
            break;
        case 'k':
            
            break;
        case 'l':
            
            break;
        case 'm':
            
            break;
        case 'n':
            
            break;
        case 'o':
            
            break;
        case 'p':
            
            break;
        case 'q':
            cout<<"file";
            break;
        case '?':
            cout<<"wrong message"
            break;  
    }
}
Community
  • 1
  • 1
RagHaven
  • 4,156
  • 21
  • 72
  • 113

2 Answers2

21

Read man getopt http://linux.die.net/man/3/getopt

optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument, so getopt() places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg. Two colons mean an option takes an optional arg; if there is text in the current argv-element (i.e., in the same word as the option name itself, for example, "-oarg"), then it is returned in optarg, otherwise optarg is set to zero.

A sample code:

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

int main (int argc, char *argv[])
{
  int opt;
  while ((opt = getopt (argc, argv, "i:o:")) != -1)
  {
    switch (opt)
    {
      case 'i':
                printf("Input file: \"%s\"\n", optarg);
                break;
      case 'o':
                printf("Output file: \"%s\"\n", optarg);
                break;
    }
  }
  return 0;
}

Here in the optstring is "i:o:" the colon ':' character after each character in the string tells that those options will require an argument. You can find argument as a string in the optarg global var. See manual for detail and more examples.

For more than one character option switches, see the long options getopt_long. Check the manual for examples.

EDIT in response to the single '-' long options:

From the man pages

getopt_long_only() is like getopt_long(), but '-' as well as "--" can indicate a long option. If an option that starts with '-' (not "--") doesn't match a long option, but does match a short option, it is parsed as a short option instead.

Check the manual and try it.

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
phoxis
  • 60,131
  • 14
  • 81
  • 117
  • I have tried using getopt_long, but my program is not recognizing the the arguments. I have added my code above. – RagHaven Jul 26 '13 at 10:45
18

To specify that a flag requires an argument, add a ':' right after the flag in the short_opt variable. To use long arguments, use getopt_long().

Here is a quick example program:

#include <getopt.h>
#include <stdio.h>

int main(int argc, char * argv[]);

int main(int argc, char * argv[])
{
   int             c;
   const char    * short_opt = "hf:";
   struct option   long_opt[] =
   {
      {"help",          no_argument,       NULL, 'h'},
      {"file",          required_argument, NULL, 'f'},
      {NULL,            0,                 NULL, 0  }
   };

   while((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1)
   {
      switch(c)
      {
         case -1:       /* no more arguments */
         case 0:        /* long options toggles */
         break;

         case 'f':
         printf("you entered \"%s\"\n", optarg);
         break;

         case 'h':
         printf("Usage: %s [OPTIONS]\n", argv[0]);
         printf("  -f file                   file\n");
         printf("  -h, --help                print this help and exit\n");
         printf("\n");
         return(0);

         case ':':
         case '?':
         fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
         return(-2);

         default:
         fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
         fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
         return(-2);
      };
   };

   return(0);
}
David M. Syzdek
  • 15,360
  • 6
  • 30
  • 40
  • 1
    Is there a limit to the number of different arguments I can use for getopt_long()? I have 17 different arguments and it only recognizes the argument when I enter the character version of the argument and not the long argument. – RagHaven Jul 26 '13 at 10:39
  • I believe you are only limited by memory. Are you updating the last value of the long_opts? In my example, each long option is paired with a short option. So '--help' and '-h' are the same option. However you could make the '--help' be the same as the '-p' option by changing the 'h' to 'p' and adding 'p' to the short_opt string. – David M. Syzdek Jul 26 '13 at 12:13
  • 3
    I just read you edits. You have to use '--option' instead of '-option'. getopt() and getopt_long() will interpret '-option' as '-o -p -t -i -o -n'. If you want to use long options with a single dash, you will have to either write your own CLI argument parser or try to find an existing one which matches your desired behavior. – David M. Syzdek Jul 26 '13 at 12:16
  • It's a little bit confusing that "required_argument" means that the flag require**s** an argument, rather than meaning that, for example, "file" is a required argument to the program (as in you can't call the program without passing the 'file' option). – Raleigh L. Sep 28 '22 at 22:49