2013-03-20 12 views
11
//Using boost program options to read command line and config file data 
    #include <boost/program_options.hpp> 
    using namespace std; 
    using namespace boost; 
    namespace po = boost::program_options; 

int main (int argc, char *argv[]) 
{ 
    po::options_description config("Configuration"); 
    config.add_options() 
       ("IPAddress,i","IP Address") 
       ("Port,p","Port") 
       ; 

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

    cout << "Values\n"; 

    string address = (vm["IPAddress"].as<std::string >()).c_str(); 
    string port = (vm["Port"].as<std::string>()).c_str(); 

    cout << (vm["IPAddress"].as<string>()).c_str(); 
    cout << " " << (vm["Port"].as<string>()).c_str(); 

    return 0; 

} 

Czy wprowadzane wartości są w jakiś sposób niedrukowalne?Jak rozwiązać problem "boost :: bad_any_cast: nieudana konwersja przy użyciu parametru boost :: any_cast" podczas używania opcji programu doładowania?

Oto wyjściowy gdb, wydaje się być oddane Problem:

terminate nazywany po wrzuceniu instancją 'boost :: exception_detail :: clone_impl

' co(): boost :: bad_any_cast: failed konwersję za pomocą boost :: any_cast

 Program received signal SIGABRT, Aborted. 
     0x0000003afd835935 in raise() from /lib64/libc.so.6 
string address = (vm["IPAddress"].as<std::string >()).c_str(); 

to miejsce, w którym wystąpił błąd; Próbowałem std :: string i string z tymi samymi wynikami.

testboostpo -i 192.168.1.10 -p 5000 

to linia poleceń.

Próbowałem deklarowania typów, tak jak poniżej:

config.add_options() 
     ("IPAddress,i", po::value<std::string>(), "IP Address") 
      ("Port,p", po::value<std::string>(), "Port"); 

ale nadal wystąpił błąd.

Czy może to być prawdziwy błąd?

+0

Należy opublikować argumenty wiersza poleceń przekazywane programowi. – Praetorian

+0

nit: zbędne jest przekształcenie wyniku z 'std :: string :: c_str()' na 'std :: string' –

Odpowiedz

13

widać wyjątek boost::bad_any_cast wyrzucony z po::variables_map ponieważ przeciążenie dwa const char* argument po::options_description_easy_init::operator() nie określa Typ po::value_semantic, więc przekonwertowanie go na std::string nie będzie działać. Jeśli chcesz przekonwertować wartość na std::string i jest ona wymagana dla twojej aplikacji, użyj wartości semantycznej required().

#include <boost/program_options.hpp> 
namespace po = boost::program_options; 

int main (int argc, char *argv[]) 
{ 
    po::options_description config("Configuration"); 
    config.add_options() 
       ("IPAddress,i", po::value<std::string>()->required(), "IP Address") 
       ("Port,p", po::value<std::string>()->required(), "Port") 
       ; 

    try { 
     po::variables_map vm; 
     po::store(po::parse_command_line(argc, argv, config),vm); 
     po::notify(vm); 
     std::cout << "Values" << std::endl; 

     const std::string address = vm["IPAddress"].as<std::string>(); 
     const std::string port = vm["Port"].as<std::string>(); 

     std::cout << "address: " << address << std::endl; 
     std::cout << "port: " << port << std::endl; 
    } catch (const std::exception& e) { 
     std::cerr << e.what() << std::endl; 
     return 1; 
    } 

    return 0; 
} 

Zanotuj dodany blok przechwytywania, ponieważ parsowanie może (i będzie, jak zauważyłeś) zgłaszać wyjątki. Oto sesja próbki:

samm$ ./a.out 
the option '--IPAddress' is required but missing 
samm$ ./a.out --IPAddress 127.0.0.1 
the option '--Port' is required but missing 
samm$ ./a.out --IPAddress 127.0.0.1 --Port 5000 
Values 
address: 127.0.0.1 
port: 5000 
samm$ 

Oto online demo pokazując to samo zachowanie, dzięki uprzejmości skompilować link run (coliru).

4

Musisz zadeklarować adres IP i port jako ciągi podczas dodawania opcje:

config.add_options() 
    ("IPAddress,i", po::value<std::string>(), "IP Address") 
    ("Port,p", po::value<std::string>(), "Port") 
    ; 
+0

częściowo poprawny, wyjątek' boost :: bad_any_cast' [nadal będzie wyrzucany] (http : //coliru.stacked-crooked.com/view? id = f50049b76d804061b926500aa6953033-57c67fe4b82106f02cd504259a9a9be3) podczas rzucania opcji, która nie występuje w 'po :: variables_map' na' std :: string'. –

2

Ten sam komunikat może również wystąpić, jeśli nie obsługujesz poprawnie argumentów opcjonalnych.

Gwoździe Sam's gwoździe wymagają argumentów, a kod OP sugeruje, że są one wymagane - wystarczy je oznaczyć. Dla wejść opcjonalnych, the Boost PO tutorial daje nam szablon do sprawdzania, czy istnieje opcja przed przekształceniem go:

if(vm.count("address")) 
{ 
    const std::string address = vm["IPAddress"].as<std::string>(); 
    std::cout << "address: " << address << std::endl; 
} 
if(vm.count("port")) 
    const std::string port = vm["Port"].as<std::string>(); 
    std::cout << "port: " << port << std::endl; 
} 

mój problem - ja skopiowane/wklejony i zapomniane, aby wyrównać Jeśli test z wykorzystaniem!

Powiązane problemy