Какой эффективный способ анализа параметров командной строки в C ++? - PullRequest
5 голосов
/ 30 сентября 2010

Есть ли действительно эффективный способ работы с параметрами командной строки в C ++?

То, что я делаю ниже, выглядит совершенно дилетантским, и я не могу себе представить, как именно обрабатываются параметры командной строки (atoi, жестко запрограммированные проверки argc) в профессиональном программном обеспечении.

// Command line usage: sum num1 num2

int main(int argc, char *argv[])
{
   if (argc < 3)
   {
      cout << "Usage: " << argv[0] << " num1 num2\n";
      exit(1);
   }<br>
   int a = atoi(argv[1]);
   int b = atoi(argv[2]);
   int sum = a + b;<br>
   cout << "Sum: " << sum << "\n";<br>
   return 0;
}

Ответы [ 6 ]

18 голосов
/ 30 сентября 2010

Возможно, вы захотите использовать для этого внешнюю библиотеку.Есть много на выбор.

В Boost очень богатая (как обычно) библиотека Параметры программы Boost .

Мой личный фаворитза последние несколько лет TCLAP - чисто шаблонный, отсюда нет библиотек или ссылок, автоматическое создание '--help' и другие вкусности.См. самый простой пример из документации.

3 голосов
/ 30 сентября 2010

Вы можете использовать уже созданную библиотеку для этого

http://www.boost.org/doc/libs/1_44_0/doc/html/program_options.html

2 голосов
/ 30 сентября 2010

если это linux / unix, то стандартным для использования является gnu getopt

http://www.gnu.org/s/libc/manual/html_node/Getopt.html

1 голос
/ 03 апреля 2018

Он слишком велик, чтобы включить его в ответ о переполнении стека, но я создал библиотеку для декларативного определения командных строк.Он использует возможность C ++ 14 для создания конструктора класса, присваивая начальные значения каждой переменной-члену.

Библиотека в основном является базовым классом.Чтобы определить синтаксис вашей команды, вы объявляете структуру, производную от нее.Вот пример:

struct MyCommandLine : public core::CommandLine {
    Argument<std::string> m_verb{this, "program", "program.exe",
        "this is what my program does"};
    Option<bool> m_help{this, "help", false,
        "displays information about the command line"};
    Alias<bool> alias_help{this, '?', &m_help};
    Option<bool> m_demo{this, "demo", false,
        "runs my program in demonstration mode"};
    Option<bool> m_maximize{this, "maximize", false,
        "opens the main window maximized"};
    Option<int> m_loops{this, "loops", 1,
        "specifies the number of times to repeat"};
    EnumOption<int> m_size{this, "size", 3,
                           { {"s", 1},
                             {"small", 1},
                             {"m", 3},
                             {"med", 3},
                             {"medium", 3},
                             {"l", 5},
                             {"large", 5} } };
    BeginOptionalArguments here{this};
    Argument<std::string> m_file{this, "file-name", "",
        "name of an existing file to open"};
} cl;

Шаблоны классов Argument, Option и Alias объявлены в области действия базового класса CommandLine, и вы можете специализировать их для своих собственных типов.,Каждый из них принимает указатель this, имя опции, значение по умолчанию и описание для использования при печати синопсиса / использования команды.

Я все еще пытаюсь устранить необходимость разбрызгивания всех this указатели там, но я не нашел способ сделать это без введения макросов.Эти указатели позволяют каждому члену регистрироваться в таблицах базового класса, которые управляют синтаксическим анализом.

Как только у вас есть экземпляр, существует несколько перегрузок метода для анализа ввода из строки или * 1016.* стиль аргумента вектора.Синтаксический анализатор обрабатывает синтаксис опций как в стиле Windows, так и в стиле Unix.

if (!cl.Parse(argc, argv)) {
    std::string message;
    for (const auto &error : cl.GetErrors()) {
        message += error + "\n";
    }
    std::cerr << message;
    exit(EXIT_FAILURE);
}

После анализа вы можете получить доступ к значению любой из опций, используя operator():

if (cl.m_help()) { std::cout << cl.GetUsage(); }
for (int i = 0; i < cl.m_loops(); ++i) { ... }

Вся библиотека занимает всего около 300 строк (без тестов).Экземпляры немного вздуты, так как таблицы синтаксического анализа являются частью экземпляра (а не класса).Но вам, как правило, нужен только один экземпляр для каждой программы, и удобство этого чисто декларативного подхода довольно мощное, и экземпляр можно сбросить, просто проанализировав новый ввод.

0 голосов
/ 12 декабря 2017

Я использую getopt () под windows / mingw:

while ((c = getopt(myargc, myargv, "vp:d:rcx")) != -1) {
        switch (c) {
        case 'v': // print version
            printf("%s Version %s\n", myargv[0], VERSION);
            exit(0);
            break;
        case 'p': // change local port to listen to
            strncpy(g_portnum, optarg, 10);
            break;
...
0 голосов
/ 30 сентября 2010

Я бы порекомендовал всегда использовать boost lexical_cast<> вместо мусора, например atoi, atof и т. Д.

http://www.boost.org/doc/libs/release/libs/conversion/lexical_cast.htm

Кроме этого ваш код в порядке для простогопрочее.

...