作曲・指導・C言語・Linux

金沢音楽制作

金沢音楽制作では、楽曲・楽譜の制作と、作曲や写譜などレッスンを行っています。

パイプラインから入力する

パイプライン「|」から入力する方法について紹介します。パイプラインから入力するとは、次のような動作のことです。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.outfgets()で取得し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

コマンドライン引数にも対応

パイプラインだけではく、コマンドライン引数にも対応させます。今回は、argc1(実行コマンド名)ならばパイプライン、それ以外をコマンドライン引数で処理するようにしました。コマンドライン引数については「自作関数の考え方と設計について」を参照ください。

#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

パイプライン、コマンドライン引数の両方に対応しているのが分かります。

更新情報