JavaScript (Spidermonkey) 標準入力のエラー回避の方法について

要旨

JavaScript(Spidermonkey)ではバージョンにより、readline()メソッドにバグがあり、標準入力が正しくできない場合がある。
これへの対処方法の紹介。
(但し根本的な解決にはならない)

注意点

バージョンの違いによるエラーの有無について

Spidermonkeyのバージョンの違いにより今回の記事で取り上げるreadline()メソッドに関するエラーの有無がある。
それをまとめたものが以下の表。

version 使用しているサービスの例 エラーの有無
spidermonkey-1.7 CodeIQ 「実行くん」 企業版ideone エラー有り
spidermonkey 24.2 コンシューマー版 ideone.com エラー無し

例えば、コンシューマー版ideoneで問題がなかったとしても、「実行くん」と同じ企業版ideoneを使用しているCodeIQに同じコードを提出した時に、意図した通りの動作をしない可能性がある。(記事公開時点での状況)
上記の表の通り、Spidermonkeyのバージョンが 24.2 以降の環境の場合はreadline()メソッドのバグによるエラーは無く、この記事の内容は無視してよい。

f:id:ibeckuu:20160321212215j:plain
コンシューマー版ideoneの例。 正しく動作している。

エラーの現象について

readline()メソッドを使用した時に起こり得るエラーの現象は次の2点

  1. 標準入力から入力された文字列の最後に改行文字が無い場合は最後の文字が入力されない。
  2. 複数行の入力の場合、EOFを検知できないので入力待ちの状態で止まる。

上記のいずれのエラーもバージョンが古い場合、Spidermonkeyを使用しない以外に根本的な解決策は無い。
(Rhino で標準入力を使用する場合はこちらを)

それでも、コードゴルフなどで、Rhino/Node.js等では記述が多く使いたくないなど、どうしてもSpidermonkeyを使いたい場合の対処方法を下記に述べる。

1.文字列の最後に改行文字が無い場合、最後の文字が入力されないエラーへの対処

リダイレクト、パイプ等で標準入力に渡すデータを自分でチェックできる場合は、文字列が改行文字で終わっている様にすれば良い。
readline()メソッドは文字列を改行文字が検出されるまで読み込み、改行文字の有無に関わらず、最後の文字を捨てている('\0'に置き換えている?)様に実装されていると思われる。

f:id:ibeckuu:20160321212853j:plain
文字列の最後に改行文字がある場合


以下の様に、文字列の最後に改行文字が付加されていない場合は文字列の最後の文字が正しく読み込まれないので、正しく処理できない。
CodeIQへのコードの提出の場合など、入力の最後に改行文字が間違いなく付加されているか確認できない場合はreadline()メソッドを使用してSpidermonkeyを使用する事は諦めざるを得ない。

f:id:ibeckuu:20160321212951j:plain
文字列の最後に改行文字がない場合


2.EOFを検知できないエラーへの対処

複数行の入力がある場合、readline()メソッドはEOF(入力の終わり)を検知できないので、
while((str=readline())!==null){
というコードを書くと、最終行を読み込んだ後、ずっと入力待ちの状態になり処理が止まる。
見かけ上処理が実行中なのか、入力待ちで止まっているのか分からない為、実行時間制限がある場合でタイムアウトした時に、実装の不備と思って間違った方向で悩む事があり得る。

f:id:ibeckuu:20160321213423j:plain


複数行の入力がある場合で、行数が分かっている場合は下記の様にループの回数を指定して記述すれば問題ない。
(但し、この場合も最後の行が改行文字が終わっていなければ最後の文字を正しく読み取れないエラーは発生する)

f:id:ibeckuu:20160321213517j:plain

複数行の入力で入力の行数が分からない場合はSpidermonkeyの使用を諦めざるを得ない。

以上。
では、

Sponsored Link