43

I know of the following:

  • The venerable getopt(3)
  • The extended getopt_long
  • glibc's argp parser for Unix-style argument vectors
  • popt from the GNOME project (or its spiritual successor in Glib)

I'm sure there's more that I haven't used or even heard of; a quick Google search reveals Gopt, argtable, and Optlist.

Personally, I like argp best, and every program I wrote using getopt/getopt_long (beyond a certain baseline of complexity) has been converted to use argp. It's more widely available than popt, more powerful than getopt_long, well-documented, consistent with all the GNU-style conventions, and very flexible. On the downside, it's far from the easiest to use (thanks to being so flexible), and the code to support it is quite verbose (as are many things in C).

What do you use, and why?

Yes, I mean C rather than C++. There are a ton of C++ parsers, but I don't use C++.

John Millikin notes that popt is no longer maintained. I list it because many programs still use it -- including AbiWord, rpm, rsync, and samba -- despite Gnome's efforts to migrate away. But I've added a link to Glib's argument parser now, too.


For C++ argument parsing, see the question What parameter parser libraries are there for C++?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ephemient
  • 198,619
  • 38
  • 280
  • 391

7 Answers7

18

GNU has gengetopt which generates code for an options data structure and the getopt_long code to parse the command line and fill the structure.. It's fairly easy to learn and works well.

As a bonus you can pass the options structure around your code and avoid global storage if desired.

It provides GNU style semantics (obviously), and is small enough to simply include with the project for distribution if you're not sure of your audience's build environment.

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
5

As the saying goes, "standard is better than better". So I always use getopt_long() and anything that is non-GNOME/glibby, and the glib one on anything that does.

For the same reason I always use optparse in Python applications, even though it has a lot of missing features relative to getopt_long() ... but that's the Python standard.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
James Antill
  • 2,825
  • 18
  • 16
  • I've never used a system without glibc, but you do have a good point that getopt_long is even more widespread. Now I'm curious as to why both you and John mentioned Python? :) – ephemient Oct 10 '08 at 19:22
  • 4
    I can't speak for them but generally I consider witting direct C programs waist of time. I write program in python and if necessary libraries in C. – Luka Marinko Oct 14 '08 at 22:10
  • In Python 3.x the standard has been renamed to argparse. – EvertW Jul 12 '18 at 07:50
4

Since I was looking for the same thing, I read the answers of this old topic. Finally I chose dropt which is mentioned in What parameter parser libraries are there for C++?. Actually it's implemented in C, so I think it's worth mentioning here as well. I haven't used the C++ helper, which wraps the C implementation.

Interesting facts about dropt:

  • Lightweight
  • Depends only on standard libs
  • No steep learning curve
  • Sufficient for basic arg parsing, plus a couple of powerful features
  • Easy to extend
  • Unrestrictive license (zlib-ish)

It is limited though. For instance, I had to adapt my parameters syntax specifications a little; that was acceptable in this very case, but of course sometimes specifications are carved in stone.

As a conclusion I would recommend dropt at least for fast prototyping, tools development, and in-house projects.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
eruve
  • 661
  • 5
  • 12
3

popt has been abandoned for a long time -- argument parsing was merged into glib since version 2.6, three years ago.

I use glib's parser, or Python's port of getopt.

John Millikin
  • 197,344
  • 39
  • 212
  • 226
  • 1
    I'd like to know why you use glib's argument parser -- what makes it better for your uses than alternatives? – ephemient Oct 10 '08 at 03:16
  • For no other reason than being bundled with glib. I can learn how to use another parser, or just use the one everybody else does. – John Millikin Oct 10 '08 at 03:26
  • Just commenting that the question does ask "What do you use, and why?"... Glib's parser does look pretty nice, though, so thanks for the answer. – ephemient Oct 10 '08 at 03:42
  • There was a release 1.15 of `popt` in Apr 2009 and release 1.16 in May 2010. However, if the http://rpm5.org/files/popt/ site is to be believed, there have been no releases since then — it now (March 2018) qualifies as 'unmaintained', even if it was not strictly true back in mid-2010. – Jonathan Leffler Mar 21 '18 at 21:41
2

I'm not too fond of getopt either (although it's pretty standard). One solution I've made is the function argopt(). It's C compatible, can be used to test whether flags are set as well as reading options with values. It only supports short options (e.g. -h) although writing a similar function for long options (e.g. --help) shouldn't be too difficult. See example:

int main(int argc, char **argv){

    if(argopt(argc, argv, 'p')) printf("-p is set\n");
    if(argopt(argc, argv, 'q')) printf("-q is set\n");

    const char *f = argopt(argc, argv, 'f');
    if(f) printf("-f is %s\n",f);

    return 0;
}

Example from command line:

$./main -f input.txt -rq
-q is set
-f is input.txt

Disclaimer: I made this function for fun, intending for it to be short, C-compatible, easy to use, and have no dependencies. Here it is:

const char* argopt(int argc, const char *const *argv, char key){

    for(int i=1; i<argc; i++){
        const char *c = argv[i];
        if(*c!='-') continue;
        while(*++c) if(*c==key) return argv[(i+1)%argc];
    }

    return 0;
}
sigvaldm
  • 564
  • 4
  • 15
  • 1
    One disadvantage of this scheme is that if the user types `./main -t -V`, you never report on the invalid options — you just ignore them (witness `-r` in the example). Another is that the function does not handle `--` as 'end of option arguments'. If someone writes `-finput output`, your code reports that the file name is `output`, not `input`. These issues would be sufficient to stop me using your solution. As it happens, since `argv[argc]` is defined to be NULL, you don't need the modulus operation. It's an interesting idea. – Jonathan Leffler May 19 '17 at 01:01
  • 1
    Yes, that's why I added the disclaimer. It's made to be minimal rather than fail-safe and flexible. The example intentionally uses `-r` to indicate this. Whether `-finput` should even be a valid input depends on which conventions you use. I used the convention that grouping of flags should be allowed, e.g. `-rq`. Then `-finput` would be a grouping of flags `f`, `i`, and so forth. Of course you could treate the `f`option differently from `q`, but then it wouldn't be minimal. The modulus is necessary since otherwise the search for `q` would evaluate false. I appreciate your feedback, though. – sigvaldm May 19 '17 at 09:14
0

I have been developing and using libparamset that is a command-line parameter parsing library written in plain C. It provides:

  • Cross-platform functionality (Linux, OS X, Windows).
  • Configurable parser where each parameter can act differently (powerful and flexible feature).
  • Auto-generated messages for typos, unknown parameters or invalid parameters.
  • Extra functionality to design command-line user interface.
  • Good documentation.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Taavi Valjaots
  • 111
  • 1
  • 4
-1

I really like the TCLAP library, because it is very flexible and easy to use. It is also completely template-based, so it is a header-only library.

My mistake: you said C and I posted a C++ library...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Scott Dillman
  • 821
  • 1
  • 9
  • 16