Programming in C

Commandline Arguments

Gerald Senarclens de Grancy

Purpose of Commandline Arguments

  • Allow the user to pass information to a program upon startup
    • Which input files should be processed
      gcc infile.c
    • Options can be defined
      ls -l -a -h
    • Possible subcommands
      apt install programname

Issues

  • String parsing is tedious
  • ISO C's getopt (unistd.h) has limited features (eg. no long options)
  • Many libraries offer differing feature sets
  • Argument parsing libraries are usually not trivial to use

Foundation of Argument Passing

In C, arguments have to be passed to main(.)

argc
argument count
argv
argument vector
int main(int argc, char** argv) {
/* work with arguments */
return 0;
}

Example: Echo Arguments Without Using a Library

#include <stdio.h>

int main(int argc, char **argv) {
for (int i = 0; i < argc; ++i) {
puts(argv[i]);
}
return 0;
}
Download echo.c

Example: Show a Simple Help Message

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

int main(int argc, char **argv) {
for (int i = 1; i < argc; ++i) {
if (strcmp("-h", argv[i]) == 0 ||
strcmp("--help", argv[i]) == 0) {
puts("Usage: ls [OPTION]... ");
puts("-h, --help display this help and exit");
exit(0);
}
}
puts("To solve the world's problems, use the correct arguments");
return 0;
}
Download help.c

POSIX Standard getopt

+
standardized
avaiable everywhere
-
no support for long options
lack of support for subcommands etc.
#include <stdio.h>
#include <unistd.h> /* for getopt */
int main (int argc, char **argv) {
int c;
int aopt = 0, bopt = 0; // flags
char *copt = 0, *dopt = 0; // option arguments
while ((c = getopt(argc, argv, "abc:d:")) != -1) {
switch (c) {
case 'a':
aopt = 1;
break;
case 'b':
bopt = 1;
break;
case 'c':
copt = optarg;
break;
case 'd':
dopt = optarg;
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf ("non-option ARGV-elements: ");
while (optind < argc) {
printf ("%s ", argv[optind++]);
}
printf ("\n");
}
printf ("aopt: %d, bopt: %d, copt: %s, dopt: %s\n",
aopt, bopt, copt, dopt);
return 0;
}
Download posix_getopt.c

GNU getopt_long

#include <stdio.h>
#include <stdbool.h>
#include <getopt.h> // getopt_long
int main (int argc, char **argv) {
int c;
int has_a = false, has_b = false; // flags
int v = 0;
char *c_arg = 0, *d_arg = 0; // option_arguments
static struct option long_options[] = {
/* NAME ARGUMENT FLAG SHORTNAME */
{"add", required_argument, NULL, 0},
{"append", no_argument, NULL, 1000},
{"delete", required_argument, NULL, 0},
{"verbose", no_argument, NULL, 'v'},
{"create", required_argument, NULL, 'c'},
{"file", required_argument, NULL, 0},
{NULL, 0, NULL, 0}
};
int option_index = 0;
while ((c = getopt_long(argc, argv, "abc:d:v",
long_options, &option_index)) != -1) {
switch (c) {
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg) {
printf (" with arg %s", optarg);
}
printf ("\n");
break;
case 1000: // append
puts("`append` option was given");
break;
case 'a':
has_a = true;
break;
case 'b':
has_b = true;
break;
case 'c':
c_arg = optarg;
break;
case 'd':
d_arg = optarg;
break;
case 'v':
++v;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf ("non-option ARGV-elements: ");
while (optind < argc) {
printf ("%s ", argv[optind++]);
}
printf ("\n");
}
printf ("a: %s, b: %s, c_arg: %s, d_arg: %s, verbosity-level: %d\n",
has_a ? "true" : "false", has_b ? "true" : "false", c_arg, d_arg, v);
return 0;
}
Download gnu_getopt.c

Comprehensive Example(s)

Just look at the source code of your favorite commanline program...

apt source $PACKAGE

One possible example (using GNU getopt): cvrptwms

Other Libraries

There are many libraries for argument parsing...

... select the one that suits your needs

argparse
https://github.com/cofyc/argparse
MIT License

Exercise

Write a C program that takes the following arguments

-h, --help
-a, --author
display your name and email address
--color {red,green,blue}
display a message in the given color

Questions
and feedback...