倭算数理研究所

科学・数学・学習関連の記事を、「倭マン日記」とは別に書いていくのだ!

2.4 True BASIC のプログラム product2

今回はコマンドラインから入力を受け付けられるようにするプログラムを見ていきます。 Groops では今のところコマンドラインからの入力を受け付けるような機構をサポートする予定はありませんが、Groovy (と Java)の API を使えば実装するのは難しくありません。

True BASIC

True BASIC では、コマンドラインからの入力は INPUT 文で書きます:

PROGRAM product2
INPUT m
INPUT prompt "acceleration a (mks units) = ": a
LET force = m*a
PRINT "force (in Newtons) = "; force
END

「INPUT prompt」で入力を促すメッセージも書けます。

Groovy

Groovy で上記のコードを書くと、以下のようになります:

System.in.withReader{
    double m = it.readLine().toDouble()    // readLine() で返されるのは Strnig オブジェクト
    println 'accelerration a (mks units) = '
    double a = it.readLine() as double    // 「as double」でも double 型に変換可能
    println "fource (in Newtons) = $force"    // 「force (in Newtons) = 8.0」と表示される
}
  • Groovy では、コマンドラインからの入力は「System.in.withReader{ it.readLine() }」とするのが定型文のようです。 ここに結構いろいろ凝縮されてますけど、簡単に説明すると
    • System.in は標準入力を表す InputStream オブジェクト (Java)。
    • InputStream#withReader() メソッド*1は Groovy が InputStream に追加したメソッド。 引数にクロージャをとり(withReader({ it.readLine() }) と同じ)、このクロージャの処理を行った後、InputStream のクローズ処理も実行する。
    • { と } で囲まれた部分は Groovy のクロージャ。 大雑把に言うと、処理をオブジェクト化したもの。 この中の it 変数は特別で、今の場合、System.in に対応する Reader*2 が割り当てられている。
  • Reader#readLine() (上記の it.readLine())はコマンドラインから String オブジェクトを読み込む。 コード中では読み込んだ文字列を数値として扱いたいので、以下の方法のどちらかを使って Double 型に変換する必要がある:
    • String#toDouble() メソッド(Groovy が String オブジェクトに追加したメソッド
    • as キーワードを使って「as double」とする
  • Groovy では、Java と違ってシングルクォートで挟んだ部分 ('...') も文字列として扱われる。 ダブルクォート ("...") で挟んだ部分は GString として扱われ、「$force」の形で変数の値を参照することができる。

True BASIC のコードと比べてちょこっと追加コード(String から double への変換とか)がありますが、まぁそんなに大差ないですね。

java.util.Scanner オブジェクトを使う

上記では Groovy の定型文「System.in.withReader{ it.readLine() }」を使いましたが、java.util.Scanner クラスを使うと型変換をする必要がないのでちょっと楽かも。 あんま変わんないかも。

def scan = new Scanner(System.in)    // java.util.Scanner オブジェクトを生成
double m = scan.nextDouble()
println 'accelerration a (mks units) = '
double a = scan.nextDouble()
double force = m*a
println "force (in Newton) = $force"    // 「force (in Newtons) = 8.0」と表示される
  • Groovy は java.io パッケージや java.util パッケージを自動で import するので、これらのパッケージ内の import 文は必要ありません。
  • Scanner#nextDouble() メソッドで読み込んだ文字列を double に変換して返します。 他のプリミティブ型に対応するメソッドもあります。

Scanner オブジェクトは、普通は使用後にクローズ処理(Scanner#close() を呼び出す)が必要ですが、標準入力は閉じない方がいいのでここでは省略してます。 もしクローズ処理をしたいなら、Java SE 7 の try-with-resources 文を使うのもいいかもしれません。

プログラミングGROOVY

プログラミングGROOVY

計算物理学入門

計算物理学入門

  • 作者: ハーベイゴールド,ジャントボチニク,Harvey Gould,Jan Tobochnik,鈴木増雄,石川正勝,溜渕継博,宮島佐介
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本
  • 購入: 1人 クリック: 28回
  • この商品を含むブログ (45件) を見る

*1:InputStream クラスの withReader() メソッドを「InputStream#withReader()」のように書きます。 JavaDoc 起源だったかな。

*2:これは Java の話ですが、InputStream と Reader は用途としては似たものですが、読み込むものが byte か文字 (int) かの違いがあります。 ザックリ言えば、InputStream と文字セット(byte と文字の対応、文字エンコーディング)をまとめたものが Reader です。 と言っても、InputStream クラスと Reader クラスに継承関係などはありませんが。