Muddyblack k
Muddyblack k

Reputation: 252

Cpp: How can I get the long-name of an option using getopt.h

Hey I have a function to check the given arguments for my program.

I want to get the long-name of the given users argument. Problem is currently he gives me weird high numbers example 32758 while my struct has only 9 elements...

I have to use it for university otherwise I would use the boost library....

#include <iostream>
#include <getopt.h>

int main(int argc, char *argv[])
{
    // Standard directories
    std::string outputDir = "PROJECT_PATH\\output\\"; /**< Output directory */

    // Options
    const struct option longOptions[3] = {
        {"output-dir", required_argument, nullptr, 'O'},
        {"help", no_argument, nullptr, 'h'},
        {nullptr, 0, nullptr, 0}};

    int opt;
    int option_index;
    while ((opt = getopt_long(argc, argv, "O:h", longOptions, &option_index)) != -1)
    {
        std::cout << "Long option index: " << option_index << std::endl;
        std::cout << "Option name: " << longOptions[option_index].name << std::endl;
        switch (opt)
        {
        case 'O':
            outputDir = optarg;
            break;
        case 'h':
            // printHelpText();
            exit(0);
        case '?':
            if ((optopt == 'O' || optopt == 'h'))
            {
                std::cout << "OK ... option '-" << static_cast<char>(optopt) << "' without argument"
                          << std::endl;
                exit(1);
            }
            else if (isprint(optopt))
            {
                std::cerr << "ERR ... Unknown option -" << static_cast<char>(optopt) << std::endl;
                exit(-1);
            }
            else
            {
                std::cerr << "ERR ... Unknown option character \\x" << static_cast<char>(optopt) << std::endl;
                exit(-1);
            }
        }
    }
    return 0;
}

Upvotes: 0

Views: 317

Answers (2)

Muddyblack k
Muddyblack k

Reputation: 252

Okay well you have to differ between the short and long options. And if using an option that requires an argument you have to add one to get a result.

std::cout << "Long option index: " << option_index << std::endl;
if (option_index > options_amount - 1)
{
    std::cout << static_cast<char>(optopt) << std::endl;
}
else
{
    std::cout << "Option name: " << longOptions[option_index].name << std::endl;
}

Here if you forget to add the path for --output-dir

mini.exe --output-dir
option requires an argument -- output-dir
Long option index: 32758
O
OK ... option '-O' without argument

With argument if works fine:

mini.exe --output-dir ./hello
Long option index: 0   
Option name: output-dir

Upvotes: 0

Erik Elmgren
Erik Elmgren

Reputation: 780

Looking at the documentation and source code for getopt_long() it does not seem to calculate the index of the long option if it parses a short option so you are seeing uninitialized data in option_index.

It will only be filled with data if a long option is actually present.

If you need this value, write your own loop through the array looking for the returned short option.

Here is a link to getopt_long() in android copied from BSD. I would assume this is the same on all other platforms.

https://android.googlesource.com/platform/bionic/+/a27d2baa/libc/unistd/getopt_long.c

Upvotes: 4

Related Questions