2011-01-16 11 views
12

Estoy usando boost :: program_options para obtener los parámetros de un archivo de configuración.hay una manera de imprimir el archivo de configuración para aumentar las opciones del programa

entiendo que puedo crear un archivo a mano y las opciones del programa lo analizarán. pero estoy buscando una manera para que el programa genere el archivo automáticamente. es decir, imprimir el nombre de la opción y su valor. por ejemplo:

>./main 

sin opción generaría init.cfg que tiene este aspecto

[wave packet] 
width = 1 
position = 2.0 
[calculation parameters] 
levels = 15 

entonces me gustaría ir a ese archivo cambiar los valores utilizando el editor de texto y utilizar este archivo:

>./main init.cfg 

una buena manera de abordar esto sería tener variables_map para tener operator<<. de esta manera solo puedo escribirlo en el archivo. cambiar los valores. lee el archivo todo en el mismo formato y sin necesidad de escribir cada línea.

no pude encontrar nada de eso en la documentación o ejemplos. por favor, hágamelo saber si esto es posible

EDITAR: Sam Miller mostró cómo analizar el archivo ini en secciones. Sin embargo, todavía tengo problemas para obtener los valores de boost :: program_options :: variables_map vm. He intentado lo siguiente

for(po::variables_map::iterator it = vm.begin(); it != vm.end(); ++it) 
    { 
    if(it->first!="help"&&it->first!="config") 
    cout << "first - " << it->first << ", second - " << it->second.value() << "\n"; 
    } 

en lugar de it->second.value(), tiene un error. También probé it->second. También me dio un error:

icpc -lboost_serialization -lboost_program_options -c programOptions.cc 
programOptions.cc(60): error: no operator "<<" matches these operands 
      operand types are: std::basic_ostream<char, std::char_traits<char>> << boost::any 
     cout << "first - " << it->first << ", second - " << it->second.value() << "\n"; 
                ^

compilation aborted for programOptions.cc (code 2) 
make: *** [programOptions.o] Error 2 

consigo el valor correctamente si uso it->second.as<int>() pero no todos mis valores son enteros y una vez que llego doble, el programa se bloquea con esto:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_any_cast> >' 
    what(): boost::bad_any_cast: failed conversion using boost::any_cast 

Respuesta

12

Hay no es una forma de usar program_options que yo sepa. Puede usar la biblioteca del árbol de propiedades al write the ini file.

Aquí es un breve ejemplo:

macmini:stackoverflow samm$ cat property.cc 
#include <boost/property_tree/ptree.hpp> 
#include <boost/property_tree/ini_parser.hpp> 

#include <iostream> 

int 
main() 
{ 
    using boost::property_tree::ptree; 

    ptree root; 

    ptree wave_packet; 
    wave_packet.put("width", "1"); 
    wave_packet.put("position", "2.0"); 

    ptree calculation_parameters; 
    calculation_parameters.put("levels", "15"); 

    root.push_front(
      ptree::value_type("calculation parameters", calculation_parameters) 
      ); 
    root.push_front(
      ptree::value_type("wave packet", wave_packet) 
      ); 

    write_ini(std::cout, root); 

    return 0; 
} 

macmini:stackoverflow samm$ g++ property.cc 
macmini:stackoverflow samm$ ./a.out 
[wave packet] 
width=1 
position=2.0 
[calculation parameters] 
levels=15 
macmini:stackoverflow samm$ 
+0

¿hay alguna manera de que pueda escribir un pequeño ejemplo? o dar una hoja de ruta cómo hacerlo? –

+0

@kirill_igum He añadido un ejemplo. –

0

Por lo que yo entiendo la pregunta, se trata de la forma de escribir el archivo de configuración basado en option_description dado.

Aquí está la solución posible, cómo escribir una options_description al archivo de configuración. Se relaciona con el hecho de que cada parámetro tiene algún valor predeterminado.

void SaveDefaultConfig() 
{ 
    boost::filesystem::ofstream configFile(configFilePath_); 
    auto descOptions = algorithmsDesc_.options(); 
    boost::property_tree::ptree tree; 

    for (auto& option : descOptions) 
    { 
     std::string name = option->long_name(); 
     boost::any defaultValue; 
     option->semantic()->apply_default(defaultValue); 

     if (defaultValue.type() == typeid(std::string)) 
     { 
      std::string val = boost::any_cast<std::string>(defaultValue); 
      tree.put(name, val); 
     } 
     ///Add here additional else.. type() == typeid() if neccesary 
    } 

    //or write_ini 
    boost::property_tree::write_json(configFile, tree); 
} 

Aquí algorithmsDesc es impulsar :: :: program_options options_description, que es donde usted describe opciones como:

algorithmsDesc_.add_options() 
    ("general.blur_Width", po::value<int>(&varWhereToStoreValue)->default_value(3), "Gaussian blur aperture width") 

El problema es si necesita secciones en el archivo de configuración. options_description no tiene un método para que los subtítulos pasen a través de su constructor. La manera sucia conseguirlo es cortarlo de flujo de salida realizada por impresión():

std::string getSectionName() 
{ 
    std::stringstream ss; 
    algorithmDesc_.print(ss) 

    std::string caption; 
    std::getline(ss,caption) 

    //cut last ':' 
    return caption.substr(0, caption.size() - 1) 
} 

Combinando juntos es sencillo.

Cuestiones relacionadas