C言語のargc, argv(コマンドライン引数)の使い方

322, 2021-09-14

目次

C言語のargv(コマンドライン引数)のわかりやすい使い方

この記事では、C言語のmain関数で定義されるargcargvの意味と使い方をわかりやすく解説します。
結論から言うとargcargvコマンドライン引数のことで、コマンドライン引数はプログラムの振る舞いを外部から変えたい時に使います

具体的には↓を見ていきます。

  • argc, argvの読み方

  • argc, argvとはコマンドライン引数のことです

  • コマンドライン引数とは何なのか?

  • コマンドライン引数はどんな時に使うのか?

  • argc, argvの使い方

argc, argvの読み方

argcargvの読み方は↓になります。

  • argc ... エーアールジーシー, アーギュシー

  • argv ... エーアールジーブイ, アーギュブイ

argcargvargの部分がargument(アーギュメント、引数の意)の略のため「アーギュシー」とか「アーギュブイ」と言う人もいます。
またargcargument count(引数の個数)の略で、argvargument vector(引数の配列)の略になります。

argc, argvとはコマンドライン引数のことです

argcargvは何のために使われるのかと言うと、これらはコマンドライン引数として機能します。
つまりC言語のargcargvを指した場合、これはほぼコマンドライン引数を指していると言ってもいいです。
ということはコマンドライン引数について理解すればargcargvについては理解できるということになります。

コマンドライン引数とは何なのか?

ではコマンドライン引数とは何なのでしょうか?
コマンドライン引数について具体的に見ていきましょう。
まずはコマンドライン引数の「コマンドライン」の部分からです。

コマンドラインとは何なのか?

コマンドライン引数の「コマンドライン」とはいったい何なのでしょうか?
コマンドラインとは「コマンド」の「ライン(行)」のことを言います。
これはキーボードから端末に入力されるコマンドの行のことで、CUI(キャラクター・ユーザー・インターフェース、文字だけの画面のこと)で主に使われるものです。

たとえばBashという端末(シェル)に入力するコマンドラインは↓のようなものになります。

$ echo "print(1)" | python

↑の$より後のコマンドの行がコマンドラインです。
↑のコマンドラインを実行するとPythonがインストールされていれば端末に「1」と表示されます。

コマンドラインはサーバー管理者やプログラマーが日常的に入力するもので、その界隈ではかなり一般的なものです。

プログラムに渡される引数をコマンドライン引数と言う

コマンドライン引数とは何なのかと言うと「コマンドライン」の「引数」のことを言います。
つまり、プログラム(コマンド)に渡される引数のことをコマンドライン引数という訳です。
たとえば↓のコマンドラインを見てください。

$ python -c "print(1)"

↑のコマンドラインの場合、pythonというのがコマンド(プログラム)です。
そして半角スペースで区切られて渡されている-c"print(1)"などがコマンドの引数になります。
この引数のことをコマンドライン引数と言います。

コマンドライン引数の例

では実際にコマンドライン引数の例を見てみたいと思います。
たとえば↓のようなコマンドラインもコマンドライン引数の指定方法として正しいです。

$ command abc def

↑の場合はcommandがコマンドで、abcdefがコマンドライン引数です。
↓の場合はどうでしょうか。

$ command --opt val

↑の場合も--optvalがコマンドライン引数になります。
--optは一般的にはオプションと呼ばれるものですが、これもコマンドライン引数の一種です。
コマンドライン引数というカテゴリの中にオプションが存在している感じです。

コマンドライン引数はどんな時に使うのか?

ではコマンドライン引数はどんな時に使うのでしょうか?
コマンドライン引数の使い道は?
コマンドライン引数を使えると何が嬉しいのか?
1つ1つ見ていきたいと思います。

プログラムに引数を渡したいとき

コマンドライン引数の使い道の1つが、プログラムに引数を渡したいときです。
たとえばコマンドラインからプログラムにファイル名を渡したいとしましょう。
そうすると↓のようなコマンドラインになります。

$ command 私のファイル.txt

commandというコマンドは「私のファイル.txt」を受け取り、それをプログラムの中で使うことができます。
ファイルを開いてファイル内容を取得し、それを表示したりあるいは加工したりなどといった処理が可能になります。
このようにプログラム(コマンド)に引数を渡せると、プログラムを便利にすることができます。
外部からプログラムにファイル名を渡せれば、プログラムの中でファイル名を決め打ちしなくて済むので楽ですよね。

プログラムにオプションを指定したいとき

あとはコマンドライン引数の使い道として、プログラムにオプションを指定するという使い道があります。
オプションとはプログラムの振る舞いを変えたい時に指定する引数のことです。
オプションはUNIX系のコマンドではハイフン(-)で始まる名前で指定します。
Windows系の場合はスラッシュ(/)で始まる名前で指定します。

UNIX系のコマンドのオプションは↓のようになります。

$ command --option1 --option2 option2_value

Windows系のコマンドの場合は↓のようになります。

> command /option1 /option2 option2_value

プログラムの振る舞いを変えたいときに使う

このようにコマンドライン引数はプログラムの振る舞い、つまり動作を変えたいときに指定します
コマンドライン引数を使うとプログラムの振る舞いを実行時に指定することができるので、非常に便利です。
外部からファイル名を渡したり、あるいはオプションを指定してプログラムの動作を変更したりなど、いろいろな使い道があります。

argc, argvの使い方

ではC言語におけるargcargvのコマンドライン引数の使い方について見てみたいと思います。

main関数の定義方法

まずmain関数の定義方法です。
プログラム内でコマンドライン引数を使いたい場合はmain関数は↓のように定義します。

int main(int argc, char *argv[]) {
    return 0;
}

argcint型の整数です。
argvは文字列の配列として定義します。
これらargcargvにはプログラムの実行時に自動でコマンドライン引数が渡されます。
つまり、↑のようにmain関数を書いておけば、あとは実行時にargcargvを参照するだけでコマンドライン引数を参照できるということになります。

argv[0]にはプログラムのパスが入る

argcargvの注意点として、argvの第1要素、つまりargv[0]には必ず実行プログラムのパスが保存されます。
つまりargcのカウントも最低は常に1です。
これはargcargvの特徴なので気をつけてください。

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("argc = %d, argv[0] = %s\n", argc, argv[0]);
    return 0;
}

↑のコードを実行プログラムcommandとしてコンパイルします。
そして実行すると↓のような結果になります。

$ ./command 
argc = 1, argv[0] = ./command

↑の結果を見ると、コマンドラインからコマンドのみを指定して実行した場合、argc1argv[0]にはコマンドのパスが入っていることがわかります。

色んな引数のargc, argvの値を見てみる

では具体的に引数の指定によってargcargvがどのように変化するのか確認してみたいと思います。
確認用のコードは↓になります。

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("argc = %d\n", argc);

    for (int i = 0; i < argc; i += 1) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }

    return 0;
}

↑のコードはargcargvの値を確認したい時に便利に使えるテンプレです。
↑のコードをコンパイルして↓のように色々とコマンドライン引数を指定して使ってみます。

$ ./command
argc = 1
argv[0] = ./command

$ ./command 1
argc = 2
argv[0] = ./command
argv[1] = 1

$ ./command 1 2
argc = 3
argv[0] = ./command
argv[1] = 1
argv[2] = 2

$ ./command 1 2 --opt "hello world"
argc = 5
argv[0] = ./command
argv[1] = 1
argv[2] = 2
argv[3] = --opt
argv[4] = hello world

↑の例を見るとわかりますが、ダブルクオートで囲んだ引数はそれが1つの引数として解釈されます。
↑の場合、hello worldというダブルクオートで囲んだ引数がargv[4]に保存されているのがわかります。

argvはNULL終端されている

argvは文字列の配列、つまりポインタの配列になるわけですが、この配列はNULL終端されています。
NULL終端とは配列の末尾にNULLが入っていることです。
つまり↓のようなコードは必ずNULLが出力されます。

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("argv[argc] = %s\n", argv[argc]);
    return 0;
}

またこの特徴を利用して、↓のようなポインタ配列を使ったfor文を書くことも出来ます。

#include <stdio.h>

int main(int argc, char *argv[]) {
    for (char **p = argv; *p; p += 1) {
        printf("p = %s\n", *p);
    }
    return 0;
}
$ ./command 1 2
p = ./command
p = 1
p = 2

ファイル名を必須とするプログラム

たとえばコマンドライン引数から入力されるファイル名を必須とするプログラムを作りたい場合を考えます。
ファイル名が指定されていなければプログラムの使い方を表示し、ファイル名が指定されていたら処理を続行するという感じです。
このような動作のプログラム(コマンド)は非常に一般的な設計と言えます。

#include <stdio.h>

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: command [file-name]\n");
        return 0;
    }

    const char *fname = argv[1];
    printf("fname = %s\n", fname);

    return 0;
}

↑のようにコードを書きます。
コンパイルして実行すると↓の結果になります。

$ ./command
Usage: command [file-name]

$ ./command file.txt
fname = file.txt

↑の結果を見ると、引数を指定しない場合はUsage: ...が表示されています。
引数(ファイル名)を指定した場合は処理が続行されているのがわかります。

argcは最低が1なので、そのことを考慮してプログラムを書く必要があります。
↑のプログラムの場合、if (argc < 2)というif文でargcをチェックしていますが、これは「argcがが2より下だったら処理を中断し、2以上だったら処理を続行する」という意味になります。
コマンドラインからファイル名が渡された場合、argcの値は1から2に増えるので、このような条件式になります。

おわりに

今回はC言語のargcargvについて見てみました。
コマンドライン引数はCUI系のプログラムでは無くてはならないものと言っても良いかもしれません。
コマンドライン引数を解析できるプログラムを作ることで皆さんのプログラムはさらに便利になるでしょう。

アーギュブイブイ

勝利(処理)のV