4
#include <iostream>
#include <getopt.h>

#define no_argument 0
#define required_argument 1 
#define optional_argument 2


int main(int argc, char * argv[])
{
  std::cout << "Hello" << std::endl;

  const struct option longopts[] =
  {
    {"version",   no_argument,        0, 'v'},
    {"help",      no_argument,        0, 'h'},
    {"stuff",     required_argument,  0, 's'},
    {0,0,0,0},
  };

  int index;
  int iarg=0;

  //turn off getopt error message
  opterr=1; 

  while(iarg != -1)
  {
    iarg = getopt_long(argc, argv, "svh", longopts, &index);

    switch (iarg)
    {
      case 'h':
        std::cout << "You hit help" << std::endl;
        break;

      case 'v':
        std::cout << "You hit version" << std::endl;
        break;

      case 's':
        std::cout << "You hit stuff" << std::endl;
        break;
    }
  }

  std::cout << "GoodBye!" << std::endl;

  return 0; 
}

Output:

./a.out -s
Hello
You hit stuff
GoodBye!

Output:

./a.out --stuff
Hello
./a.out: option `--stuff' requires an argument
GoodBye!

Conflict needing resolved: Both -s & --s should say: ./a.out: option `--stuff' requires an argument when used without proceeding arguments following the command. But only --stuff does? Does anyone know what I'm missing here?

Desired result:

./a.out -s
     Hello
     ./a.out: option `--stuff' requires an argument
      GoodBye!

./a.out --stuff
     Hello
     ./a.out: option `--stuff' requires an argument
     GoodBye!
stackoverflow
  • 18,348
  • 50
  • 129
  • 196
  • Just a nit: Probably don't need those #define statements, as the variables of the same name ought to have been declared as an enum when getopt.h was included, thus redefining might throw an error. If some esoteric, archaic, or otherwise broken platform's getopt.h doesn't declare those variables, then the #defines should probably be wrapped inside an #ifdef checking for some variable defined only on that specific platform. –  Mar 19 '17 at 11:51

2 Answers2

9

Your getopt_long call specifies "svh" for the short options when it should say "s:vh". The colon tells getopt to require an argument for "s".

Kyle Jones
  • 5,492
  • 1
  • 21
  • 30
5

I'm pretty sure you need to replace "svh" with "s:vh". Per the Linux man page for getopt_long "optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument,".

spdaley
  • 811
  • 7
  • 7