法大奥山研究室

 previous  contents

13.2. 標準入力:argc, argv, scanf, fscanf


 次は,標準入力です。標準入力には,コマンドラインからの入力と相手にたずねる場合の2通りがあります。

■コマンドラインからの入力

int main(int argc, char *argv[]) { /* 本体 */ }

変数 argc には,コマンドラインに入力(標準入力)された文字列の個数(argument count)が入ります。また,argv[argc] は NULLポインタ(空ポインタ)であり,argc0 より大きい場合,argv[0] にはプログラム名が入ります。[C99, 5.1.2.2.1](argv は「ポインタの配列」です。)例えば,

% ./a.out this is a test.

と実行した場合,argc = 5 となり,argv[0] には ./a.outargv[1] には this,そして以下順番に argv[2]isargv[3]aargv[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(ストリーム, フォーマット, 記憶先のアドレス)
int fscanff(FILE * restrict stream, const char * restrict format,...);
ストリーム
scanf(フォーマット, 記憶先のアドレス)
int scanf(const char * restrict format,...);
標準入力
sscanf(char型配列, フォーマット, 記憶先のアドレス)
int sscanf(char * restrict s, const char * restrict format,...);
char型配列

これらは printf関数系の入力版です。返却値は記憶された個数です。フォーマット 内に指定する変換指定子は,double型変数の読み込みの場合に限り %lf を使用することを除き,printf で見た変換指定子が使えます。その他には,UNIXにおける正規表現と同じ変換指定子もあります。

■その他の変換指定子
nddn 桁の読み込み,または出力。df などにも適用可。printf系,scanf系の双方。
.nff で小数点 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 に格納します。%lfdouble型データへの格納です。%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;
}

この例では,配列 xyz が3文字までのため,4文字目以降の該当文字列を切り捨てる(次の配列に読み込まれない)ように %*[ ] で余分な文字列をスキップします。しかしながら,もし該当の文字列が3文字以内の場合,残りは捨てられます。

% ./a.out
opqrstuVWXYZ98765
x = opq, y = VWX, z = 987 (3)
% ./a.out
abcdeABC0123
x = abc, y = ABC, z =  (2)

 previous  contents