SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

コマンドラインの解析

Boost.program_optionsのご紹介

  • X ポスト
  • このエントリーをはてなブックマークに追加

 前回のGDBM、コレ使ってコンフィギュレーション(設定情報)をファイルに保存し、次回起動時に復元する小さなアプリケーションを実装し開発チームにリリースしたところ、これがなかなか好評で、数日後新たなリクエストが寄せられました。生成されたコンフィギュレーション・ファイルをブラウズ/編集するコンソールアプリが欲しいんだそうな。キー/値のいずれも文字列ならば、さほどの手間はかからんだろうと引き受けました。

  • X ポスト
  • このエントリーをはてなブックマークに追加

 コンソールアプリっていうからにはコマンドラインを解析し、与えられたオプションに基づいてそれに応じた処理を行わにゃなりません。簡単なものであれば:

list01
int main(int argc, char* argv[]) {
  vector<string> args(argv, argv+argc);
  if ( args.size() <= 1 ) {
    cerr << "no input file(s). --help to see the help." << endl;
    return 1;
  }
  if ( args[1] == "--help" ) {
    usage(); // '使い方'を出力
    return 0;
  }
  if ( args[1] == .... )
  ...

 みたいな"力技"でコマンドラインを解析するんですが、オプションが増えてくると力技では相当に面倒で複雑なコーディングを強いられます。

 コマンドラインを解析してくれるライブラリといえば、Cの世界ならgetopt()が有名どころですけど、今回はいつもなにかとお世話になっているBoostライブラリ群の中の一つ、program_optionsを使います。

前準備:Boostをビルドする

 それではBoostのビルドから始めましょう。現時点での最新版1.54.0をダウンロードページから拾って適当なディレクトリに展開します(ここを<BOOST_ROOT>と表記します)。Windows/Visual C++であれば、コマンドプロンプト立ち上げて<BOOST_ROOT>に移動しbootstrap,続いてb2を実行すればBoostの提供する全ライブラリを片っ端からコンパイルし、<BOOST_ROOT>\stage\libに置いてくれます。生成されるライブラリはマルチスレッド・ランタイムDLL・Release/Debug(-MD/-MDd)です。

※1

 サンプル・プロジェクトをお試しの際は、環境変数BOOST_ROOTを設定してください。

Boost.program_optionsのかんたんチュートリアル

 Boost.program_optionsによるコマンドライン解析は、

  1. options_descriptionにオプションを記述して
  2. parserに(1)を食わせてコマンドラインを解析し
  3. (2)の結果をvariables_mapから取り出す

というダンドリになります。

 簡単な例をいくつか紹介しましょう。例えば小さなコンパイラ:myccを作るとしましょうか。コマンドライン文法はこんなカンジで:

  • - mycc foo.c bar.c:foo.c,bar.cをコンパイルし実行形式を作る
  • - mycc -O2 ... :最適化レベルを2にする(デフォルト値は0)
  • - mycc -I../include ...:インクルード・パス設定(複数設定可)
  • - mycc --help:ヘルプを出力する

 いちばん単純な、オプションスイッチ(-,--から始まる識別子)に後続するオプション値を持たない(上記では--help)場合。

list02
#include <iostream>
#include <boost/program_options.hpp>

namespace po = boost::program_options;
using namespace std;

int main(int argc, char* argv[]) { 
  try {

    // オプションを記述して
    po::options_description desc("オプションの説明");
    desc.add_options()
      ("help,h"      , "ヘルプの出力")
     ;

    // parserに食わせ
    po::command_line_parser parser(argc,argv);
    parser.options(desc);

    // 解析結果を variables_map に格納し
    po::variables_map vm;
    po::store(parser.run(), vm);
    po::notify(vm);    

    // 結果を読み出す
    if ( vm.count("help") ) {
      cout << "mycc [option]... <input_file>...\n"
           << desc << endl;
    }
    return 0;

  } catch(exception& e) {
    cerr << "error: " << e.what() << "\n";
  } catch(...) {
    cerr << "Exception of unknown type!\n";
  }
  return 1;
}

 variables_mapはstd::mapから導出されているので、count()メンバ関数で指定したオプションがコマンドラインに指定されたかを知ることができます。また、options_descriptionをストリームに<<するとヘルプが出てくる親切設計。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7243 2013/07/16 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング