argc, argv, scanf, fscanf
次は,標準入力です。標準入力には,コマンドラインからの入力と相手にたずねる場合の2通りがあります。
■コマンドラインからの入力
int main(int argc, char *argv[]) { /* 本体 */ }
変数 argc
には,コマンドラインに入力(標準入力)された文字列の個数(argument count)が入ります。また,argv[argc]
は NULLポインタ(空ポインタ)であり,argc
が 0
より大きい場合,argv[0]
にはプログラム名が入ります。[C99, 5.1.2.2.1](argv
は「ポインタの配列」です。)例えば,
% ./a.out this is a test.
と実行した場合,argc = 5
となり,argv[0]
には ./a.out
,argv[1]
には this
,そして以下順番に argv[2]
に is
,argv[3]
に a
,argv[4]
に test.
が入り,そして argv[5] = NULL
となります。
/* Example 13.3 */ #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) printf("argv[%d] = %s\n", i, argv[i]); return 0; }
実行例です。(太字部分が入力箇所です。)
% ./a.out this is a test. argv[0] = ./a.out argv[1] = this argv[2] = is argv[3] = a argv[4] = test.
■相手にたずねる場合
ライブラリ stdio.h
には入力用に用意された関数も多数あります。次はそのごく一部です。
関数(プロトタイプ:2段目) | 入力元 |
fscanf(ストリーム, フォーマット, 記憶先のアドレス) | ストリーム |
scanf(フォーマット, 記憶先のアドレス) | 標準入力 |
sscanf(char型配列, フォーマット, 記憶先のアドレス) | char 型配列 |
これらは printf
関数系の入力版です。返却値は記憶された個数です。フォーマット 内に指定する変換指定子は,double
型変数の読み込みの場合に限り %lf
を使用することを除き,printf
で見た変換指定子が使えます。その他には,UNIXにおける正規表現と同じ変換指定子もあります。
■その他の変換指定子 | ||
nd | d で n 桁の読み込み,または出力。d は f などにも適用可。 | printf 系,scanf 系の双方。 |
.nf | f で小数点 n 桁の出力。 | printf 系のみ。 |
[a-n] | 文字 a から n に適合する場合 | scanf 系のみ。 |
[^a-n] | 文字 a から n に適合しない場合 | scanf 系のみ。 |
* | 適合するものをスキップ | scanf 系のみ。 |
/* Example 13.4 */ #include <stdio.h> int main(void) { int n = 0, s = 0; double x = 0.0; char str[12] = "\x00"; s = scanf("%4d%lf%11s", &n, &x, str); printf("n = %d, x = %f, str = %s (%d)\n", n, x, str, s); return 0; }
%4d
は数字4桁までを n
に格納します。%lf
は double
型データへの格納です。%11s
は文字列のうち11文字までを str
へ格納します。これは sizeof(str)
が 12
なので,バッファ・オーバーフローを起こさないためです。
実行例です。丸括弧内の数値は scanf
の戻り値です。(太字部分が入力箇所です。)
% ./a.out 123456ABC n = 1234, x = 56.000000, str = ABC (3) % ./a.out 123.456ABC n = 123, x = 0.456000, str = ABC (3) % ./a.out 12 3.456 ABC n = 12, x = 3.456000, str = ABC (3)
付言すると,「10.1. 配列型とメモリ領域」で見たように,配列型(式)str
は配列の第1要素を指し示すポインタであり,scanf
の第2変数以降はすべてアドレスを指定しています。
/* Example 13.5 */ #include <stdio.h> #include <string.h> int main(void) { int s = 0; char x[4], y[4], z[4]; memset(x, 0, sizeof(x)); memset(y, 0, sizeof(x)); memset(z, 0, sizeof(x)); s = fscanf(stdin, "%3[a-z]%*[a-z]%3[A-Z]%*[A-Z]%3[0-9]", x, y, z); printf("x = %s, y = %s, z = %s (%d)\n", x, y, z, s); return 0; }
この例では,配列 x
,y
,z
が3文字までのため,4文字目以降の該当文字列を切り捨てる(次の配列に読み込まれない)ように %*[ ]
で余分な文字列をスキップします。しかしながら,もし該当の文字列が3文字以内の場合,残りは捨てられます。
% ./a.out opqrstuVWXYZ98765 x = opq, y = VWX, z = 987 (3) % ./a.out abcdeABC0123 x = abc, y = ABC, z = (2)