Comment parsingr les arguments de ligne de commande en C ++?

Duplication possible:
Quelles sont les bibliothèques d’parsingurs de parameters pour C ++?

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

prog [-abc] [input [output]] 

Y at-il une bibliothèque dans STL pour faire cela?


En relation:

  • Analyse des arguments de ligne de commande dans une application C ++ unicode

Boost.Program_options devrait faire l’affaire

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 argument de ligne de commande -f . Vous pouvez aussi simplement détecter si une option à un seul mot a été transmise comme -h pour obtenir de l’aide.

 #include  char* getCmdOption(char ** begin, char ** end, const std::ssortingng & 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::ssortingng& 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; } 

En ce qui concerne cette approche, vous devez utiliser std :: ssortingngs comme valeur pour std :: find, sinon le contrôle d’égalité est effectué sur les valeurs du pointeur.


J’espère que vous pourrez modifier cette réponse en ajoutant une nouvelle, car elle est basée sur la réponse d’origine. J’ai réécrit légèrement les fonctions et les ai encapsulées dans une classe, alors voici le code. J’ai pensé qu’il pourrait être pratique de l’utiliser ainsi:

 class InputParser{ public: InputParser (int &argc, char **argv){ for (int i=1; i < argc; ++i) this->tokens.push_back(std::ssortingng(argv[i])); } /// @author iain const std::ssortingng& getCmdOption(const std::ssortingng &option) const{ std::vector::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::ssortingng empty_ssortingng(""); return empty_ssortingng; } /// @author iain bool cmdOptionExists(const std::ssortingng &option) const{ return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end(); } private: std::vector  tokens; }; int main(int argc, char **argv){ InputParser input(argc, argv); if(input.cmdOptionExists("-h")){ // Do stuff } const std::ssortingng &filename = input.getCmdOption("-f"); if (!filename.empty()){ // Do interesting things ... } return 0; } 

Je peux suggérer une bibliothèque d’parsingur syntaxique de ligne de commande en C ++ (certaines fourches sur GitHub sont disponibles), l’API est très simple et (citée sur le site):

la bibliothèque est entièrement implémentée dans des fichiers d’en-tête, ce qui la rend facile à utiliser et à dissortingbuer avec d’autres logiciels. Il est sous licence MIT pour une dissortingbution sans souci.

Voici un exemple du manuel, coloré ici pour plus de simplicité:

 #include  #include  #include  #include  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 nameArg("n","name","Name to print",true,"homer","ssortingng"); // 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::ssortingng 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; } } 

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

Un exemple simple utilisant GetOpt de ce que vous voulez ( entrée prog [-ab] ) est le suivant:

 // C Libraries: #include  #include  #include  // Namespaces: using namespace std; int main(int argc, char** argv) { int opt; ssortingng input = ""; bool flagA = false; bool flagB = false; // Resortingeve 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; } 

Une autre alternative est l’parsingur Lean Mean C ++ Option:

http://optionparser.sourceforge.net

C’est une bibliothèque en-tête uniquement (en fait un fichier d’en-tête unique) et contrairement à toutes les autres suggestions, elle est également indépendante, c’est-à-dire qu’elle ne comporte aucune dépendance. En particulier, il n’y a pas de dépendance vis-à-vis de la STL. Il n’utilise même pas les exceptions ou tout autre élément nécessitant un support de bibliothèque. Cela signifie qu’il peut être lié à plain C ou à d’autres langages sans introduire de bibliothèques “étrangères”.

Comme boost :: program_options, son API offre un access direct pratique aux options, c’est-à-dire que vous pouvez écrire du code comme celui-ci.

si (options [AIDE]) …;

et

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.

C’est bien documenté et dispose d’une licence conviviale (MIT).

TLMC ++ OP inclut un bon formateur pour les messages d’utilisation qui peuvent faire l’écriture des lignes et l’alignement des colonnes, ce qui est utile si vous localisez votre programme, car il garantit que la sortie sera correcte même dans les langues contenant des messages plus longs. Cela vous évite également de formater manuellement votre utilisation pour 80 colonnes.

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

AnyOption est une classe C ++ pour l’parsing facile des options de ligne de commande complexes. Il parsing également les options d’un fichier de ressources au format de paire de valeurs d’option.

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

Je recommande boost :: program_options si vous pouvez utiliser la librairie Boost.

Il n’y a rien de spécifique dans STL ni dans les bibliothèques d’exécution C ++ / C classiques.

Essayez la bibliothèque CLPP. C’est une bibliothèque simple et flexible pour l’parsing des parameters de ligne de commande. En-tête uniquement et multiplateforme. Utilise uniquement les bibliothèques ISO C ++ et Boost C ++. IMHO c’est plus facile que Boost.Program_options.

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

26 octobre 2010 – nouvelle version 2.0rc. De nombreux bogues corrigés, la refactorisation complète du code source, de la documentation, des exemples et des commentaires ont été corrigés.

Une 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 soucis de génération. Sauvegardez-le 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 essayer.