I have a problem with situation when I don't write parameters, which I would like to be essential.
while ((choice = getopt(argc, argv, "a:b:")) != -1) {
switch (choice) {
case 'a' :
printf("a %s\n", optarg);
break;
case 'b' :
printf("b %d\n", optarg);
break;
case '?' :
if (optopt == 'a')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
break;
}
}
When I write ./a.out -b test I don't see fprintf() message
I think you'll need to track whether or not option -a has been used yourself - getopt() doesn't have a rich enough spec to capture that information. Something like:
int opt_a_found = 0;
while ((choice = getopt(argc, argv, "a:b:")) != -1) {
switch (choice) {
case 'a' :
opt_a_found = 1;
printf("a %s\n", optarg);
break;
case 'b' :
printf("b %d\n", optarg);
break;
case '?' :
if (optopt == 'a')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
break;
}
}
if (!opt_a_found) {
fprintf (stderr, "Option -a is required.\n");
}
Assuming you mean printf() when wrting fprintf():
I might be wrong, but as far as I remember optarg is char * so you should use %s also in your second printf().
In case you really meant fprintf() please explain why you expect to see it.
because your fprintf is under this condition if (optopt == 'a') which will be false when optopt is 'b'
if (optopt == 'a')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
break;
try
if (optopt == 'a' || optopt == 'b' )
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
break;
Related
I am trying to make it so that getopt can handle certain flags, but I am having trouble implementing the error handling using getopt. I want to prevent duplicate flags such as '-s 1 -s 1', and having too many arguments for a flag '-s 1 2' both of these should exit the program.
int opt; //command flags
while((opt = getopt(argc, argv, "s:f:")) != -1){
switch(opt){
case 's':
printf("%s\n", optarg);
printf("%i\n", optind);
break;
case 'f':
printf("%s\n", optarg);
printf("%i\n", optind);
break;
default:
//unknown command flags
fprintf(stderr, "Usage: fred [ -s symbol-table-file ] [ -f fred-program-file ]\n");
return EXIT_FAILURE;
}
}
Too many arguments (e.g., program -s f1 -f f2 hello). Duplicate flags (e.g., program -s f1 -s f2). Both should exit the program
For each option, you may maintain a flag to see if the option has already been encountered or not. Duplicate options are detected with the help of these flags.
int c, sflag=0, fflag=0;
while( (c=getopt(argc, argv, "s:f:"))!=-1 )
{
switch(c)
{
case 's':
if(sflag!=0)
{
//fprintf(stderr, "\n dup s option");
return 1; //duplicate s option
}
sflag++;
//printf("\ns flag: %s", optarg);
break;
case 'f':
if(fflag!=0)
{
//fprintf(stderr, "\n dup f option");
return 1; //duplicate f option
}
fflag++;
//printf("\nf flag: %s", optarg);
break;
case '?':
if(isprint(optopt))
{
fprintf(stderr, "Unknown option %c", optopt);
}
else
{
fprintf(stderr, "\nUnknown option character x%x", optopt);
}
return 1;
}
}
optind will have the index of the next argv[] which is still to be examined. After all the options have been taken care of, in your program there should be exactly one non-option argument.
So, optind must be equal to argc-1 for a correct usage of the command.
if(optind != argc-1) //exactly one non-option argument is expected
{
fprintf(stderr, "\nInvalid number of arguments.");
return 1;
}
I'm trying to figure out getopt, but I keep getting hung up at the end of the switch statement.
#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 *filename = NULL, *x = NULL;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "hnc:")) != -1)
switch (c)
{
case 'h':
printf("You chose h");
break;
case 'n':
x = optarg;
break;
case 'l':
filename = optarg;
break;
case '?':
if (optopt == 'n' || optopt == 'l')
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 ();
}
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
When I compile this and run a.out -l it does as it should, but when I do a.out -n it does nothing, when it should say "Option n requires an argument."
How can I fix this?
Your optstring "hnc:" says n is a valid argument that doesn't require an argument, while l is not specified at all so the ? case will always be hit. Try using
getopt (argc, argv, "hn:l:")
which says n and l both require arguments.
I am trying out the following C code (saved in file called testgetopt.c):
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
void usage(char *s)
{
fprintf(stderr, "Usage: %s [-d] -i input-TIFF-file -o output-raw-file\n", s);
fprintf(stderr, "Note: -d indicates debugging option\n");
}
int main(int argc, char **argv) {
char c;
size_t i;
char *itext = NULL, *otext = NULL;
FILE *fout;
short debug = 0;
if ((c = getopt(argc, argv, "di:o:")) == EOF) {
usage(argv[0]);
exit(1);
}
while ((c = getopt(argc, argv, "di:o:")) != EOF) {
switch (c) {
case 'd':
debug = 1;
break;
case 'i':
itext = optarg;
break;
case 'o':
otext = optarg;
break;
case '?':
if (optopt == 'i' || optopt == 'o')
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);
usage(argv[0]);
exit(1);
default:
fprintf(stderr, "Both -i and -o are needed\n");
usage(argv[0]);
exit(1);
}
}
printf("debug = %i\n", debug);
if (debug)
printf ("input file = %s, output file = %s\n", itext, otext);
return EXIT_SUCCESS;
}
I compile using:
gcc testgetopt.c
But regardless of whether I include -d or not, I always get debug set at 0. The program should have -d set debug at 1, 0 otherwise.
What is being done wrong?
Here are the examples:
Let us first try with no -d
./a.out -i in.dat -o out.dat
debug = 0
Let us next try with -d included.
./a.out -d -i in.dat -o out.dat
debug = 0
Thank you in advance for any help and suggestions!
The problem is that you are calling getopt as a sanity check and then not using its result when it succeeds. That means the first option is always discarded. You can easily verify this by putting -d as a non-first option:
$ ./a.out -i in.dat -o out.dat -d
debug = 1
input file = (null), output file = out.dat
You can see that the -d did take effect this time but the first argument, -i, is not set.
There are several ways to fix this. The recommended way (IMHO) is to remove the first getopt call. Then change the sanity check to verify the actual options. That is, there should be code after the getopt loop which verifies that all mandatory options have been provided.
For example:
int main(int argc, char **argv) {
char c;
size_t i;
char *itext = NULL, *otext = NULL;
FILE *fout;
short debug = 0;
/* REMOVED THIS BLOCK OF CODE
if ((c = getopt(argc, argv, "di:o:")) == EOF) {
usage(argv[0]);
exit(1);
}
*/
while ((c = getopt(argc, argv, "di:o:")) != EOF) {
switch (c) {
case 'd':
debug = 1;
break;
case 'i':
itext = optarg;
break;
case 'o':
otext = optarg;
break;
case '?':
if (optopt == 'i' || optopt == 'o')
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);
usage(argv[0]);
exit(1);
default:
fprintf(stderr, "Both -i and -o are needed\n");
usage(argv[0]);
exit(1);
}
}
/* ADD SOME ARGUMENT SANITY CHECKS */
if (!itext || !otext) {
printf("Missing mandatory arguments\n");
exit(1);
}
printf("debug = %i\n", debug);
if (debug)
printf ("input file = %s, output file = %s\n", itext, otext);
return EXIT_SUCCESS;
}
Because you are calling getopt twice, you need to reset optind = 1; between the calls.
I'm writing a program which needs to be able to parse command line arguments, and I would like to use getopt. I have no issues with getting it to work with the regular arguments, however I need it to be able to pick up an argument that is not specified with a flag. For example if I ran: ./prog -a a1 -b b2 foo I would need to be able to get a1,a2 and foo. Right now it handles everything but the unspecified argument. Here is what I have:
while((command = getopt(argc, argv, "a:b:c:")) != -1){
switch(command){
case('a'):
input = fopen(optarg, "r");
if(input == NULL){
printf("Error opening file, exiting\n");
exit( -1 );
}
break;
case('b'):
output = fopen(optarg, "r");
if(output == NULL){
printf("Error opening file, exiting\n");
exit( -1 );
}
break;
case('c'):
keyword = optarg;
break;
case('?'):
if((optopt == 'a') || (optopt == 'b') || (optopt == 'c')){
fprintf(stderr, "Error, no argument specified for -%c\n", optopt);
exit( -1 );
} else
extra = optarg; // This is how I thought I needed to do it
break;
default:
fprintf(stderr,"Error in getopt");
break;
}// switch
} // while
Thanks!
After the loop, the optind variable will be the index to the next non-option argument.
So do e.g.
if (optind < argc)
{
printf("Have extra arguments: ");
for (int i = optind; i < argc; ++i)
printf("%s ", argv[i]);
printf("\n");
}
to list all non-option arguments.
here is my question. I want to be able to support this in my application:
./cipher [-devh] [-p PASSWD] infile outfile
I managed to get the [-devh] supported, but I don't know how to get [-p PASSWORD] supported. Of course I can manually check for argc being 2 and then have a bunch of flags but I prefer using getopts and think it would be easier. Here is my code for the [-devh] how can I extend it so it can support them remaining?
while ( (c = getopt(argc, argv, "devh")) != -1) {
switch (c) {
case 'd':
printf ("option d\n");
dopt = 1;
break;
case 'e':
printf ("option e\n");
eopt = 1;
break;
case 'v':
printf ("option v\n");
vopt = 1;
break;
case 'h':
printf ("option h\n");
hopt = 1;
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
Taken directly from the GNU C Library Reference page on getopt:
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();
}
c here is the argument that takes an optional parameter, so this is probably the syntax you were looking for.
What I understand getopt does is loop through the given arguments, parsing them one at a time. So when it gets to the option c (in your case p) where a second argument is required, it is stored in optarg. This is assigned to a variable of your choice (here cvalue) for later processing.