Ответ 1
Boost.Program_options должен сделать трюк
Возможный дубликат:
Какие библиотеки парсеров для языка существуют для С++?
Каков наилучший способ анализа аргументов командной строки на С++, если указанная программа для запуска следующим образом:
prog [-abc] [input [output]]
Есть ли библиотека в STL для этого?
по теме:
Boost.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;
}
Я могу предложить Templatized С++ Command Parser Library (некоторые вилки на 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) или один из различных портов С++, например getoptpp (GPL).
Простой пример использования GetOpt из того, что вы хотите (prog [-ab]):
// 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;
}
Еще одной альтернативой является Paraner Paralleler Lean Mean С++:
http://optionparser.sourceforge.net
Это библиотека только для заголовков (на самом деле это только один файл заголовка), и в отличие от всех других предложений также автономный, то есть он не имеет никаких зависимостей. В частности, нет никакой зависимости от STL. Он даже не использует исключения или что-то еще, что требует поддержки библиотеки. Это означает, что он может быть связан с обычным C или другими языками без введения "чужих" библиотек.
Как и boost:: program_options, его API предлагает удобный прямой доступ к параметрам, то есть вы можете написать код, подобный этому
if (опции [HELP])...;
и
int verbosity = options [VERBOSE].count();
В отличие от boost:: program_options, это просто использует массив, проиндексированный с перечислением (предоставленным пользователем). Это обеспечивает удобство ассоциативного контейнера без веса.
Он хорошо документирован и имеет дружественную к компании лицензию (MIT).
TLMС++ OP содержит красивый форматтер для сообщений об использовании, которые могут выполнять line-wrapping и выравнивание столбцов, что полезно, если вы локализируете свою программу, потому что она гарантирует, что результат будет хорошо смотреться даже на языках с более длинными сообщениями. Это также избавляет вас от необходимости вручную форматировать ваше использование для 80 столбцов.
AnyOption - это класс С++ для простого анализа сложных параметров командной строки. Он также анализирует параметры из файла rsourcefile в формате пары значений параметра.
AnyOption реализует традиционные параметры символа стиля POSIX (-n), а также новые варианты длинного стиля GNU (--name). Или вы можете использовать более простую длинную опционную версию (-name), попросив игнорировать параметры стиля POSIX.
Я бы рекомендовал boost:: program_options, если вы можете использовать Boost lib.
В STL нет ничего конкретного и в обычных версиях С++/C runtime.
Попробуйте библиотеку CLPP. Это простая и гибкая библиотека для синтаксического анализа параметров командной строки. Только для заголовков и кросс-платформенных. Использует только библиотеки ISO С++ и Boost С++. ИМХО это проще, чем Boost.Program_options.
Библиотека: http://sourceforge.net/projects/clp-parser
26 октября 2010 г. - новый выпуск 2.0rc. Исправлено множество ошибок, исправлен полный рефакторинг исходного кода, документация, примеры и комментарии.
Довольно поздний ответ, но я использовал GetPot для некоторых проектов: http://getpot.sourceforge.net/
Основная особенность: все в одном файле заголовка, без сбоев сборки. Просто сохраните его где-нибудь на своей машине и "#include" в файле main()
Не обновляется в последнее время, но красиво оформлено и работает хорошо. Вы можете попробовать.
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);
}
}