15

boost::program_options を使用して、構成ファイルからパラメーターを取得しています。

私は手動でファイルを作成でき、プログラムオプションがそれを解析することを理解しています。しかし、プログラムがファイルを自動的に生成する方法を探しています。オプションの名前とその値を出力することを意味します。例えば:

>./main 

オプションを指定しないと、次のような init.cfg が生成されます

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

次に、そのファイルに移動し、テキスト エディターを使用して値を変更し、このファイルを使用します。

>./main init.cfg

これにアプローチする良い方法は、variables_map を持つことoperator<<です。このようにして、ファイルに書き込むことができます。値を変更します。ファイルを読み取ります。すべて同じ形式で、各行を記述する必要はありません。

ドキュメントや例でそのようなものを見つけることができませんでした。これが可能かどうか教えてください

編集: Sam Miller は、セクションで 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>()が、すべての値が int であるとは限らず、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
4

2 に答える 2

13

私が知っている 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$ 
于 2011-01-16T02:19:41.410 に答える
1

私が質問を理解している限り、指定された option_description に基づいて構成ファイルを作成する方法についてです。

options_description を構成ファイルに 1 つ書き込む方法として考えられる解決策を次に示します。これは、すべてのパラメーターにデフォルト値があるという事実に関連しています。

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

ここで algorithmDesc は 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)
}

それらを組み合わせるのは簡単です。

于 2017-07-20T09:47:47.147 に答える