はじめに
C#やVB.NETを用いることで手軽にGUIアプリケーションが作れるようになったとはいえ、ちょっとしたツールを書くときなどは、手軽さからC言語を使ったCUIのプログラムにしてしまうことが多いのではないかと思います。このようなCUIベースのツールを作るとき、よく使うのに面倒な処理としてコマンドラインオプション(以下オプション)の解析が挙げられます。
そこで本稿では、PC-UNIX系の環境でよく使われるgetopt
関数をC言語から使う様子を紹介しながら、同様の方法をWindows上で実現するための方法について説明します。
対象読者
- C言語を理解していて、
getopt
関数を使ったオプションの解析方法を知りたいという方
なお、サンプルプログラムはすべてC言語で書かれており、Debian GNU/Linux + gcc 4.3でコンパイルと動作確認を行っています。また、Windows向けに書いたプログラムについては、Windows XP(Professional) SP3 + Visual Studio 2008を用いてコンパイルおよび動作の確認を行っています。
シンプルなオプションの解析
getopt
を使ったオプションの解析方法を見る前に、そもそもオプションの解析とは何をしているのかについて考えていきたいと思います。
題材として、引数に指定されたファイルから一文字ずつデータを取り出し、標準出力に出力するという単純なプログラムを考えます(リスト1)。
/* ファイルの内容を書き出すだけのシンプルなプログラム */ #include <stdio.h> int main(int argc, char *argv[]) { int c; FILE *fp; if( *++argv ) { if( (fp = fopen( *argv, "r" ) ) == NULL ) { fprintf( stderr, "Can't opened fle.\n" ); } else { while( ( c = getc(fp) ) != EOF ) { putchar(c); } fclose( fp ); } } else { printf( "Usage : command [filename]\n" ); } return 0; }
ここで、このプログラムに-n
オプションをつけて実行すると、改行記号を無視して表示するように改造したいとしましょう。すると、リスト2に示すような形で、オプションを解析し、必要な処理を行うコードを書くことになります。
/* -nオプションが指定されたら、改行を無視するようにしたプログラム */ #include <stdio.h> int main(int argc, char *argv[]) { int c; int flg = 0; FILE *fp; if( *++argv ) { if( !strcmp( *argv, "-n" ) ) { flg = 1; ++argv; } 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 ); } } else { printf( "Usage : command [filename]\n" ); } return 0; }
ご覧いただけば分かるとおり、オプションの解析というのは、突き詰めていけば
- オプションとなる引数があるのか?
- ある場合、それは正しい引数か?
などをチェックし、それに応じてフラグを起こしたり、メッセージの表示処理をするというのが主体になります。基本的には、getopt
などのオプション解析機能を使った場合に、その中で行われている操作もこれと同じです。であれば、コードは汚くなりますが、この調子でif
による分岐を増やしていけば、getopt
などを使うまでもなく、5個や6個の機能拡張であれば簡単に行えそうな気がします。
しかし、オプションがさらに引数をとる必要性が出てきたり、あるオプションの引数が省略可能だったり、オプションの指定される順序が決まっていない場合を考えるとどうでしょう? 想像するだけで面倒な感じがします。けれどもgetopt
を使えば、そういった面倒な要求にもきちんと答えてくれるオプションの解析が可能なのです。