0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

process.stdout.write() の罠?!:バッファリング問題と解決法

Posted at

僕がPaizaの出力問題を解いてるとき、あることに気づいた。小さな入力だとサクサク動くのに、大きな数字を入れると出力が途中で消えちゃう…!?その原因は、Node.jsのprocess.stdout.write()に潜むバッファリング問題なるものかも?!今回はその問題と解決策をシンプルに紹介するよ!

問題概要

与えられた H, W, A, B を使って、H×W(A, B) の表を作成せよ。横は|区切り、縦は=で区切る。ただし、縦の区切り線は上の行と同じ長さにすること!


入力:

2 3 7 8  

出力:

(7, 8) | (7, 8) | (7, 8)  
=======================  
(7, 8) | (7, 8) | (7, 8)  


バッファリングの罠

最初はprocess.stdout.write()を使って出力してたんだけど、小さい数字だと問題なく動いてたのに、大きい数字(例えば 92 79 7 8)だと出力が途中で消えちゃう…!これがバッファリングの問題かもしれない(´;ω;`)


バッファリングって何?

簡単に言うと、バッファリングは大量のデータを一時的にメモリにためてから出力する仕組み。でも、このせいで、ループ内で何度もstdout.write()を使うと、バッファがいっぱいになっちゃって、出力が途切れることがあるんだ。


NG例: process.stdout.write() を使いすぎるとどうなる?

まず、これがNGなコード。process.stdout.write()を使いすぎて、出力が途切れる原因になってる。

const rl = require('readline').createInterface({ input: process.stdin });

rl.on('line', (input) => {
    const [H, W, A, B] = input.split(" ").map(Number);
    for (let i = 1; i <= H; i++) {
        for (let j = 1; j <= W; j++) {
            if (j === W) {
                process.stdout.write(`(${A}, ${B})\n`);
            } else {
                process.stdout.write(`(${A}, ${B}) | `);
            }
        }
        if (i !== H) {
            console.log("=".repeat(W * (4 + W - 1 + String(A).length + String(B).length)));
        }
    }
     rl.close();
});

このコードだと、大きな入力値を処理する際にバッファが溢れて、途中で出力が途切れちゃうんだ。


解決策:console.log()とArray.from()を使ってスッキリ解決

バッファリング問題を回避しつつ、コードをもっとシンプルにする方法がある!

console.log()を使えば、バッファリングの影響を受けずに安定した出力が得られるし、Array.from()を使うとコードがめっちゃスッキリするよ。


OK例:console.log()とArray.from()を活用

const rl = require('readline').createInterface({ input: process.stdin });

rl.on('line', (input) => {
    const [H, W, A, B] = input.split(" ").map(Number);
    const row = Array.from({ length: W }, () => `(${A}, ${B})`).join(" | ");
    const separator = "=".repeat(row.length);

    console.log(Array.from({ length: H }, () => row).join("\n" + separator + "\n"));
});

これで、バッファリング問題を回避しつつ、コードがスッキリした!
Array.from()を使うことでループもシンプルになって、可読性も向上。


改善ポイント

  • process.stdout.write()はバッファリングの影響を受けやすいから、console.log()を使ったコードを考えてみよう。
  • Array.from()を使うと、2重ループなしでスッキリコード!
  • repeat()を使えば区切り線の計算も楽々!


まとめ

Paizaの問題を解いてると、意外なところでバグに遭遇することもある。でも問題をしっかり理解すれば、簡単に解決策が見つかるよ。console.log()Array.from()を活用して、コードをスッキリさせよう!🚀


僕の失敗談と解決話!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?