SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

特集記事

C言語を使ったコンソールアプリケーションの作成
コマンドラインオプションの解析方法

PC-UNIX系の環境と同様に、Windows上にもgetopt関数を実装可能

getoptを使って書き直す

 では、先ほどの例をgetoptを使って書き直してみます(リスト3)。

リスト3
/* getoptを利用して-nオプションが指定されたら、改行を無視するようにしたプログラム */
#include <stdio.h>
#include "getopt.h" //==(1)

int main(int argc, char *argv[])
{
	int c;
	int opt; //==(2)
	int flg = 0;
	FILE *fp;

	while( ( opt = getopt(argc, argv, "n") ) != -1 ) { //==(3)
		switch( opt ) {
		case 'n' : flg = 1; break;
		}
	}

	//==(4)
	argc -= optind;
	argv += optind;

	if( (fp = fopen( *argv, "r" ) ) == NULL ) {
		fprintf( stderr, "Can't opened fle.\n" );
	} else {
		while( ( c = getc(fp) ) != EOF ) {
			if( flg ) {
				if( c != '\n' ) putchar(c);
			} else {
				putchar(c);
			}
		}
		putchar('\n');
		fclose( fp );
	}
	
	return 0;
}

 いかがでしょう? たった一つの関数を導入しただけですが、ずっと簡潔な書き方になったと思いませんか? 加えてgetoptを使うと、先ほどの例では実現できなかった

$ プログラム名 [filename] -n

 のような、オプションを後付けする機能も実現できます。

 もしリスト2に示したようなアプローチを使うとすると、後付けのオプションに対応するのは大変な労力です。しかし、getoptを使うことで、そのような面倒な処理はすべてgetoptが行うため、気軽にオプションを増やしたり減らしたりといった、プログラムに合わせた効果的なコーディングが可能です。

getoptを使ったプログラムでよく見られるテクニック

 リスト3に示したプログラムでは、getoptを使ったプログラムに見られる独特の表記方法やルールがいくつか隠れています。より詳細なgetoptの使い方を紹介する前に、そのことについて触れておきたいと思います。

 最初に見ていただきたいのは、リスト3の(1)で示した部分です。PC-UNIX系のシステムでは、getoptはunistd.hに含まれているので、それをincludeするよう指示しています。

※注意

 Windows系のOSでは、使用するライブラリに合わせたファイルをincludeします。

 つぎに、リスト3の(2)と(3)で示した部分をご覧ください。

 (2)で宣言しているのは、getoptの解析結果を受け取る変数です。(3)では、実際にgetopt関数を使い、オプションの解析結果を受け取っています。

 getoptは、呼び出されるたびに見つかった次のオプションを一文字ずつ返します。返せる文字がなくなった時点で-1を返す約束になっているため、(3)のようなループを書くことで、いくつもオプションを取るようなプログラムや将来的にオプションが増える予定のあるプログラムであっても、拡張性と保守性を両立させたコードに仕上げることができます。この時getoptに渡す引数は、main関数の引数2つと、オプションを表す文字列です(後述)。あとはループ内に分岐を設け、オプションに対応したフラグを起こしたり、関数を呼び出したりといった操作を行っていきます。

 こうして一通りオプションの解析が済むとリスト3の(4)に進むわけですが、いきなり宣言されていない変数を用いて、加算と減算を行っている様子が見て取れます。実はこの変数はgetoptが暗黙的に用意している変数で、「変数optindは、argvの次に処理される要素のインデックス」を保持するint型の変数です。

 この変数を用いたテクニックが(4)のような処理です。この処理以降、argv[0]~argv[argc-1]には、オプションを除いたプログラムの引数が入ります(※注1)。

 例えばオプション以外に複数のファイル名を受け取る必要があるコードなら、argv[0]~argv[argc-1]までに指定されたファイル名が格納されるといった具合です(※注2)。

 通常のプログラムのように、argv[0]がプログラムの名称ではないので注意が必要です。

 また、(4)の処理によって、同様にargcオプション以外の引数の数を表す数に変化するので、こちらも注意が必要です。

 ここで登場したoptind以外にも同様に、getoptchar型ポインタ変数のoptargint型変数のopterroptoptという三種類の変数を提供してくれます。例えばoptargはオプションが引数を取る場合に活躍する変数で、opterrはその値を0にすることで、認識できない文字オプションが存在したときのエラーメッセージの表示を抑制する変数です。また、認識できない文字オプションが存在した場合には、その文字オプションがoptoptに入ります。この仕組みを利用して、エラーに対してプログラムごとの対処を行うことが可能です。

 このほか、getoptの特別な動作として、解析できないオプションが見つかったときには「?」を返すという動作が挙げられます。独自の方法でエラーに対処するときには、このことも覚えておくと良いでしょう。

次のページ
より複雑なオプションを、getoptを用いて解析する

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

特集記事連載記事一覧

もっと読む

この記事の著者

太田 晃(オオタ アキラ)

 ブログ(http://repse.blogspot.com/)では、coLinux上にMinGWを用いてクロスコンパイル環境を構築し、そのうえでSDLやOpenGLを使ってWindows向けのプログラムを書くとか、海外のソフトウェアを(勝手に)日本語化するとか、Windowsのインデックスサービ...

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4086 2009/07/23 14:00

イベント

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

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

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

メールバックナンバー