第17回
コマンドライン引数と終了コード~main関数の基本事項

コマンドライン引数の取得

コンソールモードで実行される多くのプログラムは、編集するファイル名や操作の指示などをコマンドライン引数(パラメータ)としてコマンドラインのプログラム名に続けて与えられるようになっています。Cでは、これらをmain関数の引数から取得できます。

GUI環境でも引数を使える

プログラムは、実行時にコマンドライン引数(コマンドライン・パラメータ)を受け取れます。これはコンソールモードでコマンドラインから実行した場合だけではなく、例えばWindowsでもアプリケーションへのショートカットにパラメータを与えることができます。

Windowsに限らず、UNIX系OSやMacOS ※3 でもデータファイルをダブルクリックすると、そのデータファイルに関連付けられたアプリケーションが起動してデータファイルを開きますが、そのとき内部的には
<アプリケーション名> <ファイル名>
という形のコマンドラインに置き換えられてアプリケーションが実行されます。<ファイル名>の部分がコマンドライン引数に相当します。

MacOSでは、拡張子によって起動するアプリケーションを判別するWindowsとは異なり、1つのファイルに対してディスク上にファイルの本体を記録するデータフォークとその属性を記録するリソースフォークの2つが作られます。そのデータを作成したアプリケーション(クリエータ)やアイコンなどはリソースフォークに保存されるため、Windowsのように拡張子を必要としません

ファイル名や細かな指示を与えられる

コマンドラインでは、以下のような形式で実行するプログラムにコマンドライン引数を指定できます。
<プログラム名> <パラメータ>

コマンドライン引数は、例えばMS-DOSなら以下のようにしてプログラムの実行時に与えられます。
foo -a -f:c:\data\abc.txt
アンダーラインの箇所が、プログラムfooに与えられた引数です。-などの記号とアルファベット1文字がよく使われ、コマンドライン・オプションとも呼ばれます ※4

コマンドライン引数は、プログラムに対して『何を・どのように』処理するかを指示するもので、必須ではありません。コマンドライン引数を必要としないプログラムもありますし、必要であっても省略できるプログラムもあります。場合によっては、コマンドライン引数が必須のものもありますが、大抵の場合は省略すると規定値(デフォルト)が適用されるように設計されています。

"-f"など指示の種類を表す記号を「コマンドライン・オプション」と呼び、その形式はOSや場合によってはプログラムによっても異なります。MS-DOSでは"-"記号の他に"/"を使うものもありました。UNIX系では"--"がよく用いられます

yesno.cのコマンドライン引数

yesno.cでは、画面に表示されるプロンプト(入力を促すメッセージ)をコマンドライン引数で指定できるようにしています。

yesno よろしいですか?
と入力すれば、画面には「よろしいですか? <y/n>」と表示されて1文字の入力を待ちます。コマンドライン引数を何も指定せず

yesno
とだけ入力すれば、規定値として「Are you ready? <y/n>」と表示されます。

argcとargv

コマンドライン引数は、main関数の先頭行で引数として定義されます。

int main(int argc, char *argv[])
           (a)        (b)
int型のargcはスペースまたはタブコードで区切られたコマンドライン引数の数を示します(a)。この値にはプログラム名自体も含まれるので、最低でも1となります。パラメータがなくてプログラム名だけの場合は1、パラメータが1個あれば2……ということです。

char :*型の配列というややこしい型のargvは、
パラメータ文字列へのポインタの配列
を示しています(b)。ポインタも配列もまだ詳しく説明していないので、ここではその格納イメージを紹介しておきましょう。

例えば、先ほど紹介したコマンドライン
foo -a -f:c:\data\abc.txt
の場合なら、メモリ上では図3のような形でコマンドライン引数が格納されています。

この場合、argv[2]の先頭(argv[2][0])は文字列"-f:c:\data\abc.txt"の先頭にある'-'を、4文字目(argv[2][3])なら文字列"-f:c:\data\abc.txt"の4文字目である'c'を指します。

詳しくは、配列とポインタを説明するときに解説しましょう。今の段階では、図3のようなイメージでコマンドライン引数がメモリに格納され、プログラム名を除く実質的な最初の引数はargv[1]で、2番目の引数はargv[2]で……という具合に取得できることだけを理解しておきましょう。


最初の引数はargv[1]

yesno.cでは、
  if (argc > 1) ------ パラメータがある場合

strcpy(strMessage, argv[1]);
という形で引数の数を表すargcが1より大きい(2以上)なら続く引数があると判断し、その内容を「画面に表示するメッセージ」としてstrMessageにコピーするようにしています。それが、文字列をコピーする関数strcpyの第2引数で指定しているargv[1](アンダーラインの箇所)です。

例えば
yesno どうしますか?
というコマンドラインなら、argv[1]は文字列"どうしますか?"の先頭アドレスを示すため、文字列(char型配列)変数strMessageには"どうしますか?"という文字列がコピーされます。