Comment analyser les Arguments en ligne de commande en C++? [dupliquer]

possibilité de dupliquer:

Quels sont les paramètres des bibliothèques d'analyseur pour C++?

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

prog [-abc] [input [output]]

y a-t-il une bibliothèque à STL pour faire ça?


Related:

  • analyse des arguments en ligne de commande dans une application unicode c++
158
demandé sur Community 2009-05-15 00:46:44

10 réponses

coup de pouce.Program_options devrait faire l'affaire

79
répondu ChrisN 2013-05-21 21:22:25

les suggestions pour boost::program_options et GNU getopt sont bonnes.

Cependant, pour les options de ligne de commande simples 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 à un seul mot a été passée comme -h pour obtenir 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;
}

sur la chose à surveiller avec cette approche, vous devez utiliser std::strings comme le valeur pour std:: find otherwise le contrôle d'égalité est effectué sur les valeurs du pointeur.


j'espère qu'il est correct d'éditer cette réponse au lieu d'en ajouter une nouvelle, car elle est basée sur la réponse originale. J'ai légèrement réécrit les fonctions et les ai encapsulées dans une classe, donc voici le code. J'ai pensé qu'il pourrait être utile de l'utiliser de cette façon:

class InputParser{
    public:
        InputParser (int &argc, char **argv){
            for (int i=1; i < argc; ++i)
                this->tokens.push_back(std::string(argv[i]));
        }
        /// @author iain
        const std::string& getCmdOption(const std::string &option) const{
            std::vector<std::string>::const_iterator itr;
            itr =  std::find(this->tokens.begin(), this->tokens.end(), option);
            if (itr != this->tokens.end() && ++itr != this->tokens.end()){
                return *itr;
            }
            static const std::string empty_string("");
            return empty_string;
        }
        /// @author iain
        bool cmdOptionExists(const std::string &option) const{
            return std::find(this->tokens.begin(), this->tokens.end(), option)
                   != this->tokens.end();
        }
    private:
        std::vector <std::string> tokens;
};

int main(int argc, char **argv){
    InputParser input(argc, argv);
    if(input.cmdOptionExists("-h")){
        // Do stuff
    }
    const std::string &filename = input.getCmdOption("-f");
    if (!filename.empty()){
        // Do interesting things ...
    }
    return 0;
}
196
répondu iain 2018-03-16 13:17:02

je peux suggérer Templatized C++ de la Ligne de Commande Parser (certains fourches sur GitHub sont disponibles), de l'API est très simple et (cité sur le site):

la Bibliothèque est implémentée entièrement dans les fichiers d'en-tête ce qui rend facile à utiliser et distribuer avec d'autres logiciels. Il est autorisé par le MIT Licence pour distribution sans soucis.

C'est un exemple du manuel, coloré ici pour la 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; }
}
51
répondu naufraghi 2015-09-28 15:14:13

vous pouvez utiliser GNU GetOpt (LGPL) ou l'un des différents ports C++, comme getoptpp (GPL).

un exemple simple utilisant GetOpt de ce que vous voulez ( prog [-ab] input ) est le suivant:

// C Libraries:
#include <string>
#include <iostream>
#include <unistd.h>

// Namespaces:
using namespace std;

int main(int argc, char** argv) {
    int opt;
    string input = "";
    bool flagA = false;
    bool flagB = false;

    // Retrieve the (non-option) argument:
    if ( (argc <= 1) || (argv[argc-1] == NULL) || (argv[argc-1][0] == '-') ) {  // there is NO input...
        cerr << "No argument provided!" << endl;
        //return 1;
    }
    else {  // there is an input...
        input = argv[argc-1];
    }

    // Debug:
    cout << "input = " << input << endl;

    // Shut GetOpt error messages down (return '?'): 
    opterr = 0;

    // Retrieve the options:
    while ( (opt = getopt(argc, argv, "ab")) != -1 ) {  // for each option...
        switch ( opt ) {
            case 'a':
                    flagA = true;
                break;
            case 'b':
                    flagB = true;
                break;
            case '?':  // unknown option...
                    cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
                break;
        }
    }

    // Debug:
    cout << "flagA = " << flagA << endl;
    cout << "flagB = " << flagB << endl;

    return 0;
}
31
répondu Matthew Flaschen 2014-09-06 19:04:50

une autre alternative est le lean Mean c++ Option Parser:

http://optionparser.sourceforge.net

c'est une bibliothèque d'en-tête seulement (juste un seul fichier d'en-tête, en fait) et contrairement à toutes les autres suggestions il est aussi autonome, c'est-à-dire sans aucune dépendance. En particulier, il n'y a pas de dépendance au STL. Il n'utilise même pas d'exceptions ou quoi que ce soit d'autre qui nécessite un support de bibliothèque. Cela signifie qu'il peut être relié avec le C simple ou d'autres langues sans introduire des 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 du code comme ceci

si (options[AIDE]) ... ;

et

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

contrairement à boost:: program_options cependant, il s'agit simplement d'utiliser un tableau indexé avec un enum (fourni par l'utilisateur). Cette offre la commodité d'un conteneur associatif sans le poids.

il est bien documenté et a une licence conviviale (MIT).

TLMC++OP comprend une belle formateur pour l'utilisation de messages qui peuvent le faire l'enroulement de ligne et l'alignement de colonne qui est utile si vous localisez votre programme, parce qu'il assure que la sortie sera bonne même dans les langues qui ont des messages plus longs. Il vous épargne également la nuisance de formater manuellement votre utilisation pour 80 colonnes.

21
répondu MSB 2012-01-24 18:12:37
for (int i = 1; i < argc; i++) {

    if (strcmp(argv[i],"-i")==0) {
        filename = argv[i+1];
        printf("filename: %s",filename);
    } else if (strcmp(argv[i],"-c")==0) {
        convergence = atoi(argv[i + 1]);
        printf("\nconvergence: %d",convergence);
    } else if (strcmp(argv[i],"-a")==0) {
        accuracy = atoi(argv[i + 1]);
        printf("\naccuracy:%d",accuracy);
    } else if (strcmp(argv[i],"-t")==0) {
        targetBitRate = atof(argv[i + 1]);
        printf("\ntargetBitRate:%f",targetBitRate);
    } else if (strcmp(argv[i],"-f")==0) {
        frameRate = atoi(argv[i + 1]);
        printf("\nframeRate:%d",frameRate);
    }

}
7
répondu Oliver Nina 2012-07-02 22:35:01

AnyOption est une Classe C++ pour l'analyse facile des options de ligne de commande complexes. Il analyse également les options à partir d'un fichier rsourcefile dans le format de paire d'options.

AnyOption implémente les options de caractères traditionnels de style POSIX (- n) ainsi que les nouvelles options longues de style GNU ( --name). Ou vous pouvez utiliser une version plus simple d'option longue (- name) en demandant d'ignorer les options de style POSIX.

5
répondu Jay 2011-08-17 15:23:19

je recommande boost::program_options si vous pouvez utiliser la lib Boost.

il n'y a rien de spécifique dans STL ni dans les libs d'exécution C++/C réguliers.

3
répondu Macke 2009-05-14 20:50:00

essayez la bibliothèque CLPP. C'est une bibliothèque simple et flexible pour l'analyse des paramètres en ligne de commande. En-tête seulement et multiplateformes. Utilise les bibliothèques ISO C++ et Boost C++ uniquement. IMHO il est plus facile que Boost.Program_options.

Bibliothèque: http://sourceforge.net/projects/clp-parser

26 octobre 2010 - nouvelle version 2.0 rc. Beaucoup de bugs corrigés, le remaniement complet du code source, la documentation, les exemples et les commentaires ont été correct.

2
répondu Denis Shevchenko 2010-10-27 03:52:35

réponse assez tardive, mais j'ai utilisé GetPot pour certains projets: http://getpot.sourceforge.net /

caractéristique principale: tout est dans un seul fichier d'en-tête, Pas de problèmes de construction. Il suffit de le sauvegarder quelque part sur votre machine et "# include" dans votre fichier contenant main()

N'a pas été mis à jour récemment, mais bien documenté, et fonctionne bien. Vous pouvez lui donner un essai.

2
répondu kebs 2015-04-24 13:39:26