Introduction
One of the important tasks of any program, be it console or graphical, is the interpretation of command line
arguments . Formally, all the words in the command line (including the name of the command itself) broken by a
separator (as a rule, this is a space and a tab) are called arguments, while quotation marks allow including separators in arguments.
Arguments can be divided into
options and
operands . Options change the behavior of the program or provide it with additional information. An option may have its own arguments, which are information necessary only for this option.
Posix
The POSIX standard describes the expected behavior of programs on UNIX-like systems. When writing a program, no one will force you to strictly follow the standard, however, this is a good idea, as this will make your users life easier. Here are the basic rules for command arguments:
- the program name must contain at least 2 and no more than 9 characters;
- program names should be written only in lowercase characters and numbers;
- The option name must be a simple alphanumeric character. Multi-digit options are disabled;
- All options must begin with a "-";
- for options with no arguments, the ability to combine options must be implemented (for example, foo -a -b -c and foo -abc );
- option argument must be separated from it by a space;
- option argument may not be optional;
- if options require multiple argument values, they must be passed as a string, separated by commas or a separator;
- options must go before operands;
- the argument "-" indicates the end of all options;
- the order of options should not play a role, except when options are mutually exclusive, then the latter wins;
- the order of the arguments may matter;
- programs that read or write named files should treat the single argument "-" as standard input or standard output, respectively.
Long options
GNU programs also use long options whose behavior is not described in POSIX; long options start with "-" The following conventions are also implemented for these options in GNU:
- each short option must have its own version of the long option;
- the long option can be shortened to the shortest line, ensuring its uniqueness;
- The arguments of the long option are separated either by a delimiter, or by the "=" sign.
Where do the parameters in the program come from
as it is known, the
main () function in C is defined as:
int main(int argc, char *argv[])
Here there are two parameters:
argc determines the number of arguments on the command line, and
argv stores an array of pointers to these arguments.
It should be noted that
argv [0] is always the name of the command, and
argv [argc] == NULL , these two facts may be useful in development.
')
Parsing options
In the 1980s, the Unix support team noticed that each Unix program uses its own method of parsing options. This prompted the development of the
getopt () function to make it easier to write code that follows standard conventions.
The GNU
getopt_long () function is compatible with
getopt () , and also simplifies the parsing of long options.
getopt
Announcement:
#include <unistd.h>
int getopt(int argc, char *argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
The
argc and
argv arguments are passed directly from the
main () function, and
optstring is a string of option characters. If any letter in the line is followed by a colon, then this option takes an argument.
To use
getopt (), it is called again in a loop, until it returns
-1 . Each time a valid option character is found, the function returns this character. If the option takes an argument, then the pointer to it is placed in the variable
optarg .
The
optind variable stores the current index in
argv . When the
opterr variable
is not zero (the default is
0 ),
getopt () itself displays messages in case of an invalid option or no argument. If
opterr is zero, then if an error occurs,
getopt () returns
"?" or
":" , depending on whether an invalid option is found or the required argument of the option is omitted, the detected symbol will be found in the
optopt variable.
It should be noted that the standard
getopt () function stops as soon as it finds the first argument that does not begin with the “-” character, the GNU option scans the option line for the entire command line. The behavior of the GNU functions can be changed (but this is beyond the scope of the article).
sample program using getopt ()
Courtesy of
iv_s- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- int main ( int argc, char ** argv) {
- if (argc == 1) { // if we run without arguments, display help
- printf ( "getopt test \ n" );
- printf ( "usage: \ n" );
- printf ( "opts -an -bm -os \ n" );
- printf ( "example: \ n" );
- printf ( "$ opts -a 323 -b 23 -o '-' \ n" );
- printf ( "323 - 23 = 300 \ n" );
- return 0;
- }
- char * opts = "a: b: o:" ; // available options, each takes an argument
- int a, b; // store numbers here
- char op; // and here is the operator
- int opt; // each next option gets here
- while ((opt = getopt (argc, argv, opts))! = -1) { // call getopt until it returns -1
- switch (opt) {
- case 'a' : // if the -a option, convert the string with the argument to a number
- a = atoi (optarg);
- break ;
- case 'b' : // for -b too
- b = atoi (optarg);
- break ;
- case 'o' : // in op save the statement
- op = optarg [0];
- break ;
- }
- }
- switch (op) {
- case '+' : // if opator + add, etc.
- printf ( "% d +% d =% d \ n" , a, b, a + b);
- break ;
- case '-' :
- printf ( "% d -% d =% d \ n" , a, b, a - b);
- break ;
- case '*' :
- printf ( "% d *% d =% d \ n" , a, b, a * b);
- break ;
- case '/' :
- printf ( "% d /% d =% d \ n" , a, b, a / b);
- break ;
- }
- return 0;
- }
* This source code was highlighted with Source Code Highlighter .
getopt_long ()
Announcement:
#include <getopt.h>
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex);
the first three arguments are the same as in
getopt () ,
longopts is a pointer to an array of long options,
longindex points to a variable in which the index of the detected long options is
placed in
longopts , if this may not be necessary
NULL .
The
option structure is defined as follows:
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
}
name - the name of the option without preceding dashes;
has_arg - as the name implies, the variable describes whether the long option has an argument that can take three values:
- 0 - does not accept the argument;
- 1 is a required argument;
- 2 is an optional argument.
flag - if this pointer is
NULL , then
getopt_long () returns the value of the
val field, otherwise it returns
0 , and the variable pointed to by flag is filled with the value of
val ;
val - usually contains some symbolic constant, if the long option is short, then this constant must be the same as the one that appears in the argument
optstring .
It is important to note that the last element of the
longopts array must be filled with zeros.
Sample program using getopt_long ()
Courtesy of
shuffle- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <getopt.h>
- void usage ( char * name)
- {
- printf ( "usage:% s \ n \ \ th this message \ n \ \ tc [config file] \ n \ \ t - help this message \ n \ \ t - config = config_file \ n", name);
- return ;
- }
- int main ( int argc, char * argv [])
- {
- int c;
- while (1) {
- static struct option long_opt [] = {
- { "Help" , 0, 0, 'h' },
- { "Config" , 1, 0, 'c' },
- {0,0,0,0}
- };
- int optIdx;
- if ((c = getopt_long (argc, argv, "c: h" , long_opt, & optIdx)) == -1)
- break ;
- switch (c) {
- case 'h' :
- usage (argv [0]);
- return (-1);
- case 'c' :
- printf ( "option 'c' selected, filename:% s \ n" , optarg);
- return (1);
- default :
- usage (argv [0]);
- return (-1);
- }
- }
- return (0);
- }
* This source code was highlighted with Source Code Highlighter .
Conclusion
The article describes the basics of using the functions of parsing command line arguments on UNIX-like systems. This material can be more extensive, but any interested person is able to learn and learn all the subtleties on their own.
The article was prepared on the basis of the book by Arnold Robbins "Linux programming in examples"
ISBN 5-9579-0059-1