Cómo analizar argumentos de línea de comando en C ++?

Posible duplicado:
¿Qué bibliotecas de analizador de parámetros existen para C ++?

¿Cuál es la mejor forma de analizar argumentos de línea de comandos en C ++ si se especifica que el progtwig se ejecute así?

prog [-abc] [input [output]] 

¿Hay una biblioteca en STL para hacer esto?


Relacionado:

  • Análisis de los argumentos de la línea de comando en una aplicación Unicode C ++

Boost.Program_options debería hacer el truco

Las sugerencias para boost::program_options y GNU getopt son buenas.

Sin embargo, para las opciones de línea de comando simples tiendo a usar std :: find

Por ejemplo, para leer el nombre de un archivo después de un argumento de línea de comando -f . También puede detectar si se ha pasado una opción de palabra única en -h para obtener ayuda.

 #include  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; } 

En lo que hay que tener en cuenta con este enfoque, debe usar std :: strings como valor para std :: find; de lo contrario, se realiza la comprobación de igualdad en los valores del puntero.


Espero que esté bien editar esta respuesta en lugar de agregar una nueva, ya que está basada en la respuesta original. Recribí las funciones ligeramente y las encapsulé en una clase, así que aquí está el código. Pensé que podría ser práctico usarlo de esa manera también:

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

Puedo sugerir la biblioteca de analizador de línea de comandos de Comandos de Templatized C ++ (algunos tenedores de GitHub están disponibles), la API es muy sencilla y (se cita en el sitio):

la biblioteca se implementa por completo en archivos de encabezado por lo que es fácil de usar y distribuir con otro software. Está licenciado bajo la licencia MIT para distribución sin preocupaciones.

Este es un ejemplo del manual, coloreado aquí para simplificar:

 #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","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; } } 

Puede utilizar GNU GetOpt (LGPL) o uno de los diversos puertos C ++, como getoptpp (GPL).

Un ejemplo simple usando GetOpt de lo que quiere (entrada prog [-ab] ) es el siguiente:

 // C Libraries: #include  #include  #include  // 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; } 

Otra alternativa más es el analizador de opciones Lean Mean C ++:

http://optionparser.sourceforge.net

Es una biblioteca de solo cabecera (solo un único archivo de cabecera, de hecho) y, a diferencia de todas las otras sugerencias, también es independiente, es decir, no tiene dependencias de ningún tipo. En particular, no hay dependencia en el STL. Ni siquiera usa excepciones o cualquier otra cosa que requiera soporte de biblioteca. Esto significa que puede vincularse con C simple u otros lenguajes sin introducir bibliotecas “extranjeras”.

Al igual que boost :: program_options, su API ofrece acceso directo conveniente a las opciones, es decir, puede escribir código como este

if (opciones [AYUDA]) …;

y

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

A diferencia de boost :: program_options, sin embargo, esto simplemente utiliza una matriz indexada con una enumeración (proporcionada por el usuario). Esto ofrece la conveniencia de un contenedor asociativo sin el peso.

Está bien documentado y tiene una licencia amigable para la empresa (MIT).

TLMC ++ OP incluye un buen formateador para mensajes de uso que puede alinear líneas y alinear columnas, lo cual es útil si está localizando su progtwig, ya que asegura que la salida se verá bien incluso en los idiomas que tienen mensajes más largos. También le ahorra la molestia de formatear manualmente su uso para 80 columnas.

 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 es una clase de C ++ para analizar con facilidad opciones de línea de comandos complejas. También analiza las opciones desde un archivo rsource en formato de par de valor de opción.

AnyOption implementa las opciones tradicionales de caracteres del estilo POSIX (-n) así como también las nuevas opciones largas de estilo de GNU (–name). O puede usar una versión de opción larga más simple (-name) pidiendo ignorar las opciones de estilo POSIX.

Recomiendo boost :: program_options si puedes usar la lib de Boost.

No hay nada específico en STL ni en las librerías de tiempo de ejecución normales de C ++ / C.

Pruebe la biblioteca CLPP. Es una biblioteca simple y flexible para el análisis de parámetros de línea de comandos. Encabezado solo y multiplataforma. Utiliza solo bibliotecas de C ++ y C ++ de C ++. En mi humilde opinión es más fácil que Boost.Program_options.

Biblioteca: http://sourceforge.net/projects/clp-parser

26 de octubre de 2010: nuevo lanzamiento 2.0rc. Se corrigieron muchos errores, se reparó la refacturación completa del código fuente, la documentación, los ejemplos y los comentarios.

Una respuesta tardía, pero he usado GetPot para algunos proyectos: http://getpot.sourceforge.net/

Característica principal: todo está en un solo archivo de encabezado, sin problemas de comstackción. Solo guárdelo en algún lugar de su máquina y “#include” en su archivo manteniendo main()

No se ha actualizado recientemente, pero está bien documentado y funciona bien. Puedes darle una oportunidad.