Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling command line flags in C/C++

I am looking for a very simple explanation/tutorial on what flags are. I understand that flags work indicate a command what to do. For example:

rm -Rf test

I know that the rm command will remove the test folder and that the -Rf flags will force the command to erase not just the folder but the files in it.

But, where are the flags read/compiled??? What handles the flags? Can I, for example, write my own C/C++ program and designate different flags so that the program does different things? I hope I am asking the right questions. If not, please let me know.

like image 560
Fabio Gomez Avatar asked Feb 06 '13 20:02

Fabio Gomez


Video Answer


2 Answers

At the C level, command line arguments to a program appear in the parameters to the main function. For instance, if you compile this program:

#include <stdio.h>
int main(int argc, char **argv)
{
    int i;
    for (i = 0; i < argc; i++)
        printf("argv[%d] = %s\n", i, argv[i]);
    return 0;
 }

and invoke it with the same arguments as your example 'rm' command, you get this:

$ ./a.out -Rf test
argv[0] = ./a.out
argv[1] = -Rf
argv[2] = test

As you can see, the first entry in argv is the name of the program itself, and the rest of the array entries are the command line arguments.

The operating system does not care at all what the arguments are; it is up to your program to interpret them. However, there are conventions for how they work, of which the following are the most important:

  • Arguments are divided into options and non-options. Options start with a dash, non-options don't.
  • Options, as the name implies, are supposed to be optional. If your program requires some command-line arguments to do anything at all useful, those arguments should be non-options (i.e. they should not start with a dash).
  • Options can be further divided into short options, which are a single dash followed by a single letter (-r, -f), and long options, which are two dashes followed by one or more dash-separated words (--recursive, --frobnicate-the-gourds). Short options can be glommed together into one argument (-rf) as long as none of them takes arguments (see below).
  • Options may themselves take arguments.
    • The argument to a short option -x is either the remainder of the argv entry, or if there is no further text in that entry, the very next argv entry whether or not it starts with a dash.
    • The argument to a long option is set off with an equals sign: --output=outputfile.txt.
  • If at all possible, the relative ordering of distinct options (with their arguments) should have no observable effect.
  • The special option -- means "do not treat anything after this point on the command line as an option, even if it looks like one." This is so, for instance, you can remove a file named '-f' by typing rm -- -f.
  • The special option - means "read standard input".
  • There are a number of short option letters reserved by convention: the most important are
    • -v = be verbose
    • -q = be quiet
    • -h = print some help text
    • -o file = output to file
    • -f = force (don't prompt for confirmation of dangerous actions, just do them)

There are a bunch of libraries for helping you parse command line arguments. The most portable, but also the most limited, of these is getopt, which is built into the C library on most systems nowadays. I recommend you read all of the documentation for GNU argp even if you don't want to use that particular one, because it'll further educate you in the conventions.

It's also worth mentioning that wildcard expansion (rm -rf *) is done before your program is ever invoked. If you ran the above sample program as ./a.out * in a directory containing only the binary and its source code you would get

argv[0] = ./a.out
argv[1] = a.out
argv[2] = test.c
like image 168
zwol Avatar answered Oct 07 '22 00:10

zwol


This simple program should demonstrate the arguments passed to the program (including the program name itself.)

Parsing, interpreting and using those arguments is up to the programmer (you), although there are libraries available to help:

int main(int argc, char* argv[])
{
    int i;
    for(i=0; i<argc; ++i)
    {   printf("Argument %d : %s\n", i, argv[i]);
    }
    return 0;
}

If you compile this program into a.out, and run it as:

prompt$>  ./a.out ParamOne ParamTwo -rf x.c

You should see output:

Argument 0 : a.out
Argument 1 : ParamOne
Argument 2 : ParamTwo
Argument 3 : -rf
Argument 4 : x.c
like image 36
abelenky Avatar answered Oct 07 '22 00:10

abelenky