2011-01-16 16 views
12

Sto utilizzando boost :: program_options per ottenere parametri da un file di configurazione.c'è un modo per stampare il file di configurazione per le opzioni del programma di potenziamento

Capisco che posso creare un file a mano e le opzioni del programma lo analizzeremo. ma sto cercando un modo per il programma per generare automaticamente il file. significa stampare il nome dell'opzione e il suo valore. per esempio:

>./main 

senza opzione genererebbe init.cfg che assomiglia a questo

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

quindi vorrei andare in quel file modificare i valori utilizzando editor di testo e utilizzare questo file:

>./main init.cfg 

un buon modo per avvicinarsi a questo sarebbe avere variables_map per avere operator<<. in questo modo posso solo scriverlo in un file. cambia i valori. leggi il file. tutto nello stesso formato e nessuna necessità di scrivere ogni riga.

Non ho trovato nulla di simile nella documentazione o negli esempi. per favore fatemi sapere se questo è possibile

MODIFICA: Sam Miller ha mostrato come analizzare il file ini nelle sezioni. Tuttavia, ho ancora un problema nel recuperare i valori da boost :: program_options :: variables_map vm. ho provato la seguente

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"; 
    } 

invece di it->second.value(), ha ottenuto un errore. ho anche provato it->second. Ho anche avuto un errore:

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 

ottengo il valore correttamente se io uso it->second.as<int>() ma non tutti i miei valori sono interi e una volta raggiungo doppio, il programma si blocca con questo:

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 

risposta

12

C'è non è un modo che usa program_options di cui sono a conoscenza. È possibile utilizzare la libreria ad albero delle proprietà su write the ini file.

Ecco un breve esempio:

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

c'è un modo per scrivere un breve esempio? o dare una road map come si fa? –

+0

@kirill_igum Ho aggiunto un esempio. –

0

Per quanto ho capito la domanda, si tratta di come scrivere file di configurazione in base a data option_description.

Ecco la possibile soluzione, come scrivere una options_description nel file di configurazione. Si riferisce al fatto che ogni parametro ha un valore predefinito.

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); 
} 

Qui algorithmsDesc è boost :: :: program_options options_description, che è dove si descrivono le opzioni come:

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

Il problema è che se avete bisogno di sezioni nel file di configurazione. options_description non ha il metodo per far passare la didascalia attraverso il suo costruttore. Il modo sporco per farlo è quello di tagliare dal flusso di output fatto da print():

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 insieme è semplice.

Problemi correlati