C examples: Difference between revisions
No edit summary |
|||
Line 186: | Line 186: | ||
argp_parse (&argp, argc, argv, 0, 0, 0); |
argp_parse (&argp, argc, argv, 0, 0, 0); |
||
exit (0); |
exit (0); |
||
} |
|||
</source> |
|||
== Report errors== |
|||
On Linux, use functions <code>err</code>, <code>errx</code> defined in header {{file|err.h}}. This replaces conveniently custom error-reporting functions: |
|||
<source lang="c"> |
|||
#include <err.h> |
|||
// ... |
|||
if ( bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0 ) { |
|||
err(1, "bind failed"); |
|||
/* errx(1, "bind failed: ", strerror(errno)); // Equivalent */ |
|||
} |
|||
</source> |
|||
<code>errx</code> is similar to following <code>die</code> function: |
|||
<source lang="c"> |
|||
void die(int errcode, const char *format, ...) |
|||
{ |
|||
va_list ap; |
|||
va_start(ap, format); |
|||
int result = fprintf(stderr, "%s: ", APPNAME); |
|||
result += vfprintf(stderr, format, ap); |
|||
va_end(ap); |
|||
fflush(stderr); |
|||
exit(errcode); |
|||
} |
} |
||
</source> |
</source> |
Revision as of 06:24, 5 October 2018
Parse command-line parameters
The standard solution is to use either getopt or argp SO, GNU C library.
Using getopt
This is suitable to parse short arguments, although getopt can also parse long ones. The short-option only version is actually a part of the POSIX standard.
From SO:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
bool isCaseInsensitive = false;
int opt;
enum { CHARACTER_MODE, WORD_MODE, LINE_MODE } mode = CHARACTER_MODE;
while ((opt = getopt(argc, argv, "ilw")) != -1) {
switch (opt) {
case 'i': isCaseInsensitive = true; break;
case 'l': mode = LINE_MODE; break;
case 'w': mode = WORD_MODE; break;
default:
fprintf(stderr, "Usage: %s [-ilw] [file...]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
// Now optind (declared extern int by <unistd.h>) is the index of the first non-option argument.
// If it is >= argc, there were no non-option arguments.
// ...
}
Below another example using short options from the GNU C lib manual. See that manual for another example using getopt_long
.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "abc:")) != -1)
switch (c)
{
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("aflag = %d, bflag = %d, cvalue = %s\n",
aflag, bflag, cvalue);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
Using argp
argp is a complete solution to parse long parameters, including support for -?
, --help
, -V
, --version
, and --usage
.
From SO:
#include <argp.h>
#include <stdbool.h>
const char *argp_program_version = "programname programversion";
const char *argp_program_bug_address = "<your@email.address>";
static char doc[] = "Your program description.";
static char args_doc[] = "[FILENAME]...";
static struct argp_option options[] = {
{ "line", 'l', 0, 0, "Compare lines instead of characters."},
{ "word", 'w', 0, 0, "Compare words instead of characters."},
{ "nocase", 'i', 0, 0, "Compare case insensitive instead of case sensitive."},
{ 0 }
};
struct arguments {
enum { CHARACTER_MODE, WORD_MODE, LINE_MODE } mode;
bool isCaseInsensitive;
};
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
struct arguments *arguments = state->input;
switch (key) {
case 'l': arguments->mode = LINE_MODE; break;
case 'w': arguments->mode = WORD_MODE; break;
case 'i': arguments->isCaseInsensitive = true; break;
case ARGP_KEY_ARG: return 0;
default: return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };
int main(int argc, char *argv[])
{
struct arguments arguments;
arguments.mode = CHARACTER_MODE;
arguments.isCaseInsensitive = false;
argp_parse(&argp, argc, argv, 0, 0, &arguments);
// ...
}
Below the smallest program using argp, from GNU C Lib
/* This is (probably) the smallest possible program that
uses argp. It won’t do much except give an error
messages and exit when there are any arguments, and print
a (rather pointless) messages for –help. */
#include <stdlib.h>
#include <argp.h>
int
main (int argc, char **argv)
{
argp_parse (0, argc, argv, 0, 0, 0);
exit (0);
}
Another example using only default options. See the GNU C Lib manual for more examples including user-defined options, and sub-options.
#include <stdlib.h>
#include <argp.h>
const char *argp_program_version =
"argp-ex2 1.0";
const char *argp_program_bug_address =
"<bug-gnu-utils@gnu.org>";
/* Program documentation. */
static char doc[] =
"Argp example #2 -- a pretty minimal program using argp";
/* Our argument parser. The options, parser, and
args_doc fields are zero because we have neither options or
arguments; doc and argp_program_bug_address will be
used in the output for ‘--help’, and the ‘--version’
option will print out argp_program_version. */
static struct argp argp = { 0, 0, 0, doc };
int
main (int argc, char **argv)
{
argp_parse (&argp, argc, argv, 0, 0, 0);
exit (0);
}
Report errors
On Linux, use functions err
, errx
defined in header err.h. This replaces conveniently custom error-reporting functions:
#include <err.h>
// ...
if ( bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0 ) {
err(1, "bind failed");
/* errx(1, "bind failed: ", strerror(errno)); // Equivalent */
}
errx
is similar to following die
function:
void die(int errcode, const char *format, ...)
{
va_list ap;
va_start(ap, format);
int result = fprintf(stderr, "%s: ", APPNAME);
result += vfprintf(stderr, format, ap);
va_end(ap);
fflush(stderr);
exit(errcode);
}