HOWTO · C++

How to Handle Arguments Using getopt in C++

This article demonstrates how to use the getopt function in C++ to handle command-line arguments effectively. Learn to parse options, manage required arguments, and create a user-friendly interface for your applications. With clear examples and detailed explanations, you'll enhance your C++ programming skills and improve usability.

On this page

To parse short command-line options in C++, call the POSIX getopt function with argc, argv, and an optstring that declares each option and whether it needs a value. Use optarg for option values and optind to reach remaining positional arguments; use getopt_long when the program also needs long options such as --help.

Understanding getopt in C++

getopt is specified by POSIX and is commonly available on Unix-like systems; it is not part of the C++ standard library. Include <unistd.h> on systems that provide it. The function reads argc and argv, returning one parsed option at a time. A short option is a single character such as -v; a value can follow an option, as in -o report.txt. getopt parses short options only, so a token such as --output needs a separate interface. See the POSIX getopt specification for its interface and return-value rules.

Availability and details such as argument ordering vary by platform. Confirm the target system’s headers and documentation when portability matters. The examples below use POSIX interfaces and a C++ compiler such as g++.

Define short options and parse arguments

An optstring lists the accepted one-character options. A character followed by : requires a value, which getopt exposes through optarg. In the example, v is a flag and o: accepts an output path. The program also prints the positional value left after parsing. Save it as main.cpp; on a POSIX-like system, compile it with g++ -std=c++17 -Wall -Wextra -pedantic main.cpp -o app.

Run this example:

#include <iostream>
#include <unistd.h>

int main() {
    char app[] = "app";
    char verbose_option[] = "-v";
    char output_option[] = "-o";
    char output_path[] = "report.txt";
    char input_path[] = "input.csv";
    char* arguments[] = {app, verbose_option, output_option, output_path, input_path, nullptr};
    int argument_count = 5;
    bool verbose = false;
    const char* output = "result.txt";
    int option = 0;

    opterr = 0;
    while ((option = getopt(argument_count, arguments, ":vo:")) != -1) {
        switch (option) {
            case 'v':
                verbose = true;
                break;
            case 'o':
                output = optarg;
                break;
            case ':':
                std::cerr << "Option -" << static_cast<char>(optopt) << " requires a value\n";
                return 2;
            case '?':
            default:
                std::cerr << "Unknown option: -" << static_cast<char>(optopt) << '\n';
                return 2;
        }
    }

    std::cout << "verbose=" << (verbose ? "on" : "off") << '\n';
    std::cout << "output=" << output << '\n';
    for (int i = optind; i < argument_count; ++i) {
        std::cout << "input=" << arguments[i] << '\n';
    }
}
verbose=on
output=report.txt
input=input.csv

The fixed argument array makes the example self-contained; in a regular program, pass the argc and argv received by main. The optstring :vo: uses a leading colon to distinguish a missing required value from an unknown option; v takes no value and o: requires one. Both -o report.txt and -oreport.txt are commonly accepted spellings. optarg points to the value associated with the option being processed.

Handle errors and remaining arguments

Normally, getopt returns -1 when option parsing is complete. For an unrecognized option it returns ?; for a missing value on a required option it also returns ? unless the optstring begins with :. With that leading-colon convention, a missing value returns : while an unrecognized option still returns ?. optopt identifies the option character involved. The short-option example uses this convention and sets opterr to 0, so its switch prints one diagnostic and returns a nonzero status for either error. If the leading colon is omitted, both conditions use ? and the caller cannot distinguish them by the return value alone. The same opterr setting suppresses the library’s own error message.

After parsing, optind is the index of the first remaining argument. Iterate from optind to argc to handle file names or other positional values. Some implementations permute options and operands during parsing; others stop at the first operand or provide different ordering controls. Do not assume every platform treats interspersed options and positional arguments the same way.

Use getopt_long for long options

On systems that provide the GNU <getopt.h> extension, getopt_long recognizes long names as well as short options; it is not specified by POSIX or the C++ standard library. The GNU C Library manual’s getopt_long documentation describes this extension and its struct option table. Each entry supplies a long name, whether it accepts no value or a required or optional value, and the value returned to the switch. A final entry with a null name ends the table. This self-contained illustration accepts --help and --output FILE, plus their short forms:

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

int main() {
    char app[] = "app";
    char help_option[] = "--help";
    char* arguments[] = {app, help_option, nullptr};
    int argument_count = 2;
    const option long_options[] = {
        {"help", no_argument, nullptr, 'h'},
        {"output", required_argument, nullptr, 'o'},
        {nullptr, 0, nullptr, 0}
    };
    const char* output = "result.txt";
    int option = 0;

    opterr = 0;
    while ((option = getopt_long(argument_count, arguments, ":ho:", long_options, nullptr)) != -1) {
        switch (option) {
            case 'h':
                std::cout << "Usage: app [-h] [-o FILE] [FILE...]\n";
                break;
            case 'o':
                output = optarg;
                break;
            case ':':
                std::cerr << "Option requires a value\n";
                return 2;
            case '?':
            default:
                std::cerr << "Unknown option\n";
                return 2;
        }
    }

    std::cout << "output=" << output << '\n';
    for (int i = optind; i < argument_count; ++i) {
        std::cout << "input=" << arguments[i] << '\n';
    }
}
Usage: app [-h] [-o FILE] [FILE...]
output=result.txt

For an actual command-line program, use the argc and argv from main and compile with g++ -std=c++17 -Wall -Wextra -pedantic main.cpp -o app on a system that supplies getopt_long. The example’s fixed input selects the help path; replace it with --output report.txt input.csv to select an output path and leave input.csv for handling through optind. Check the target platform before relying on this extension.