より複雑なオプションを、getoptを用いて解析する
先ほど見た例は、たった一つのオプションを解析したに過ぎませんでした。しかし、これではオプションが引数をとる場合や、オプションに渡す引数を省略可能な場合については対応できません。これに対処するための例として、リスト4では原点からオプションで指定したx,y座標までの距離を表示するプログラムを用意しました。
/* getoptを利用した原点から指定した点の距離を表示するプログラム */
#include <stdio.h>
#include "getopt.h"
#include <stdlib.h>
#include <math.h>
void usage(char* name)
{
printf("Usage:%s -x[val] -y[val]\n", name);
exit(0);
}
int main(int argc, char *argv[])
{
int c;
int opt;
double xval, yval;
double dist;
FILE *fp;
if(argc < 2) {
usage(argv[0]);
}
while( ( opt = getopt(argc, argv, "x:y:") ) != -1 ) { //=== (a)
switch( opt ) {
case 'x' : xval = strtod(optarg, NULL); break;
case 'y' : yval = strtod(optarg, NULL); break;
case '?' : usage(argv[0]); break;
}
}
argc -= optind;
argv += optind;
dist = sqrt( (xval * xval) +(yval * yval) );
printf("原点からの距離は%fです\n", dist);
return 0;
}
このプログラムは
$ プログラム名 -x[val] -y[val]
のように使うことで原点からx,yの引数で示された座標までの距離を表示するものです。間違ったオプションを指定した場合やオプションが指定されなかったときには、使い方を表示します。
さて、さらにこのプログラムに改造を加えて、xとyの引数が省略された場合に、デフォルトの値としてx,yともに1.0という値を使うようにしたのがリスト5です。
/* getoptを利用した原点から指定した点の距離を表示するプログラム引数省略版 */
#include <stdio.h>
#include "getopt.h"
#include <stdlib.h>
#include <math.h>
void usage(char* name)
{
printf("Usage:%s -x[val] -y[val]\n", name);
exit(0);
}
int main(int argc, char *argv[])
{
int c;
int opt;
double xval, yval;
double dist;
FILE *fp;
xval = yval = 1.0;
if(argc < 2) {
usage(argv[0]);
}
while( ( opt = getopt(argc, argv, "x::y::") ) != -1 ) { //=== (a)
switch( opt ) {
case 'x':
if(optarg != 0) xval = strtod(optarg, NULL);
break;
case 'y':
if(optarg != 0) yval = strtod(optarg, NULL);
break;
case '?':usage(argv[0]); break;
}
}
argc -= optind;
argv += optind;
dist = sqrt( (xval * xval) +(yval * yval) );
printf("原点からの距離は%fです\n", dist);
return 0;
}
こちらはリスト4と違い、
$ プログラム名 -x -y
といった具合に、オプションの引数を省略して実行できます。リスト5とリスト4の大きな違いは、ソースコード中に(a)で示した部分にあります。オプションに使いたい文字に続く:が一個ならば、そのオプションには引数が必要で、:が二個ならば引数を省略可能であるとgetoptに対して明示しています。例えば、リスト5で拡張された部分をそのままリスト4に入れると、確かに省略した状態で動きますが、xとyには引数が必要だという旨のエラーメッセージが表示されます。
ここで、getoptの引数として指定する、オプションの文字列についてまとめます。
- 基本的には、オプションとして使いたい文字を羅列した文字列を用いる(オプションがa,b,c,dならば
"abcd") - 引数を取るオプション文字には、文字に続けて
:を打つ - 引数の省略が可能なオプション文字には、文字に続けて
::を打つ
