Как мне обнаружить опечатку с помощью Boost.program_options?

#c #boost #boost-program-options

#c #boost #boost-program-options

Вопрос:

Я использую библиотеку boost.program_options. Рассмотрим этот упрощенный случай.

 po::options_description desc("Usage");
desc.add_options()
("uninstall,u", "uninstall program")
("custom,c", po::wvalue<std::wstring>(), "specify custom action");

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
  

Я хочу выдать ошибку в такой командной строке:

 testprog.exe -u c- action1
  

Обратите внимание, пользователь допустил опечатку «c-» вместо «-c». Но анализатор понимает это как вариант с одним u. Как мне обрабатывать такие случаи?

Ответ №1:

Я хочу выдать ошибку в такой командной строке:

 testprog.exe -u c- action1
  

Обратите внимание, пользователь допустил опечатку «c-» вместо «-c». Но анализатор
понимает это как вариант с одним u. Как мне обрабатывать такие случаи?

Прикажите program_options библиотеке не принимать позиционные аргументы, и вы получите желаемое поведение

код и компиляция:

 macmini:stackoverflow samm$ cat po.cc
#include <boost/program_options.hpp>
#include <boost/version.hpp>

#include <iostream>

int
main(int argc, char* argv[])
{
    namespace po = boost::program_options;
    po::options_description desc("Usage");
    desc.add_options()
        ("uninstall,u", "uninstall program")
        ("custom,c", po::wvalue<std::wstring>(), "specify custom action")
        ;

    po::variables_map vm;
    po::command_line_parser cmd_line( argc, argv );
    cmd_line.options( desc );
    cmd_line.positional( po::positional_options_description() );

    try {
        po::store( cmd_line.run(), vm );

        po::notify(vm);
    } catch ( const std::exceptionamp; e ) {
        std::cerr << e.what() << std::endl;
        return -1;
    }

    return 0;
}
macmini:stackoverflow samm$ g   po.cc -I /opt/local/include -L/opt/local/lib -lboost_program_options -Wl,-rpath,/opt/local/lib
  

выполнить:

 macmini:stackoverflow samm$ ./a.out -u c- action1
too many positional options
macmini:stackoverflow samm$ ./a.out -u -c action1
macmini:stackoverflow samm$ 
  

Ответ №2:

Сравните argc-1 с количеством аргументов, найденных с помощью program_options ? Если оно не совпадает, это синтаксическая ошибка.

Он не будет улавливать все случаи, но может уловить те, которые важны для вас.

Комментарии:

1. Мне нравится этот ответ, но было бы лучше, если бы вы предоставили несколько примеров кода

Ответ №3:

Я думаю, что единственный способ сделать это — убедиться, что каждый требуемый аргумент присутствует, например, путем проверки количества каждого типа.

 if (vm.count("uninstall")) { ... }
if (vm.count("custom")) { ... }
  

Вы можете сгенерировать ошибку, если требуемые параметры отсутствуют (т.Е. Количество равно 0) или присутствуют (например -u , и -c не может быть указано, будет количество обоих >0 ).

Комментарии:

1. -опция c является необязательной. Пользователь может указать один параметр -u или оба параметра -u и -c. Проблема в том, что если пользователь допустит вышеуказанную опечатку, библиотека обрабатывает командную строку так, как будто есть один параметр, и программа может сделать что-то неожиданное для него или нее.

2. в этом случае у вас нет другого выбора, кроме как каким-то образом проверить аргументы, поэтому, если -u это предусмотрено, проверьте, что переданный аргумент соответствует тому, что вам требуется, прежде чем предпринимать действия. AFAIK, другого способа нет — объяснить ошибку пользователя….

3. -опция u зарегистрирована как опция без значений. Итак, если я попытаюсь проверить переданные аргументы, то будет выдано исключение boost::bad_any_cast. std::wstring value = vm[«custom»].как<std::wstring>();

4. Обычно с чем-то подобным (особенно с чем-то, что звучит как удаление) всегда стоит перепроверить с пользователем («вы уверены , что хотите удалить?») Если это была ошибка, это позволяет пользователям остановить действие. В случае custom исключения проверки должно быть перехвачено и отображено соответствующее сообщение об использовании. Это то, что я подразумеваю под проверкой пользовательского ввода.

5. Я согласен с вами, что стоит запросить пользователя, прежде чем продолжить. С другой стороны, описание действий -u и -u -c выглядит похожим, и он / она может не заметить разницы. Также для параметра -u всегда возникает исключение bad_any_cast, поскольку оно зарегистрировано как параметр без значений. Так что я не вижу никакого смысла это улавливать.