1

I need to parse command line arguments in C. My arguments are basically int or float with default values and range constrains.

I've started to implement something that look like this:

option_float(float* out, int argc, char* argv, char* name, description,
    float default_val, int is_optional, float min_value, float max_value)

which I call for example with:

float* pct;
option_float(pct, argc, argv, "pct", "My super percentage option", 50, 1,
    FALSE, 0, 100)

However I don't want to reinvent the wheel!

My objective is to have error checking of range constraints, throw an error when the option is not optional and is not set. And generate the help message usually given by usage() function.

The usage text would look like this:

--pct     My super percentage option (default : 50). Should be in [0, 100]

I've started with getopt but it is too limited for what I want to do and I feel it still requires me to write too much code for a simple use case like this.

What alternatives would you recommend?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
agramfort
  • 71
  • 4
  • 2
    [Argument-parsing helpers for C/UNIX](http://stackoverflow.com/q/189972/2509) goes over some of the options (ad there are probably other questions on the site, it's common need). I don't know one that meets all you requirements, but `gengetopt` would reduce the amount of code you have to write. – dmckee --- ex-moderator kitten Dec 26 '10 at 20:08
  • gengetopt is unfortunately GPL but gopt and glib seem to be good candidates. I'll explore these two options. Thanks – agramfort Dec 27 '10 at 16:23

1 Answers1

0

Assuming you are coding for Linux...

Try getopt_long (man 3 getopt_long) for the double-dash options.

Also, try making the validators to be generic functions and let getopt/getopt_long to the hard part of the parsing and checking required arguments to options.

In any case, if you want to use your functions as defined, your example call will not work as defined.

A simplified example:

int main( int argc, char **argv )
{
  float pct = 0.0
  if( !GetArgs(argc, argv, &pct) )
    DoStuff(pct)
}

int GetArgs( int argc, char **argv, float *thePct )
{
  extern char *optarg;
  int  rc = 0;

  (*thePct) = 50.0  /* default val */

  while( (opt = getopt(argc, argv, "hp:")) != -1 )
  {
    switch( opt )
    {
      case  'p':
            (*thePct) = atof( optarg );
            break;

      case  'h':
            MyUsage();  /* Explain everything */
            rc = -1;
            break;
    }
  }

  if( !rc )
  {
    rc = ValidatePct( (*thePct),   /* value to check */
                      0.0,         /* low pct val */
                      100.0 );     /* hi pct val */

    /* Other validations here */

    if( !rc )
      MyUsage();
  }
}

This will allow a call like:

$ myprogram -p 45.0

If you stick to the parsers getopt and getopt_long, you can also make command lines that take options followed by N number of other arguments like grep does, for instance:

grep -in -e "SomeRegex" file1, file2, ..., fileN

Out of sheer curiosity, you aren't a PERL programmer, are you?

buzzwang
  • 336
  • 3
  • 3
  • that's a nice and simple design around getopt but still a bit too verbose for the Python programmer I am ;) I'll explore gopt and glib as suggested above. thanks – agramfort Dec 27 '10 at 16:25
  • That's the name of the game with C. It is a much lower level language than Python. – buzzwang Dec 27 '10 at 21:29