web-dev-qa-db-fra.com

Quelles bibliothèques d'analyseurs de paramètres existe-t-il pour C ++?

Je voudrais passer des paramètres à mon programme C++ de la manière suivante:

./myprog --setting=value

Y a-t-il des bibliothèques qui m'aideront à le faire facilement?

Voir aussi Assistants d'analyse d'arguments pour C et Unix

67
Jim
37
Igor Semenov

GNU GetOpt .

Un exemple simple utilisant GetOpt:

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

// Namespaces:
using namespace std;

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

    // 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;
}

Vous pouvez également utiliser optarg si vous avez des options qui acceptent les arguments.

22
Marcin Gil

TCLAP est une conception légère vraiment agréable et facile à utiliser: http://tclap.sourceforge.net/

19
cheshirekow

Je trouve plus facile à utiliser ezOptionParser . C'est aussi un seul fichier d'en-tête, ne dépend de rien d'autre que STL, fonctionne pour Windows et Linux (très probablement d'autres plates-formes aussi), n'a pas de courbe d'apprentissage grâce aux exemples, a des fonctionnalités que d'autres bibliothèques ne font pas (comme l'importation/l'exportation de fichiers avec commentaires, noms d’option arbitraires avec délimiteurs, formatage automatique, etc.) et est sous licence LGPL.

17
Remik Ziemlinski

Et il y a bibliothèque Google disponible.

Vraiment, l'analyse en ligne de commande est "résolue". Choisissez-en un.

14
Max Lybbert

Il y a ces outils dans la bibliothèque GNU C, qui comprend GetOpt .

Si vous utilisez Qt et aimez l'interface GetOpt, froglogic a publié une belle interface ici .

8
Dusty Campbell

Je pense que GNU GetOpt n'est pas trop immédiat à utiliser.

Qt et Boost pourraient être une solution, mais vous devez télécharger et compiler beaucoup de code.

J'ai donc implémenté un analyseur par moi-même qui produit un std :: map <std :: string, std :: string> de paramètres.

Par exemple, en appelant:

 ./myProgram -v -p 1234

la carte sera:

 ["-v"][""]
 ["-p"]["1234"]

L'utilisation est:

int main(int argc, char *argv[]) {
    MainOptions mo(argc, argv);
    MainOptions::Option* opt = mo.getParamFromKey("-p");
    const string type = opt ? (*opt).second : "";
    cout << type << endl; /* Prints 1234 */
    /* Your check code */
}

MainOptions.h

#ifndef MAINOPTIONS_H_
#define MAINOPTIONS_H_

#include <map>
#include <string>

class MainOptions {
public:
    typedef std::pair<std::string, std::string> Option;
    MainOptions(int argc, char *argv[]);
    virtual ~MainOptions();
    std::string getAppName() const;
    bool hasKey(const std::string&) const;
    Option* getParamFromKey(const std::string&) const;
    void printOptions() const;
private:
    typedef std::map<std::string, std::string> Options;
    void parse();
    const char* const *begin() const;
    const char* const *end() const;
    const char* const *last() const;
    Options options_;
    int argc_;
    char** argv_;
    std::string appName_;
};

MainOptions.cpp

#include "MainOptions.h"

#include <iostream>

using namespace std;

MainOptions::MainOptions(int argc, char* argv[]) :
        argc_(argc),
        argv_(argv) {
    appName_ = argv_[0];
    this->parse();
}

MainOptions::~MainOptions() {
}

std::string MainOptions::getAppName() const {
    return appName_;
}

void MainOptions::parse() {
    typedef pair<string, string> Option;
    Option* option = new pair<string, string>();
    for (const char* const * i = this->begin() + 1; i != this->end(); i++) {
        const string p = *i;
        if (option->first == "" && p[0] == '-') {
            option->first = p;
            if (i == this->last()) {
                options_.insert(Option(option->first, option->second));
            }
            continue;
        } else if (option->first != "" && p[0] == '-') {
            option->second = "null"; /* or leave empty? */
            options_.insert(Option(option->first, option->second));
            option->first = p;
            option->second = "";
            if (i == this->last()) {
                options_.insert(Option(option->first, option->second));
            }
            continue;
        } else if (option->first != "") {
            option->second = p;
            options_.insert(Option(option->first, option->second));
            option->first = "";
            option->second = "";
            continue;
        }
    }
}

void MainOptions::printOptions() const {
    std::map<std::string, std::string>::const_iterator m = options_.begin();
    int i = 0;
    if (options_.empty()) {
        cout << "No parameters\n";
    }
    for (; m != options_.end(); m++, ++i) {
        cout << "Parameter [" << i << "] [" << (*m).first << " " << (*m).second
                << "]\n";
    }
}

const char* const *MainOptions::begin() const {
    return argv_;
}

const char* const *MainOptions::end() const {
    return argv_ + argc_;
}

const char* const *MainOptions::last() const {
    return argv_ + argc_ - 1;
}

bool MainOptions::hasKey(const std::string& key) const {
    return options_.find(key) != options_.end();
}

MainOptions::Option* MainOptions::getParamFromKey(
        const std::string& key) const {
    const Options::const_iterator i = options_.find(key);
    MainOptions::Option* o = 0;
    if (i != options_.end()) {
        o = new MainOptions::Option((*i).first, (*i).second);
    }
    return o;
}
7
Luca Davanzo

Si je peux m'exprimer, je voudrais également suggérer de jeter un œil à une bibliothèque d'analyse d'options que j'ai écrite: dropt .

  • C'est une bibliothèque C (avec un wrapper C++ si vous le souhaitez).
  • C'est léger.
  • Il est extensible (les types d'arguments personnalisés peuvent être facilement ajoutés et avoir un pied d'égalité avec les types d'arguments intégrés).
  • Il devrait être très portable (il est écrit en C standard) sans aucune dépendance (autre que la bibliothèque standard C).
  • Il a une licence très non restrictive (zlib/libpng).

Une fonctionnalité qu'il offre que beaucoup d'autres ne sont pas la possibilité de remplacer les options précédentes. Par exemple, si vous avez un alias Shell:

alias bar="foo --flag1 --flag2 --flag3"

et vous voulez utiliser bar mais avec--flag1 désactivé, il vous permet de faire:

bar --flag1=0
6
jamesdlin

Essayez la bibliothèque CLPP. C'est une bibliothèque simple et flexible pour l'analyse des paramètres de ligne de commande. En-tête uniquement et multiplateforme. Utilise uniquement les bibliothèques ISO C++ et Boost C++. À mon humble avis, il est plus facile que Boost.Program_options.

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

26 octobre 2010 - nouvelle version 2.0rc. De nombreux bugs corrigés, refactoring complet du code source, documentation, exemples et commentaires ont été corrigés.

3

Qt 5.2 est livré avec une API de l'analyseur de ligne de commande .

Petit exemple:

#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDebug>

int main(int argc, char **argv)
{
  QCoreApplication app(argc, argv);
  app.setApplicationName("ToolX");
  app.setApplicationVersion("1.2");

  QCommandLineParser parser;
  parser.setApplicationDescription("Tool for doing X.");
  parser.addHelpOption();
  parser.addVersionOption();
  parser.addPositionalArgument("infile",
      QCoreApplication::translate("main", "Input file."));

  QCommandLineOption verbose_opt("+",
      QCoreApplication::translate("main", "be verbose"));
  parser.addOption(verbose_opt);

  QCommandLineOption out_opt(QStringList() << "o" << "output",
      QCoreApplication::translate("main", "Output file."),
      QCoreApplication::translate("main", "filename"), // value name
      QCoreApplication::translate("main", "out")   // default value
      );
  parser.addOption(out_opt);

  // exits on error
  parser.process(app);

  const QStringList args = parser.positionalArguments();

  qDebug() << "Input files: " << args
    << ", verbose: " << parser.isSet(verbose_opt)
    << ", output: " << parser.value(out_opt)
    << '\n';
  return 0;
}

Exemple de sortie

L'écran d'aide généré automatiquement:

 $ ./qtopt -h 
 Utilisation: ./qtopt [options] infile 
 Outil pour faire X. 
 
 Options: 
 -h, --help Affiche cette aide. 
 -v, --version Affiche les informations de version. 
 - + être détaillé 
 -o, --output Fichier de sortie. 
 
 Arguments: 
 Infile Fichier d'entrée. 

Sortie de version générée automatiquement:

 $ ./qtopt -v 
 ToolX 1.2 

Quelques vrais appels:

 $ ./qtopt b1 - + -o tmp blah.foo 
 Fichiers d'entrée: ("b1", "blah.foo"), verbeux: vrai, sortie: "tmp" 
 $ ./qtopt 
 Fichiers d'entrée: (), verbeux: faux, sortie: "out" 

Une erreur d'analyse:

 $ ./qtopt --hlp 
 Option inconnue 'hlp'. 
 $ echo $? 
 1 

Conclusion

Si votre programme utilise déjà les bibliothèques Qt (> = 5.2), son API d'analyse de ligne de commande est suffisamment pratique pour faire le travail.

Sachez que les options Qt intégrées sont consommées par QApplication avant l'exécution de l'analyseur d'option.

3
maxschlepzig

argstream est assez similaire à boost.program_option: il permet de lier des variables aux options, etc. Cependant, il ne gère pas les options stockées dans un fichier de configuration.

3
Luc Hermitte

Vous pouvez essayer mes petites options en-tête (166 loc si facilement piratables) options.hpp . Il s'agit d'une implémentation à en-tête unique et devrait faire ce que vous demandez. Il vous imprime également la page d'aide automatiquement.

1
burner