Getopt Optional Arguments?

Getopt Optional Arguments?

I have a program where you enter an option -d and then whether or not you supply a non-optional argument after the option, do something.
Heres my code:

#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>

#define OPT_LIST "d::" 

int main (int argc, char *argv[])
{
    int c;
    char string[] = "blah";

    while ((c = getopt (argc, argv, OPT_LIST)) != -1)
    {
        switch (c)
        {
            case 'd':
                    printf("%s\n", optarg);
                    break;

            case '?':
                fprintf(stderr, "invalid option\n");
                exit(EXIT_FAILURE);
        }   
    }
}

So if you enter a non-optional argument after the option, it prints the argument. But I want it to print out the char "string" if the user doesn't supply a non-optional argument (this is why I put the double colon in the OPT_LIST). But I'm not sure how to do this so any help would be greatly appreciated.

Heres what happens when I run the program:

user:desktop shaun$ ./arg -d hello
hello
user:desktop shaun$ ./arg -d 
./arg: option requires an argument -- d
invalid option

I'm running a Mac with OS X using C language.

5

4 Answers

The "optional value of an option" feature is only a GNU libc extension, not required by POSIX, and is probably simply unimplemented by the libc shipped with Mac OS X.

The options argument is a string that specifies the option characters that are valid for this program. An option character in this string can be followed by a colon (‘:’) to indicate that it takes a required argument. If an option character is followed by two colons (‘::’), its argument is optional; this is a GNU extension.

In fact, POSIX.1-2008, section 12.2, "Utility Syntax Guidelines", explicitly forbids this feature:

Guideline 7: Option-arguments should not be optional.

According to the getopt documentation, it will return : if an option with an argument does not have one. It also sets optopt with the matching argument.

Therefore, use:

int main (int argc, char *argv[])
{
    int c;
    while ((c = getopt (argc, argv, ":d:f:")) != -1)
    {
        switch (c)
        {
            case 'd':
            case 'f':
                printf("option -%c with argument '%s'\n", c, optarg);
                break;
            case ':':
                switch (optopt)
                {
                case 'd':
                    printf("option -%c with default argument value\n", optopt);
                    break;
                default:
                    fprintf(stderr, "option -%c is missing a required argument\n", optopt);
                    return EXIT_FAILURE;
                }
                break;
            case '?':
                fprintf(stderr, "invalid option: -%c\n", optopt);
                return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}
2

Maybe I'm misunderstanding the question. I'm reading it as though the user wants to over ride getopt's default error handling. If that is the case, shouldn't there be a : in the beginning of their OPT_LIST? I think the code above is good, however, I think it will still print

./arg: option requires an argument -- d

To surpress that, don't we need a : at the beginning of the OPT_LIST? For example, changing this:

while ((c = getopt (argc, argv, "d:f:")) != -1)

to this:

while ((c = getopt (argc, argv, ":d:f:")) != -1)

Correct me if I'm wrong.

Try this solution. It works for me. Consider option 'z' as option with optional argument.

int c;
opterr = 0; //if (opterr != 0) (which it is by default), getopt() prints its own error messages for invalid options and for missing option arguments.
while ((c = getopt (argc, argv, "x:y:z:")) != -1)
    switch (c)
    {
        case 'x':
        case 'y':
        case 'z':
            printf("OK ... option -%c with argument '%s'\n", c, optarg);
            break;

        case '?':
            if (optopt == 'x' || optopt == 'y')
                fprintf (stderr, "ERR ... Option -%c requires an argument.\n", optopt);
            else if(optopt == 'z' && isprint(optopt))
            {
                printf("OK ... option '-z' without argument \n");
                break;
            }
            else if (isprint (optopt))
                fprintf (stderr, "ERR ... Unknown option `-%c'.\n", optopt);
            else
                fprintf (stderr, "ERR ... Unknown option character `\\x%x'.\n", optopt);
            return -1;
        default: ;
  }

Here are some examples:

./prog -x
    ERR ... Option -x requires an argument.

./prog -y
    ERR ... Option -x requires an argument.

./prog -z
    OK ... option '-z' without argument

./prog -x aaa
    OK ... option -x with argument 'aaa'

./prog -y bbb -x aaa
    OK ... option -y with argument 'bbb'
    OK ... option -x with argument 'aaa'

./prog -x aaa -y bbb -z
    OK ... option -x with argument 'aaa'
    OK ... option -y with argument 'bbb'
    OK ... option '-z' without argument

./prog -x aaa -y bbb -z ccc
    OK ... option -x with argument 'aaa'
    OK ... option -y with argument 'bbb'
    OK ... option -z with argument 'ccc'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.