This blog is under construction

Sunday, 3 February 2013

getopt_long example in C


Header file:
    getopt.h

Synopsis:
     int getopt_long (int argc, char *const *argv, const char *shortopts,
               const struct option *longopts, int indexptr);

Description:
     getopt_long can be used to parse long options as well as short options.  It returns -1, if there's no more options to parse.

struct option has four fields.  They are
const char *name   -   represents the name of the option.
int has_arg            -   represents no_argument, required_argument,
                                optional_argument
int *flag  & int val  -   If flag is NULL, getopt_long returns val. Otherwise, flag points
                               to the value in val to indicate that the option was seen.

"--"   -  indicates long option
"-"    -  indicates short opton

longopts[*indexptr].name - represents the name of the long option.
optarg                           - points to the optional argument or required argument.

Please know about getopt to get better understanding on getopt_long


getopt_long function C example


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

  struct option longopts[] = {
        {"list",   optional_argument, 0, 'l'},
        {"touch",  required_argument, 0, 'm'},
        {"rm",     required_argument, 0, 'r'},
        {"date",   no_argument,       0, 'd'}
  };

  int main (int argc, char **argv) {
        int i, ch, indexptr = 0;
        char str[100];
        opterr = 0;
        while ((ch = getopt_long(argc, argv, "l::m:r:d",
                                longopts, &indexptr)) != -1) {
                switch (ch) {
                        case 'd':
                                printf("short option - %c  long option - %s\n",
                                        ch, longopts[indexptr].name);
                                system("date");
                                break;
                        case 'l':
                                printf("short option - %c  long option - %s\n",
                                        ch, longopts[indexptr].name);
                                strcpy(str, "ls -l ");
                                if (optarg)
                                        strcat(str, optarg);
                                system(str);
                                break;
                        case 'm':
                                printf("short option - %c  long option - %s\n",
                                        ch, longopts[indexptr].name);
                                strcpy(str, "touch ");
                                strcat(str, optarg);
                                system(str);
                                break;
                        case 'r':
                                printf("short option - %c  long option - %s\n",
                                        ch, longopts[indexptr].name);
                                strcpy(str, "rm ");
                                strcat(str, optarg);
                                system(str);
                                break;

                        case '?':
                                if (optopt == 'r' || optopt == 'm')
                                        printf("Argument is mandatory for --%s\n",
                                                longopts[indexptr].name);
                                else if (isprint (optopt))
                                        printf("U have given an unknown option - %c\n",
                                                        optopt);
                                else
                                        printf("Unknown Error-0x%08x\n", optopt);
                                break;
                        default:
                                exit(0);
                }
        }
        for (i = optind; i < argc; i++)
                printf("Redundant argument - %s\n", argv[i]);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:$ ./a.out --touch file1 --list=file1 --rm file1 --list=file1
  short option - m  long option - touch
  short option - l  long option - list
  -rw-r--r-- 1 jp jp 0 2013-02-03 12:03 file1
  short option - r  long option - rm
  short option - l  long option - list
  ls: cannot access file1: No such file or directory

  jp@jp-VirtualBox:$ ./a.out --date
  short option - d  long option - date
  Sun Feb  3 12:09:58 IST 2013

  jp@jp-VirtualBox:$ ./a.out --rm
  Argument is mandatory for --list

  jp@jp-VirtualBox:$ ./a.out --touch file1 --rm file1 file2 file3
  short option - m  long option - touch
  short option - r  long option - rm
  Redundant argument - file2
  Redundant argument - file3


Notes:
Why optional argument is not parsed by getopt_long or getopt_long_only?
For optional argument, place '=' between option character and its argument.  There should not be any space between option and its argument.

Eg: ./a.out --list=hello
Here, long option "list" will take the optional argument hello since we have '=' between the option and argument.

No comments:

Post a Comment