[ C++で開発 ] [ Boostを使うメモ ]

コマンドライン引数の解析

コマンドラインから実行するプログラムでは、コマンドライン引数に指定した内容を取り込む処理を記述することが多いです。引数の数が数個と少ない場合は、大抵その場限りのコーディングでお茶を濁しますが、ちょっと複雑なコマンドラインとなると、やはりライブラリの出番となります。

昔はCの非標準ライブラリ getopt の出番だったのですが、最近ではBoostに含まれる program_options を使用します。

boost::program_options

簡単なサンプルを示します。

コマンドラインで、以下3つのオプションを指定可能なプログラム mcast_send があったとします。

  1. アドレスを表す文字列。プログラム中で取り込む型はstd::string。指定は必須。
  2. ポート番号を表す文字列。プログラム中で取り込む型はint。指定は必須。
  3. インタフェースを表す文字列。プログラム中で取り込む型はconst char*。指定は任意(省略可)。

以下の書式で使用するものとします。

$ mcast_send -a ff3e:20:2001:db8::101 -p 30000 -i eth0
simple.cpp
#include <boost/program_options.hpp>
#include <string>

using boost::program_options::options_description;
using boost::program_options::value;
using boost::program_options::variables_map;
using boost::program_options::store;
using boost::program_options::parse_command_line;
using boost::program_options::notify;

int main(int argc, char* argv[])
{
    options_description opt("オプション");
    // 引数の書式を定義
    opt.add_options()
        ("help,h", "ヘルプを表示")
        ("address,a", value<std::string>(), "マルチキャストアドレス")
        ("port,p", value<int>(), "ポート番号")
        ("interface,i", value<std::string>(), "インタフェース名");

    // 引数の書式に従って実際に指定されたコマンドライン引数を解析
    variables_map argmap;
    store(parse_command_line(argc, argv, opt), argmap);
    notify(argmap);

    // ヘルプ表示指定があるか、必須引数が抜けていた場合、ヘルプ表示して終了
    if (argmap.count("help") || !argmap.count("address") || !argmap.count("port")) {
        std::cerr << opt << std::endl;
        return 1;
    }                                                           

    // コマンドライン引数から変数に取り込み
    std::string address = argmap["address"].as<std::string>();
    int port = argmap["port"].as<int>();
    const char* interface = 0;
    if (argmap.count("interface")) {
        interface = argmap["interface"].as<std::string>().c_str();
    }
    :
}

ヘルプ表示は以下の出力となります。

オプション:
  -h [ --help ]          ヘルプを表示
  -a [ --address ] arg   マルチキャストアドレス
  -p [ --port ] arg      ポート番号
  -i [ --interface ] arg インタフェース名
                                          

コンパイル・リンク

boost::program_optionsは、ライブラリをリンクする必要があります。

Tips

コマンドライン未指定時のデフォルト値

コマンドラインオプションを未指定時に、デフォルト値を適用する場合、以下のようにdefault_valueを指定します。

    ("port,p", value<int>()->default_value(8080), "ポート番号")

例外を拾う

コマンドラインオプションの解析でエラーがあると、例外がスローされます。例外はstd::exceptionのサブクラスなので、これを捕捉します。

try {
    store(parse_command_line(argc, argv, opt), argmap);
} catch (std::exception& ex) {
    std::cerr << "コマンドライン引数の指定に誤りがあります: " << ex.what() << 
        std::endl << opt << std::endl;
    throw;
}

ファイルからオプションを読み込む

ファイルからオプションを読み込むことができます。

std::ifstream inFile("mcast.conf");
store(parse_config_file(inFile, opt), vm);

ファイルの書式は、

# mcast_send/receive configuration file
port = 8087
if = 2
# address = ff3e:20:2001:db8::101

行の先頭に#があると、コメントとして扱われます。

(要確認)ファイルとコマンドラインとは、先に解析した方が優先されます。