C言語 main関数のコマンドライン引数【argvとargcの使い方】

C言語
この記事は約11分で読めます。

こんにちは、ナナです。

「引数」といえば関数への入力として与える情報ですね。本記事では「コマンドライン引数」と呼ばれる特別な引数について解説します。

本記事では次の疑問点を解消する内容となっています。

本記事で学習できること
  • コマンドライン引数とは何なのか?
  • コマンドライン引数の与え方とは?
  • 「argc」と「argv」の内容と扱い方とは?
  • コマンドライン引数を使ったサンプルプログラムの紹介

では、「コマンドライン引数」とは何かを学んでいきましょう。

スポンサー

コマンドライン引数とは

「コマンドライン引数」という言葉の中には「引数ひきすう」という単語が含まれています。まずは、「引数」から振り返ってみましょう。

関数呼び出し時に指定する引数情報

関数の「引数」とは関数というサービスを作動させるために必要な入力情報です。

例えば、次のように2つの引数を受け取り、足し算した結果を画面に出力するsum関数があったとしましょう。

sum関数に対して、足し算を計算したい値を2つ与えることで計算結果を画面に表示します。

このプログラムをイメージで示すと、「依頼元」と「関数」において次のようにやり取りしているように捉えます。

このように「引数」という情報によって、「関数を呼び出す依頼元」から「関数」に対して様々な要求を依頼することができるのです。

ナナ

「引数」は関数の挙動を変化させることができる情報です。

このイメージは関数を理解する上ですごく大事なイメージです。理解していない方はしっかりと把握しておきましょう。

コマンドライン引数はmain関数に与える引数情報

main関数の引数は一般的に次のように「void型」として書きます。

#include <stdio.h>

int main(void)
{
	printf("Hello World");

	return 0;
}

しかし、main関数は次のように書くこともできるのです。

#include <stdio.h>

int main(int argc, char** argv)
{
	printf("Hello World");

	return 0;
}

この引数ひきすう「コマンドライン引数」と呼びます。

アプリケーションの動作を変えるための引数

main関数とは、C言語において最初に動作する関数です。

つまり、main関数が持つ「コマンドライン引数」の役割とは、皆さんが作成したアプリケーションとしての動作を変えるための情報なのです。

ナナ

コマンドライン引数を与えただけで動きが変わるわけではありませんよ!

皆さん自身がコマンドライン引数の情報に応じて動きが変わるようにプログラムしておく必要があります

スポンサー

コマンドライン引数の与え方

「引数」の情報とは、関数を呼び出す側が与える情報です。

main関数に引数があるということは、main関数を呼び出す側が引数の情報を与える必要があります。

ここで疑問がでてきます。

main関数って自分で呼び出したことなんてないよ!

ということです。

先ほどの例のsum関数であれば、自分が作るプログラムからsum関数を呼び出す際に引数を与えればよいのですが、main関数を呼び出すプログラムって皆さん書いたことないですよね。

ここで登場するのが「コマンドライン引数」によるmain関数への引数の受け渡し方法です。

Visual Studioを使ったプログラミングでは、コマンドライン引数の指定は2つの方法があります。

コマンドライン引数の指定方法
  • Visual Studioのプロジェクトプロパティから指定する。
  • コマンドプロンプトでアプリケーション実行時に指定する。

それでは次のプログラムを例に、コマンドライン引数を使って出力結果が変わるアプリケーションを動かしてみましょう。

#include <stdio.h>

int main(int argc, char** argv)
{
	int i;

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

	return 0;
}
ナナ

このプログラムはコマンドライン引数の使い方と与え方を知るための簡単なプログラムです。

実践的ではありませんが、こんな使い方ができるということを理解しましょう!

Visual Studioプロジェクトのプロパティから与え方

まずは、Visuau Studio固有の「コマンドライン引数」の指定方法を解説しましょう。

Visual Studioではプログラムを「プロジェクト」という単位で管理しています。プロジェクトには様々な設定を行うことができ、「コマンドライン引数」に関する設定も可能です。

例として「Project1」という名前で作成したプロジェクトのプロパティに、コマンドライン引数を設定してみましょう!

このようにプロジェクトのプロパティから「コマンド引数」の項目に、スペース区切りで文字を並べるだけです。

設定後に「デバッグ実行」を行うと次の結果が表示されたことでしょう。

C:\LearningC\Project1\Debug\Project1.exe
Hello
100

白色部分に「コマンド引数」で指定した「Hello」と「100」が表示されました。

なぜ、このような結果が表示されたかに関しては後述します。

ナナ

この方法はVisual Studioに限った指定方法になります。

しかし、Visual Studio以外の統合開発環境においても同様の設定内容がどこかしらにあるはずです。統合開発環境の設定内容を確認してみるとよいでしょう!

コマンドプロンプトによるコマンドライン引数の与え方

こちらの方法が一般的なコマンドライン引数の与え方になります。

アプリケーションとは実行ファイルであり、実行ファイルとはコマンドから実行することができます。

コマンドから実行ファイルを動かすためにはコマンドプロンプトを利用します。

コマンドプロンプトの「>」の後に、次のようにプロジェクトへの実行ファイルの指定と、コマンドライン引数である「Hello 100」を指定して、Enterキーを押してみましょう。

> C:\LearningC\Project1\Debug\Project1.exe Hello 100

※実行ファイルへのパスやファイル名が異なる方は各自で調整してください。

Project1.exeの実行ファイルが次のように実行され結果が表示されます。

C:\LearningC\Project1\Debug\Project1.exe
Hello
100
ナナ

「コマンドプロンプト」や「コンソール」と呼ばれるツールを利用して、コマンドによる実行ファイルを動かす方法は、LinuxといったPCでは当たり前に使われる手法です。

コンピューターでプログラムを動かすとは、本質的にはこちらの方法で動いているのです。覚えておくとよいでしょう。

スポンサー

argcとargvのコマンドライン引数の内容と扱い方

main関数の引数となる「argc」と「argv」について解説しましょう。

int main(int argc, char** argv)

この2つの引数は次の情報を管理しています。

引数名省略前英語説明
argcargument countargvの配列数を示す
argvargument vectorコマンドライン引数情報の配列

引数名は自由に変更できますが、慣例としてこの名前を使用するのが一般的です。英語の「argument」とは「引数」という意味です。

ナナ

よく見ると、argvは「char**」のデータ型となっていますね。ダブルポインタというやつです。順に解説していきましょう!

argvは文字列へのダブルポインタ変数

引数:argvは扱いに少し気を付ける必要があります。この変数のデータ型は「char型情報へのダブルポインタ」になっています。

ダブルポインタに慣れていない方は、この構造に戸惑うこともあるのでイメージ図として構造を示しましょう。

本例では、コマンドライン引数として得られる結果は、次の3つの文字列となっています。

コマンドライン引数で得られた文字列情報
  • C:\LearningC\Project1\Debug\Project1.exe
  • Hello
  • 100

この3つの文字列とargvの関係性は次のようになっています。

argv変数は左下の変数であり、文字列ポインタの配列への番地を管理しています。そのため「ダブルポインタ」となっているのです。

ダブルポインタを復習したい方は『「ポインタのポインタ」を図解【イメージで簡単理解!】』を見ておきましょう。

argcはポインタ配列の個数を管理

引数:argcの役割とは引数:argvが指し示す「文字列ポインタの配列」が、いくつ存在するかを示すための情報です。

この情報がないと、個数を自由に変化させることができるコマンドライン引数が、いくつ存在するのかがわからないのです。

argvの1つ目の情報

ここまでで不思議に感じている方もいることでしょう。

C:\LearningC\Project1\Debug\Project1.exe
Hello
100

コマンドライン引数として指定した情報は「Hello」「100」の2つのはずですが、個数として3つの情報が管理されています。

この現象は、コマンドプロンプトによる実施結果の方から考察するとわかりやすいです。

> C:\LearningC\Project1\Debug\Project1.exe Hello 100

コマンドライン引数で得られた情報とは次のようになっています。

このようにコマンドライン引数の1つ目はアプリケーションを実行したパスとファイル名が格納されるのです。

ナナ

つまり、コマンドライン引数として何も指定しなかったとしても、最低1つのコマンドライン引数の情報がmain関数に必ず格納されることになります。

スポンサー

コマンドライン引数を使ったサンプルプログラム

それではコマンドライン引数を使ったプログラムを紹介しましょう。

簡単な例ではありますが、この形を基本に応用すれば様々な動作をサポートするアプリケーションが作成できます。

足し算・引き算を画面に表示するサンプルプログラム

それでは次の仕様を満たすプログラムを検討するとしましょう。

主要コマンド実行内容コマンドライン指定例
helpヘルプ表示help
add足し算の結果表示add 10 20
sub引き算の結果表示sub 30 10

主要コマンドを判定し、動作を決定します。strcmp関数やatoi関数を使ってコマンドライン引数を解析していきます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv)
{
	if (argc <= 1)
	{
		printf("コマンドライン引数を指定してください\n");

		return 0;
	}

	if (strcmp(argv[1], "help") == 0)
	{
		printf("---------------------------\n");
		printf("足し算:add 10 20\n");
		printf("引き算:sub 30 10\n");
		printf("---------------------------\n");
	}
	else if (strcmp(argv[1], "add") == 0 && argc == 4)
	{
		printf("add:%d\n", atoi(argv[2]) + atoi(argv[3]));
	}
	else if (strcmp(argv[1], "sub") == 0 && argc == 4)
	{
		printf("sub:%d\n", atoi(argv[2]) - atoi(argv[3]));
	}
	else
	{
		printf("サポートされていないコマンドライン引数です\n");
	}

	return 0;
}

strcmp関数やatoi関数の使い方は次の記事を見ておくとよいでしょう。
》参考:atoi関数【文字列の数字を数値へ変換する簡単な方法】
》参考:strcmpとmemcmp【使い方と比較の違い:サンプル付き】

様々なコマンドライン引数に対する実行結果

ビルドして実行ファイルを生成後にコマンドプロンプトから次のようにコマンドライン引数を与えてみましょう。

>C:\LearningC\Project1\Debug\Project1.exe help
---------------------------
足し算:add 10 20
引き算:sub 30 10
---------------------------

>C:\LearningC\Project1\Debug\Project1.exe add 10 20
add:30

>C:\LearningC\Project1\Debug\Project1.exe sub 30 10
sub:20

>C:\LearningC\Project1\Debug\Project1.exe abc
サポートされていないコマンドライン引数です

アプリケーションをリビルドすることなく、実行結果を変化させることができます。