Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using getopt for required arguments

I currently have code that looks like this:

while (( flags = getopt(argc, argv, "abc")) != -1){
    switch(flags){
    case 'a':
        dflag = 1;
        break;
    case 'b':
        rflag = 1;
        break;
    case 'c':
        cflag = 1;
        break;
    }
}

The problem is I wanted to include something like testprogram -c -d 1

Where c is required to handle the -d, without -c, testprogram -d 1 will just run without arguments.

I tried a large variety of things and I just can't seem to get this to work.

Any help would be appreciated.

like image 592
WToa Avatar asked Oct 20 '12 05:10

WToa


People also ask

What is getopt used for?

Getopt is a C library function used to parse command-line options of the Unix/POSIX style. It is a part of the POSIX specification, and is universal to Unix-like systems. It is also the name of a Unix program for parsing command line arguments in shell scripts.

How do you write getopt?

The getopt() function is a builtin function in C and is used to parse command line arguments. Syntax: getopt(int argc, char *const argv[], const char *optstring) optstring is simply a list of characters, each representing a single character option.

Which of these is a difference between getopt and getopts?

getopt vs getopts The main differences between getopts and getopt are as follows: getopt does not handle empty flag arguments well; getopts does. getopts is included in the Bourne shell and Bash; getopt needs to be installed separately.

What does getopt do in Bash?

On Unix-like operating systems, getopts is a builtin command of the Bash shell. It parses command options and arguments, such as those passed to a shell script.


1 Answers

I think there are two options available to you, one of which will work and one of which may or may not work.

The 'may or may not work' option would be exemplified by:

char *opts = "abc";
char *opts_d = "abcd:";

while ((opt = getopt(argc, argv, opts)) != -1)
{
    switch (opt)
    {
    case 'a':
        aflag = 1;
        break;
    case 'b':
        bflag = 1;
        break;
    case 'c':
        cflag = 1;
        opts = opts_d;
        break;
    case 'd':
        dflag = 1;
        dvalue = optarg;
        break;
    default:
        ...error handling...
        break;
    }
}

I'm not sure whether there's anything that prohibits you from changing the list of valid options on successive calls to [getopt()][1], but I do know it is not normally done to change the options as you go. So, treat with caution. Note that if the -c option is never found, the opt value of d will never be returned by getopt(), so that code will not be executed otherwise. Note that if the user enters a -d option before the -c, getopt() will report an invalid option when it processes the -d. You can control the error reporting; you would probably have to. (The optopt variable contains the actual option letter that was encountered as invalid.)

The 'will work' option is:

while ((opt = getopt(argc, argv, "abcd:")) != -1)
{
    switch (opt)
    {
    case 'a':
        aflag = 1;
        break;
    case 'b':
        bflag = 1;
        break;
    case 'c':
        cflag = 1;
        break;
    case 'd':
        if (cflag == 0)
            ...report error about must use -c option before -d option...
        dflag = 1;
        dvalue = optarg;
        break;
    default:
        ...error handling...
        break;
    }
}
like image 133
Jonathan Leffler Avatar answered Oct 05 '22 22:10

Jonathan Leffler