Как анализировать аргументы командной строки в C++? [дубликат]
Возможные Дубликаты:
какие библиотеки парсеров параметров существуют для C++?
каков наилучший способ разбора аргументов командной строки в C++, если указана программа
чтобы работать так:
prog [-abc] [input [output]]
есть ли библиотека в STL для этого?
по теме:
10 ответов:
импульс.Program_options должен делать трюк
предложения
boost::program_optionsи GNU getopt-хорошие.однако для простых параметров командной строки я обычно использую std:: find
например, чтобы прочитать имя файла после
-fаргумент командной строки. Вы также можете просто определить, был ли передан параметр с одним словом, как-hза помощью.#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; }на что нужно обратить внимание при таком подходе вы должны использовать std:: strings как значение для std:: find в противном случае проверка равенства выполняется по значениям указателя.
Я надеюсь, что это нормально, чтобы отредактировать этот ответ вместо добавления нового, так как это основано на исходном ответе. Я немного переписал функции и инкапсулировал их в класс, так что вот код. Я подумал, что было бы практично использовать его таким образом:
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; }
Я могу предложить Шаблонная Библиотека Синтаксического Анализатора Командной Строки C++ (часть вилки на GitHub доступны), API очень прост и (цитируется с сайта):
библиотека полностью реализована в заголовочных файлах, что упрощает используйте и распространяйте вместе с другим программным обеспечением. Он лицензирован под MIT Лицензии для бесплатного распространения.
Это пример из руководства, окрашенный здесь для простота:
#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; } }
можно использовать GNU GetOpt (LGPL) или один из различных портов C++, таких как getoptpp (GPL).
простой пример использования GetOpt того, что вы хотите (prog [-ab] input) следующим образом:
// 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; }
еще одна альтернатива-парсер параметров Lean Mean C++:
http://optionparser.sourceforge.net
это библиотека только для заголовков (только один файл заголовка, на самом деле) и в отличие от всех других предложений это также отдельностоящий, т. е. он не имеет никаких зависимостей. В частности, нет никакой зависимости от STL. Он даже не использует исключения или что-то еще, что требует поддержки библиотеки. Это означает, что он может быть связан с обычный C или другие языки без введения" иностранных " библиотек.
Как boost:: program_options его API предлагает удобный прямой доступ к опциям, т. е. вы можете написать такой код
if (options[HELP]) ... ;
и
int verbosity = options[VERBOSE].count ();
В отличие от boost:: program_options, однако это просто использование массива, индексированного с помощью (пользовательского) перечисления. Это предложение удобство ассоциативного контейнера без веса.
Он хорошо документирован и имеет дружественную к компании лицензию (MIT).
TLMC++OP включает в себя хороший форматер для использования сообщений, которые могут сделать перенос строк и выравнивание столбцов, что полезно, если вы локализуете свою программу, потому что это гарантирует, что вывод будет хорошо выглядеть даже на языках с более длинными сообщениями. Это также избавит вас от неудобств ручного форматирования вашего использования для 80 столбцов.
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 это класс C++ для легкого разбора сложных параметров командной строки. Он также анализирует параметры из файла rsourcefile в формате пары значений параметров.
AnyOption реализует традиционные параметры символов стиля POSIX (- n), а также более новые параметры GNU style long (--name ). Или вы можете использовать более простую версию long option ( -name), попросив игнорировать параметры стиля POSIX.
Я бы рекомендовал boost:: program_options, если вы можете использовать Boost lib.
нет ничего конкретного ни в STL, ни в обычных библиотеках времени выполнения C++/C.
попробуйте библиотеку CLPP. Это простая и гибкая библиотека для разбора параметров командной строки. Только заголовок и кросс-платформенный. Использует только библиотеки ISO C++ и Boost C++. ИМХО это проще, чем форсировать.Опции программы.
библиотека:http://sourceforge.net/projects/clp-parser
26 октября 2010-новый релиз 2.0 rc. Исправлено множество ошибок, исправлен полный рефакторинг исходного кода, документации, примеров и комментариев.
довольно поздний ответ, но я использовал GetPot для некоторых проектов: http://getpot.sourceforge.net/
главная особенность: все находится в одном заголовочном файле, никаких проблем с сборкой. Просто сохраните его где-нибудь на вашем компьютере и "#включить" его в файл холдинг
main()недавно не обновлялся, но хорошо документирован и хорошо работает. Вы можете дать ему попробовать.
Comments