HOWTO · C++
Handhabung von Argumenten mit getopt in C++
Dieser Artikel demonstriert die Verwendung der getopt()-Funktion in C++ zum Umgang mit Argumenten.
Auf dieser Seite
Um kurze Befehlszeilenoptionen in C++ zu verarbeiten, rufen Sie die POSIX-Funktion getopt mit argc, argv und einem optstring auf, der jede Option und ihren möglichen Wert deklariert. Lesen Sie Optionswerte über optarg aus und greifen Sie mit optind auf verbleibende positionale Argumente zu. Wenn das Programm auch lange Optionen wie --help benötigt, verwenden Sie getopt_long.
getopt in C++ verstehen
getopt ist von POSIX spezifiziert und auf Unix-ähnlichen Systemen häufig verfügbar; die Funktion gehört nicht zur C++-Standardbibliothek. Binden Sie <unistd.h> auf Systemen ein, die diese Headerdatei bereitstellen. Die Funktion liest argc und argv und gibt jeweils eine erkannte Option zurück. Eine kurze Option besteht aus einem einzelnen Zeichen, etwa -v; ein Wert kann auf eine Option folgen, wie bei -o report.txt. getopt verarbeitet nur kurze Optionen. Für ein Token wie --output benötigen Sie daher eine separate Schnittstelle. Die POSIX-Spezifikation für getopt beschreibt die Schnittstelle und die Regeln für Rückgabewerte.
Die Verfügbarkeit und Einzelheiten wie die Reihenfolge der Argumente unterscheiden sich je nach Plattform. Wenn Portabilität wichtig ist, prüfen Sie die Headerdateien und die Dokumentation des Zielsystems. Die folgenden Beispiele verwenden POSIX-Schnittstellen und einen C++-Compiler wie g++.
Kurze Optionen definieren und Argumente verarbeiten
Ein optstring listet die akzeptierten Optionen mit jeweils einem Zeichen auf. Ein Zeichen, auf das : folgt, kennzeichnet eine Option mit erforderlichem Wert; getopt stellt diesen über optarg bereit. Im Beispiel ist v eine Schalteroption ohne Wert, während o: einen Ausgabepfad entgegennimmt. Das Programm gibt außerdem den positionalen Wert aus, der nach der Verarbeitung übrig bleibt. Speichern Sie den Quelltext als main.cpp. Auf einem POSIX-ähnlichen System können Sie ihn mit g++ -std=c++17 -Wall -Wextra -pedantic main.cpp -o app kompilieren.
Führen Sie das Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#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
Das feste Argumentarray macht das Beispiel eigenständig. In einem regulären Programm übergeben Sie stattdessen die Werte für argc und argv, die main erhalten hat. Das optstring :vo: beginnt mit einem Doppelpunkt, damit sich ein fehlender erforderlicher Wert von einer unbekannten Option unterscheiden lässt: v benötigt keinen Wert, o: dagegen schon. Sowohl -o report.txt als auch -oreport.txt werden üblicherweise akzeptiert. optarg zeigt auf den Wert der gerade verarbeiteten Option. In unveränderten Code- und Ausgabeblöcken bleiben enthaltene Bezeichnungen auf Englisch.
Fehler und verbleibende Argumente behandeln
Wenn die Verarbeitung der Optionen abgeschlossen ist, gibt getopt normalerweise -1 zurück. Bei einer unbekannten Option wird ? zurückgegeben. Auch bei einem fehlenden Wert für eine Option, die einen Wert verlangt, lautet der Rückgabewert ?, sofern optstring nicht mit : beginnt. Mit diesem führenden Doppelpunkt wird bei einem fehlenden Wert : zurückgegeben; eine unbekannte Option liefert weiterhin ?. optopt gibt das betroffene Optionszeichen an. Das Beispiel mit kurzen Optionen verwendet diese Konvention und setzt opterr auf 0. Dadurch gibt der switch für jeden der beiden Fehler eine Diagnose aus und liefert einen Status ungleich null zurück. Fehlt der führende Doppelpunkt, verwenden beide Fehlerfälle ?; allein anhand des Rückgabewerts kann der Aufrufer sie dann nicht unterscheiden. Dieselbe Einstellung von opterr unterdrückt außerdem die Fehlermeldung der Bibliothek.
Nach der Verarbeitung enthält optind den Index des ersten verbleibenden Arguments. Durchlaufen Sie die Argumente von optind bis argc, um Dateinamen oder andere positionale Werte zu verarbeiten. Manche Implementierungen ordnen Optionen und Operanden während der Verarbeitung um; andere brechen beim ersten Operanden ab oder bieten abweichende Steuerungsmöglichkeiten für die Reihenfolge. Gehen Sie nicht davon aus, dass jede Plattform gemischte Optionen und positionale Argumente gleich behandelt.
Lange Optionen mit getopt_long verarbeiten
Auf Systemen, die die GNU-Erweiterung <getopt.h> bereitstellen, erkennt getopt_long neben kurzen auch lange Optionsnamen. Die Funktion ist weder von POSIX spezifiziert noch Teil der C++-Standardbibliothek. Die Dokumentation zu getopt_long im GNU-C-Bibliothekshandbuch beschreibt die Erweiterung und ihre Tabelle mit struct option. Jeder Tabelleneintrag enthält einen langen Namen, die Angabe, ob die Option keinen, einen erforderlichen oder einen optionalen Wert akzeptiert, sowie den Wert, den der switch erhält. Ein abschließender Eintrag mit einem Nullnamen beendet die Tabelle. Dieses eigenständige Beispiel akzeptiert --help und --output FILE sowie die entsprechenden Kurzformen:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#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
Für ein echtes Befehlszeilenprogramm verwenden Sie argc und argv aus main und kompilieren den Quelltext auf einem System mit getopt_long beispielsweise mit g++ -std=c++17 -Wall -Wextra -pedantic main.cpp -o app. Die festgelegte Eingabe des Beispiels wählt den Hilfezweig. Ersetzen Sie sie durch --output report.txt input.csv, um einen Ausgabepfad anzugeben und input.csv zur Verarbeitung über optind übrig zu lassen. Prüfen Sie die Zielplattform, bevor Sie sich auf diese Erweiterung verlassen.