C言語 補足①

コマンドライン引数について

コマンドラインは、WindowsのコマンドプロンプトやLinuxのターミナルなど、キーボードからコマンドを入力し実行するためのユーザーインターフェイスです。
そして、コマンドライン引数とは、実行するコマンドに渡される値のことを指します。

たとえば、Windowsではファイルをコピーするコマンドとしてcopyコマンドが用意されています。

copy hoge.txt c:\temp

と記述するとhoge.txtがtempフォルダにコピーされます。
copyがコマンドで、hoge.txtおよびc:\tempがコマンドライン引数です。
copyコマンドは以下のようにコマンドライン引数が定義されています。

copy [/d] [/v] [/n] [/y | /-y] [/z] [/a | /b] <source> [/a | /b] [+<source> [/a | /b] [+ ...]] [<destination> [/a | /b]]

https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/copy

コマンドライン引数の利点は以下の通りです。
  1. ユーザーが実行時に値を指定できるので、同じプログラムを異なる入力で容易に実行することが可能です。
  2. プログラムの自動実行やバッチ処理が容易になることで、複雑な処理、定期的なタスク、そして大量データの処理を自動化することが可能です。
  3. テストケースを容易に切り替えることで、様々な入力値に対するプログラムの動作を素早く確認することができます。
  4. コマンドライン引数の使用により、パスワードやその他の機密情報をコード内に直接記述する必要がなくなります。

C言語での記述の方法

コマンドライン引数を受け取るには、main()関数を以下のように定義します。

int main(int argc,char* argv[])

int argc:コマンドライン引数の総個数(実行ファイル名も含まれる)
char* argv[] : 引数の文字列を指すchar型のポインタの配列

以下のプログラムは、コマンドライン引数を受け取り、その引数の数と内容を出力するサンプルです。

#include <stdio.h>

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

実行名をargc.exeとしてコンパイルします。
gcc argc.c -o argc

コマンドライン引数を指定しないで実行します。

C:\C\argc>argc

実行結果
argc:1
0:argc

コマンドライン引数に5個引数を指定して実行してみます。

C:\C\argc>argc aaa bbb ccc ddd eee

実行結果
argc:6
0:argc
1:aaa
2:bbb
3:ccc
4:ddd
5:eee

これは、以下の図に示されているように、引数が渡されたことを意味します。
argvは文字列へのポインタを表します。各文字列のアドレスは、例として1000、2000、3000、4000、5000、6000とします。(※これらは実際のアドレスではありません)

では、コマンドライン引数を使用して、整数の和を計算するサンプルプログラムを実行してみましょう。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

long int add(long int a,long int b){
	return a + b;
}

int toInt(const char* str,long int *num){
	char *endp;
	long int number;
	errno = 0;
	
	number = strtol(str,&endp,10);
	if(endp == str){
		fprintf(stderr,"%sは数値に変換できません\n",str);
	} else if(errno !0){
		if(errno == ERANGE){
			if(number == LONG_MAX){
				fprintf(stderr,"%sは範囲を超える値です\n",str);
			}else if(number == LONG_MIN){
				fprintf(stderr,"%sは範囲を下回る値です\n",str);
			}
		}
	} else{
		*num = (int)number;
		return EXIT_SUCCESS;
  	}
	 return EXIT_FAILURE;
}

int main(int argc,char* argv[]){
	long int x,y;
	int ret;
	long int a;
	
	if(argc<3){
		printf("usage:argc : %s integer integer \n",argv[0]);
		return 1;
	}

	ret = toInt(argv[1],&x);
	if(ret == EXIT_FAILURE){
		return 1;
	}
	ret = toInt(argv[2],&y);
	if(ret == EXIT_FAILURE){
		return 1;
	}
	printf("%ld + %ld = %ld\n", x,y,add(x,y));
	
	return 0;
}

実行結果
C:\C\argc>argc 5 aaa
aaaは数値に変換できません

C:\argc>argc 5 -2147483649
-2147483649は範囲を下回る値です

C:\C\argc>argc 5 -2147483648
5 + -2147483648 = -2147483643

C:\C\argc>argc 5 2147483648
2147483648は範囲を超える値です

C:\C\argc>argc 5 1000000000
5 + 1000000000 = 1000000005

コマンドライン引数は文字列として受け取られるため、整数の合計を計算するには、文字列を整数に変換する必要があります。
この例では、文字列を整数に変換するtoInt()関数を作成しました。
toInt()関数内部ではC言語の標準ライブラリ関数strtol()関数を使用しています。
strtol() 関数は、引数の文字列を数値に変換できない場合や、long int 型の範囲を超える場合にエラーを返します。
なお、strtol()関数については、補足②で説明しています。

atoi()関数は文字列を整数に変換するために存在しますが、現在は推奨されていない関数です。これは、エラー検出がないためで、strtol()関数のような代替関数がより安全なエラー処理機能を提供するからです。
【参考】INT06-C. 文字列トークンを整数に変換するには strtol() 系の関数を使う

コメント

この記事へのコメントはありません。

関連記事

C言語でフレーム可変データセット 前編

C言語 応用編 ~6日目~

C言語でデータ制御 後編

PAGE TOP