パイプラインから入力する
パイプライン「|
」から入力する方法について紹介します。パイプラインから入力するとは、次のような動作のことです。echo 5
./a.out
は階乗を計算します。本記事は、C言語(99)で書いてありますが、他の言語でも同じです。
$ echo 5 | ./a.out
120
パイプラインは標準入力
パイプラインとは、標準出力(stdout
)された結果を標準入力(stdin
)で受け取るものです。
#include <stdio.h>
int main(void)
{
const int Max = 32;
char buf[Max];
fgets(buf,Max,stdin);
fputs(buf,stdout);
return 0;
}
$ echo 'hello, world!' | ./a.out
hello, world!
$ echo '5 * 3' | ./a.out | bc
15
標準出力された5 * 3
を./a.out
がfgets()
で取得しfputs()
した標準出力をbc
が標準入力で受け取っています。
複数の値を受け取る
複数の値は、fgets()
で行を受け取り、strtok()
でトークンに分解します。フォーマットが決まっているならsscanf()
でもいいかもしれません。
次のコードは、半角スペース区切りで渡された要素数を数えます。
#include <stdio.h>
#include <string.h>
int main(void)
{
// 標準入力
const int Max = 64;
char buf[Max];
fgets(buf,Max,stdin);
// 区切り文字をトークンに分解
char *delim = " ";
int len = 0;
char *p;
p = strtok(buf, delim);
while (p != NULL){
// トークンが空なら終了
if (*p == '\n') {
break;
}
p = strtok(NULL, delim);
++len;
}
printf("%d\n", len);
return 0;
}
$ echo 1 23 45 asdf | ./a.out
4
$ echo ' 1 23 45 as df ' | ./a.out
5
$ echo ' ' | ./a.out
0
コマンドライン引数にも対応
パイプラインだけではく、コマンドライン引数にも対応させます。今回は、argc
が1
(実行コマンド名)ならばパイプライン、それ以外をコマンドライン引数で処理するようにしました。コマンドライン引数については「自作関数の考え方と設計について」を参照ください。
#include <stdio.h>
#include <string.h>
enum {
_STDIN = 1,
};
static void showNumPipeElem(void);
int main(int argc, char *argv[])
{
// argcが1ならパイプ、それ以外なら引数
switch (argc) {
default:
printf("%d\n", argc - 1);
break;
case _STDIN:
showNumPipeElem();
break;
}
return 0;
}
static void showNumPipeElem(void)
{
const int Max = 64;
char buf[Max];
fgets(buf,Max,stdin);
char *delim = " ";
int len = 0;
char *p;
p = strtok(buf, delim);
while (p != NULL){
if (*p == '\n') {
break;
}
p = strtok(NULL, delim);
++len;
}
printf("%d\n", len);
}
$ echo a b | ./a.out
2
$ ./a.out ab cd ef
3
パイプライン、コマンドライン引数の両方に対応しているのが分かります。