211 votes

Analyse des arguments de la ligne de commande en C++ ?

Quelle est la meilleure façon d'analyser les arguments de la ligne de commande en C++ si le programme est spécifié pour être exécuté comme ceci :

prog [-abc] [input [output]]

Existe-t-il un moyen de le faire intégré à la bibliothèque standard, ou dois-je écrire mon propre code ?


En rapport :

243voto

iain Points 4876

Les suggestions pour boost::program_options et GNU getopt en sont de bons exemples.

Cependant, pour les options simples de la ligne de commande, j'ai tendance à utiliser std::find

Par exemple, pour lire le nom d'un fichier après un -f argument de ligne de commande. Vous pouvez aussi simplement détecter si une option d'un seul mot a été passée comme -h pour de l'aide.

#include <algorithm>

char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
    char ** itr = std::find(begin, end, option);
    if (itr != end && ++itr != end)
    {
        return *itr;
    }
    return 0;
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
    return std::find(begin, end, option) != end;
}

int main(int argc, char * argv[])
{
    if(cmdOptionExists(argv, argv+argc, "-h"))
    {
        // Do stuff
    }

    char * filename = getCmdOption(argv, argv + argc, "-f");

    if (filename)
    {
        // Do interesting things
        // ...
    }

    return 0;
}

Une chose à laquelle il faut faire attention avec cette approche : vous devez utiliser std::strings comme valeur pour std::find, sinon la vérification de l'égalité est effectuée sur les valeurs des pointeurs.

82voto

Options du programme Boost. devrait faire l'affaire

58voto

naufraghi Points 533

Je peux suggérer Bibliothèque d'analyseur de ligne de commande C++ modélisée l'API est très simple et (cité sur le site) :

la bibliothèque est entièrement mise en œuvre dans des fichiers d'en-tête, ce qui facilite l'utilisation de la bibliothèque. facile à utiliser et à distribuer avec d'autres logiciels. Elle est sous licence MIT pour une distribution libre de tout souci.

Il s'agit d'un exemple tiré du manuel, coloré ici pour plus de simplicité :

#include <string>
#include <iostream>
#include <algorithm>
#include <tclap/CmdLine.h>

int main(int argc, char** argv)
{

    // Wrap everything in a try block.  Do this every time,
    // because exceptions will be thrown for problems.
    try {

    // Define the command line object, and insert a message
    // that describes the program. The "Command description message"
    // is printed last in the help text. The second argument is the
    // delimiter (usually space) and the last one is the version number.
    // The CmdLine object parses the argv array based on the Arg objects
    // that it contains.
    TCLAP::CmdLine cmd("Command description message", ' ', "0.9");

    // Define a value argument and add it to the command line.
    // A value arg defines a flag and a type of value that it expects,
    // such as "-n Bishop".
    TCLAP::ValueArg<std::string> nameArg("n","name","Name to print",true,"homer","string");

    // Add the argument nameArg to the CmdLine object. The CmdLine object
    // uses this Arg to parse the command line.
    cmd.add( nameArg );

    // Define a switch and add it to the command line.
    // A switch arg is a boolean argument and only defines a flag that
    // indicates true or false.  In this example the SwitchArg adds itself
    // to the CmdLine object as part of the constructor.  This eliminates
    // the need to call the cmd.add() method.  All args have support in
    // their constructors to add themselves directly to the CmdLine object.
    // It doesn't matter which idiom you choose, they accomplish the same thing.
    TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false);

    // Parse the argv array.
    cmd.parse( argc, argv );

    // Get the value parsed by each arg.
    std::string name = nameArg.getValue();
    bool reverseName = reverseSwitch.getValue();

    // Do what you intend.
    if ( reverseName )
    {
            std::reverse(name.begin(),name.end());
            std::cout << "My name (spelled backwards) is: " << name << std::endl;
    }
    else
            std::cout << "My name is: " << name << std::endl;

    } catch (TCLAP::ArgException &e)  // catch any exceptions
    { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; }
}

33voto

Matthew Flaschen Points 131723

Vous pouvez utiliser GNU Getopt (LGPL) ou l'un des différents ports C++, tels que getoptpp (GPL).

23voto

MSB Points 121

Une autre alternative est The Lean Mean C++ Option Parser :

http://optionparser.sourceforge.net

Il s'agit d'une bibliothèque d'en-tête uniquement (un seul fichier d'en-tête, en fait) et, contrairement à toutes les autres suggestions, elle est également indépendante, c'est-à-dire qu'elle n'a aucune dépendance. En particulier, elle ne dépend pas de la STL. Il n'utilise même pas les exceptions ou quoi que ce soit d'autre qui nécessite un support de la bibliothèque. Cela signifie qu'il peut être lié à du simple C ou à d'autres langages sans introduire de bibliothèques "étrangères".

Comme boost::program_options, son API offre un accès direct et pratique aux options, c'est-à-dire que vous pouvez écrire un code comme celui-ci

if (options[HELP]) ... ;

y

int verbosity = options[VERBOSE].count() ;

Contrairement à boost::program_options, ceci utilise simplement un tableau indexé avec un enum (fourni par l'utilisateur). Cela offre la commodité d'un conteneur associatif sans le poids.

Il est bien documenté et possède une licence conviviale (MIT).

TLMC++OP inclut un formateur agréable pour les messages d'utilisation qui peut faire le retour à la ligne et l'alignement des colonnes, ce qui est utile si vous localisez votre programme, car cela garantit que la sortie sera bonne même dans les langues qui ont des messages plus longs. Cela vous évite également de devoir formater manuellement vos messages d'utilisation pour 80 colonnes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X