Getopt- Passing string parameter for argument - c

I have a program which takes in multiple command line arguments so I am using getopt. One of my arguments takes in a string as a parameter. Is there anyway to obtain that string through the getopt function or would I have to obtain it through the argv[] array? Also can getopt read args like -file ? All the arguments I have seen till now have only one character such as -a
EDIT
From the below answers I have written a program to use getopt_long(), but the switch statement only recognizes the argument when I use the character argument and not the long argument. I'm not sure why this happening. On passing the arguments -mf -file sample I do not see the print statements.
EDIT
I tried entering the command arguments as --file and then it worked. Is it not possible to do this with just -file ?
static struct option long_options[] =
{
{"mf", required_argument, NULL, 'a'},
{"md", required_argument, NULL, 'b'},
{"mn", required_argument, NULL, 'c'},
{"mw", required_argument, NULL, 'd'},
{"lf", required_argument, NULL, 'e'},
{"ld", required_argument, NULL, 'f'},
{"ln", required_argument, NULL, 'g'},
{"lw", required_argument, NULL, 'h'},
{"rf", required_argument, NULL, 'i'},
{"rd", required_argument, NULL, 'j'},
{"rn", required_argument, NULL, 'k'},
{"rw", required_argument, NULL, 'l'},
{"df", required_argument, NULL, 'm'},
{"dd", required_argument, NULL, 'n'},
{"dn", required_argument, NULL, 'o'},
{"dw", required_argument, NULL, 'p'},
{"file", required_argument, NULL, 'q'},
{NULL, 0, NULL, 0}
};
int ch=0;
while ((ch = getopt_long(argc, argv, "abcdefghijklmnopq:", long_options, NULL)) != -1)
{
// check to see if a single character or long option came through
switch (ch){
case 'a':
cout<<"title";
break;
case 'b':
break;
case 'c':
break;
case 'd':
break;
case 'e':
break;
case 'f':
break;
case 'g':
break;
case 'h':
break;
case 'i':
break;
case 'j':
break;
case 'k':
break;
case 'l':
break;
case 'm':
break;
case 'n':
break;
case 'o':
break;
case 'p':
break;
case 'q':
cout<<"file";
break;
case '?':
cout<<"wrong message"
break;
}
}

Read man getopt http://linux.die.net/man/3/getopt
optstring is a string containing the legitimate option characters. If
such a character is followed by a colon, the option requires an
argument, so getopt() places a pointer to the following text in the
same argv-element, or the text of the following argv-element, in
optarg. Two colons mean an option takes an optional arg; if there is
text in the current argv-element (i.e., in the same word as the option
name itself, for example, "-oarg"), then it is returned in optarg,
otherwise optarg is set to zero.
A sample code:
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
int opt;
while ((opt = getopt (argc, argv, "i:o:")) != -1)
{
switch (opt)
{
case 'i':
printf("Input file: \"%s\"\n", optarg);
break;
case 'o':
printf("Output file: \"%s\"\n", optarg);
break;
}
}
return 0;
}
Here in the optstring is "i:o:" the colon ':' character after each character in the string tells that those options will require an argument. You can find argument as a string in the optarg global var. See manual for detail and more examples.
For more than one character option switches, see the long options getopt_long. Check the manual for examples.
EDIT in response to the single '-' long options:
From the man pages
getopt_long_only() is like getopt_long(), but '-' as well as "--" can indicate a long option. If an option that starts with '-'
(not "--") doesn't match a long option, but does match a short option,
it is parsed as a short option instead.
Check the manual and try it.

To specify that a flag requires an argument, add a ':' right after the flag in the short_opt variable. To use long arguments, use getopt_long().
Here is a quick example program:
#include <getopt.h>
#include <stdio.h>
int main(int argc, char * argv[]);
int main(int argc, char * argv[])
{
int c;
const char * short_opt = "hf:";
struct option long_opt[] =
{
{"help", no_argument, NULL, 'h'},
{"file", required_argument, NULL, 'f'},
{NULL, 0, NULL, 0 }
};
while((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1)
{
switch(c)
{
case -1: /* no more arguments */
case 0: /* long options toggles */
break;
case 'f':
printf("you entered \"%s\"\n", optarg);
break;
case 'h':
printf("Usage: %s [OPTIONS]\n", argv[0]);
printf(" -f file file\n");
printf(" -h, --help print this help and exit\n");
printf("\n");
return(0);
case ':':
case '?':
fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
return(-2);
default:
fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
return(-2);
};
};
return(0);
}

Related

What is the significance of ":" in getopt_long function?

In the getopt_long example here, why are the short options separated by a colon at abc:d:f: and why are abc are grouped together like that?
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
On GNU's page, it is said that
An option character in this string can be followed by a colon (:) to
indicate that it takes a required argument.
For example, xy:zq accepts the options x, y, z, q; y requires an additional argument.

Correct or decent getopts_long usage?

What it the correct usage if I want this behaviour:
$ ./a.out --help for printing help information
$ ./a.out --version for printing the program version
I managed to code this so that it takes the arguments but I don't know a good / correct way to separate the messages since they are the same case.
static struct option long_options[] = {
{"help", no_argument, 0, 0 },
{"version", no_argument, 0, 0 },
{0, 0, 0, 0 }
};
int main(int argc, char *argv[]) {
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
c = getopt_long(argc, argv, "",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
return 0;
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf("option 2 2 %c\n", c);
return 0;
case 'a':
printf("option a\n");
break;
case 'b':
printf("option b\n");
break;
case 'c':
printf("option c with value '%s'\n", optarg);
break;
case 'd':
printf("option d with value '%s'\n", 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");
}
...
Here you have an example:
while (1)
{
int option_index = 0;
static struct option long_options[] = {
{"with_param", required_argument, 0, 'p'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
option = getopt_long(argc, argv, "p:vh",
long_options, &option_index);
if (option == -1)
break;
switch (option) {
case 'p':
{
store_parameter(optarg);
break;
}
case 'v':
{
print_version();
break;
}
case 'h':
{
print_help();
exit(EXIT_SUCCESS);
break;
}
default:
{
fprintf(stderr, "Error (%s): unrecognized option.\n", __FUNCTION__);
print_help();
exit(EXIT_FAILURE);
break;
}
} /* end switch */
}
Notice the string "p:vh" as parameter of getopt_long, which allows you to also use short options. (":" follows options with a required argument)
You need to tell getopt_long the values it has to return:
static struct option long_options[] = {
{"help", no_argument, NULL, 1 },
{"version", no_argument, NULL, 2 },
{0, 0, 0, 0 }
};
Also, you could use "-h" as a synonym to "--help" and "-V" as a synonym to "--version", this would be done this way:
static struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"version", no_argument, NULL, 'V' },
{0, 0, 0, 0 }
};
/* ... */
c = getopt_long(argc, argv, "abc:d:Vh", long_options, &option_index);
/* ... */
case 'h': // instead of case 1:
/* ... */
case 'V': // instead of case 2:
/* ...*/

C - getopt_long() example - tests in case 0

I would like to use getopt_long() correctly and am trying to understand why certain choices were made in the example of getopt_long. (I've copied the full code listing below).
I understand that case 0 occurs when the flag field of the struct is not null (find getopt_long returns 0), but why does the example show retesting long_options[option_index].flag for null in case 0? Isn't this guaranteed given that we are in case 0?
Asked another way: What input could I provide to cause the code to enter case 0 but fail the first if-statement within it? Is printf ("option %s", long_options[option_index].name); unreachable?
25.2.4 Example of Parsing Long Options with getopt_long
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Instead of reporting ‘--verbose’
and ‘--brief’ as they are encountered,
we report the final status resulting from them. */
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
exit (0);
}

c- parsing command line options with multiple arguments with getopt_long

I am new to c programming using command line arguments so despite finding few simmilar posts I am still stuck on this problem.
I need to pass a command line option that have more than 1 argument, for example
./testProgram --command arg1 arg2 arg3
here is my code
static struct option long_options[] = {
{"rdonly", required_argument, 0, 'a'},
{"wronly", required_argument, 0, 'b'},
{"command", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'd'},
{0,0,0,0}
};
c=getopt_long(argc,argv, "", long_options, &option_index);
if(c == -1)
break;
switch(c) {
case 'a':
rdonly(fd,optarg);
break;
case 'b':
wronly(fd,optarg);
break;
case 'c':
command(optind,optarg,argc,argv);
break;
case 'd':
printf("its verbose\n");
break;
default:
printf("WRONG OPTION\n");
}
}
//command function
int command(int optind, char *optarg, int argc, char* argv)
{
printf("Its option command with argument %s\n",optarg);
return 0;
}

getopt_long() and parameters that aren't flags?

I'm trying to use the getopt_long() function for the first time only I'm having problems with arguments that aren't flags. For instance, in my code when a unknown argument is given I want to use it as a input file. When I run this with only a file name it is not printed, if I first use a flag, any flag, then I can print it.
How can I fix this?
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[]) {
int c;
int option_index = 0;
while(42) {
c = getopt_long(argc, argv, "hi:o:a:", long_options,
&option_index);
if(c == -1)
break;
switch(c) {
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag\n");
break;
case 'o': /* --output */
printf("--output flag\n");
break;
case 'a': /* --algorithm */
printf("--algorithm flag \n");
break;
default: /* ??? */
fprintf(stderr, "Invalid option");
return 1;
}
if(optind < argc) {
printf("other arguments: ");
while(optind < argc) {
printf ("%s ", argv[optind]);
optind++;
}
printf("\n");
}
}
return 0;
}
The loop should only contain the switch. Process the residual arguments in a separate (not nested) loop:
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
There is a way to have GNU getopt() and getopt_long() return file name arguments as if they were options with the 'letter' ^A '\1'; use '-' as the first character of the short options string, and trap '\1' in the switch; the value of optarg is the name of the file.
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "-hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
case '\1':
printf("File: %s\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
However, you do need the loop after the argument processing loop in case your cantankerous user types:
program -- abc def
The '--' terminates the while() loop without processing the file name arguments.
It doesn't work because you break out of the outer while loop when getopt_long returns -1 (which indicates that there are no more options).
You need to move the if (optind < argc) block out of the outer while loop; it doesn't belong there anyway. This might be clearer if you wrote that outer while loop as:
while ((c = getopt_long(...)) != -1)
{
switch (c)
{
/* Deal with flags. */
}
}

Resources