Carl
Carl

Reputation: 991

Handling user error with getopt_long

How do I handle the situation where a user only enters one dash before the long version of an argument?

For example, running my program with -copy

$ my_program -copy
Copy
Open
my_program: invalid option -- p
Unknown 

It is a problem that the o option was executed. My aim is to have an error report displayed, something of the mindset "you typed more than one character after a single dash".

The code

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

int main( int argc, char *argv[] )
{
  struct option options[] =
  {
    {"open",  no_argument, 0, 'o'},
    {"copy", no_argument, 0, 'c'},
    {0, 0, 0, 0}
  };

  int c;
  int option_index = 0;
  while ( ( c = getopt_long( argc, argv, "oc", options, &option_index ) ) != -1 )
  {
    switch (c)
    {
    case 'o':
      printf( "Open\n" );
      break;
    case 'c':
      printf( "Copy\n" );
      break;
    default:
      printf( "Unknown\n" );
      return 0;
    }
  }

  return 0;
}

Upvotes: 0

Views: 826

Answers (1)

Crowman
Crowman

Reputation: 25908

There's no way to do this other than parsing the command line manually. getopt_long() works on the assumption that long options start with --, and that if you don't want --, you're not trying to enter a long option. In any case, it would at best be ambiguous as to whether the user really did forget a -, or whether the user actually thought there were p and y short options, and there's no way for the program to distinguish the two cases.

What you can do instead, though, if desirable, is replace getopt_long() with getopt_long_only(), which allows long options to be specified with a single -. In your particular case, -copy would be accepted as an alternative to --copy, so you wouldn't need to report an error. Obviously you increase the likelihood of ambiguous matches this way.

Amended code:

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

int main(int argc, char *argv[]) {
    struct option options[] = {
        {"open", no_argument, 0, 'o'},
        {"copy", no_argument, 0, 'c'},
        {0, 0, 0, 0}
    };

    int c;
    int option_index = 0;
    while ((c = getopt_long_only(argc, argv, "oc",
                                 options, &option_index)) != -1) {
        switch (c) {
        case 'o':
            printf("Open\n");
            break;
        case 'c':
            printf("Copy\n");
            break;
        default:
            printf("Unknown\n");
            return 0;
        }
    }

    return 0;
}

and output:

paul@local:~/src/sandbox$ ./go -copy
Copy
paul@local:~/src/sandbox$ 

Upvotes: 2

Related Questions