Подтвердить что ты не робот

Есть способ распечатать файл конфигурации для опций форматирования программы

Я использую boost:: program_options для получения параметров из файла конфигурации.

Я понимаю, что я могу создать файл вручную, и параметры программы проанализируют его. но я ищу способ для программы автоматически генерировать файл. что означает распечатку имени опции и ее значения. например:

>./main 

без опции будет генерировать init.cfg, который выглядит следующим образом

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

то я бы пошел в этот файл, изменив значения с помощью текстового редактора и используя этот файл:

>./main init.cfg

хороший способ приблизиться к этому будет иметь переменные_map, чтобы иметь operator<<. таким образом я могу просто записать его в файл. измените значения. прочитайте файл. все в одном формате и не нужно писать каждую строку.

Я не мог найти ничего подобного в документации или примерах. сообщите мне, если это возможно.

EDIT: Сэм Миллер показал, как разбирать файл ini в разделах. Однако у меня все еще есть проблема с получением значений из boost:: program_options:: variables_map vm. я попробовал следующее

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

вместо it->second.value(), получена ошибка. Я также попробовал it->second. Я также получил сообщение об ошибке:

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

Я правильно получаю значение, если я использую it->second.as<int>(), но не все мои значения являются ints, и как только я достигаю double, программа вылетает с этим:

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
4b9b3361

Ответ 1

Там нет способа использования program_options, о котором я знаю. Вы можете использовать библиотеку дерева свойств для записать файл ini.

Вот краткий пример:

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$ 

Ответ 2

Насколько я понимаю, речь идет о том, как писать файл конфигурации на основе данного option_description.

Вот возможное решение, как написать один файл options_description в файле конфигурации. Это связано с тем, что каждый параметр имеет определенное значение по умолчанию.

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

Здесь алгоритмыDesc - это boost:: program_options:: options_description, вот где вы описываете такие параметры, как:

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

Проблема в том, что вам нужны разделы в файле конфигурации. options_description не имеет метода получения заголовка, переданного через конструктор. Грязный способ получить это - вырезать его из потока вывода, сделанного 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)
}

Объединить их вместе просто.