コマンドライン引数

コマンドライン引数とオプション

プログラムを起動するときに、そのプログラムの起動時に引数を与える とそれに対して処理を行なってくれる。たとえば、cat コマンドは

cat score.txt

のように、「cat ファイル名」と打てばそのファイルの中味を表 示してくれるし、

cat -n score.txt

のように -n をつければ、指定したファイルを行番号つきで 表示してくれる。また、gcc コマンドは

gcc -o hoge hoge.c

のように起動すると「hoge.c をコンパイルして hoge という実行ファイルに せよ」という意味で解釈してくれる。このように、どんなプログラムでも通常は プログラムを起動するときに「何を」、「どう」処理す るのかの指定を行なえるようになっている。「どう」処理するのか はたいていの場合 - (ハイフン) で始まる引数で指示する。 このような引数のことを特別にオプション という。catの 場合は -n オプションが、「行番号をつけながら」という 追加機能を指定し、gccの場合は -o オプションが、 「出力するファイル名を次の引数で指定するものにせよ」と指定する ようになっている。

自分が作るCプログラムでも、このように(オプションを含めた)引数を 解釈するようにしておいた方が便利である。

コマンドライン引数の取り方

C言語では、プログラム起動時には最初にmain関数に 処理が渡る。このときに、main関数にコマンドライン引数に 与えた(複数の)文字列(へのポインタ)が配列として与えられるようになっている。 これまで main 関数は、

int main()
{ .... }

のようになにも引数を取らないように記述していたが、実際にはコマンドラ イン引数の配列を渡されている。渡されるのは、

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

のように、第1引数は整数、第2引数は文字列へのポインタの配列である。 この説明では分かりづらいので実例を見よう。自分で作ったプログラム fooを、次のように起動したとする。

./foo -o hoge hoge.c

すると、システムはこのコマンドラインを次のような引数構成だと 考える。

第0引数第1引数第2引数第3引数
./foo-ohogehoge.c

そして、この4つの文字列(が格納されているアドレス)を配列にして main関数に渡す。すると、main関数がもらう引数 argc, argv は以下のように文字列と結びつけられる。

argc4 (int)
argv[0]"./foo" (の格納アドレス)
argv[1]"-o" (の格納アドレス)
argv[2]"hoge" (の格納アドレス)
argv[3]"hoge.c" (の格納アドレス)
argv[4]NULL

どのようにプログラムを起動しても(引数なしでも)、必ず argv[0] は起動したプログラム自身を指すことに注意する。 また、必ず配列の最後の値は NULL となる。

コマンドライン引数利用例

とても簡単な例として、cat コマンドと同じように引数として与えられた ものをファイル名と見なし、そのファイルを表示するプログラム dog.cを作ってみよう。

./dog score.txt

のように起動する場合、argv[1]"score.txt" が渡されるので、これを fopen するようにプログラムを書けば良い。

dog.c

#include <stdio.h>

int main(int argc, char *argv[])
{
  FILE *fp;
  char buf[10];
  if (NULL == argv[1]) {
    fp = stdin;
  } else {
    fp = fopen(argv[1], "r");
    if (NULL == fp) {
      fprintf(stderr, "%s というファイルは読めないの..\n", argv[1]);
      exit(1);
    }
  }
  while (NULL != fgets(buf, sizeof buf, fp))
    printf("%s", buf);
  if (stdin != fp)
    fclose(fp);
}

環境変数

実際には、main関数にはもう一つ引数が渡される。 これは慣習的に envp という変数で受け取る文字列への ポインタの配列である。

int main(int argc, char *argv[], char *envp[])
{ ... }

この配列に入っている文字列は環境変数といい、システムが 持っている変数の値である。コマンドラインで envコマンドを 実行すると環境変数の一覧が得られる。

env
USER=c101345
LOGNAME=c101345
HOME=/home/irhome/c101/c101345
  :
  :
  :

この例では、変数 USER の値が c101345 で、 変数 HOME の値が /home/irhome/c101/c101345 となっている。このような状態で、C言語で作成したプログラムを起動すると 第3引数 envp は以下のようになる。

envp[0] USER=c101345
envp[1] LOGNAME=c101345
envp[2] HOME=/home/irhome/c101/c101345
:
:
:
:

環境変数を使ってプログラムに指令を与えることができる。ただし、 任意の環境変数の値はライブラリ関数 getenv を使って手軽に 得ることができるので、main関数の第3引数envp を使う機会はまれだろう。次のプログラムは環境変数 USER の値(つまりユーザ名)に応じてメッセージを出力するものである。

hellouser.c

#include <stdio.h>
#include <stdlib.h>              /* getenv() で必要 */

int main(int argc, char *argv[]) /* envp は使わない */
{
  char *user = getenv("USER");
  if (user) {
    printf("%s さん こんにちは\n", user);
  } else {
    printf("%s さん こんにちは\n", "名無しの権兵衛");
  }
}

目次