【Node.js】標準入力の「?」がうまく読み込まれない

とある課題で、標準入力に「1 + 2」のように来たら1+2の結果を出力、「1 – 2」が来たらその結果を出力、「1 ? 2」のように来たら処理を終了するプログラムを作成することになった。

標準入力というと、fsモジュールでの読み込みを主としていたので、下記のように実装した。

let input = require("fs")
  .readFileSync("/dev/stdin", "utf-8")
  .split('\n');
let idx = 0;

while (true) {
  let [a, op, b] = input[idx].split(' ');
  let result = 0;

  if (op === "?") {
    break;
  } else {
    switch (op) {
      case "+":
        result = Number(a) + Number(b);
        break;
      case "-":
        result = Number(a) - Number(b);
        break;
      case "*":
        result = Number(a) * Number(b);
        break;
      case "/":
        result = Math.floor(Number(a) / Number(b));
        break;
    }
    console.log(result);
  }
}

ところが、「1 + 2」や「1 / 2」などは正常に動作するのだが、?が来た場合のみうまく動作しない、、、。

ということで標準入力の仕方を変更した。コードは下記の通り。

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

let lines = [];

rl.on('line', (line) => {
  lines.push(line);
});

rl.on('close', () => {
  // ここで lines に全ての入力が格納されています
  let idx = 0;
  while (true) {
    let [a, op, b] = lines[idx].split(' ');
    let result = 0;

    if (op === "?") {
      break;
    } else {
      switch (op) {
        case "+":
          result = Number(a) + Number(b);
          break;
        case "-":
          result = Number(a) - Number(b);
          break;
        case "*":
          result = Number(a) * Number(b);
          break;
        case "/":
          result = Math.floor(Number(a) / Number(b));
          break;
      }
      console.log(result);
    }
    idx++;
  }
});

これまでfsモジュールばかり使用していたので見慣れない部分が多いため備忘のため残す。

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

readlineモジュールをインポートし、標準入力(process.stdin)と標準出力(process.stdout)を使用してreadlineインターフェースを作成する。terminal: falseとすることで、対話モードを無効にしている。

let lines = [];

rl.on('line', (line) => {
  lines.push(line);
});

lineイベントが発生するたび(つまり、新しい行が標準入力から読み取られるたび)に実行されるコールバック関数を設定している。このコールバック関数は受け取った行をlinesという配列に追加する。

rl.on('close', () => {
  // ここで lines に全ての入力が格納されています
  // ... [省略]
});

closeイベントは、標準入力が閉じられたとき(例えば、Ctrl+Dが押されたときや入力が終了したとき)に発生する。このイベントが発生したとき、lines配列には全ての入力行が格納されている。

少々理解に時間がかかったのはrl.on('line',(line)=>{....}の部分。’line’はイベント発火のトリガーで、(line)はアロー関数の引数(新しい行のこと)。その引数をlines配列に格納していく。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次