Как анализировать аргументы командной строки в C++? [дубликат]




Возможные Дубликаты:
какие библиотеки парсеров параметров существуют для C++?






каков наилучший способ разбора аргументов командной строки в C++, если указана программа
чтобы работать так:



prog [-abc] [input [output]]


есть ли библиотека в STL для этого?





по теме:



1032   10  

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

    Ничего не найдено.