「標準入力から二つの数を読込んで、和、差、積、商を計算して、 標準出力に出力せよ。」という例題は、Fortran, Pascal, C, C++ などでは、 よく取り上げられる。
C の場合、入門書には、次のような scanf() を用いた プログラムが載っている。
readwrite1.c |
1 /* 2 * readwrite1.c 3 */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 double a, b, wa, sa, seki, syou; 10 printf("二つの数を入力してください: "); 11 scanf("%lf%lf", &a, &b); 12 wa = a + b; 13 sa = a - b; 14 seki = a * b; 15 syou = a / b; 16 printf("和=%g, 差=%g, 積=%g, 商=%g\n", wa, sa, seki, syou); 17 return 0; 18 } |
ここで詳しい理由の説明はしないが3、 scanf() をこのように使うのは良くないとされている 4(ある意味で scanf() は悪名高い関数である)。 入力を文字列として読んでから、文字列を解析することが推奨されている。 例えば以下のプログラムのようになる。
readwrite2.c |
1 /* 2 * readwrite2.c 3 */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 char buf[BUFSIZ]; 10 double a, b, wa, sa, seki, syou; 11 printf("二つの数を入力してください: "); 12 /* 一行読込む */ 13 fgets(buf, sizeof(buf), stdin); 14 /* buf[] の内容を sscanf() で解析する */ 15 if (sscanf(buf, "%lf%lf", &a, &b) != 2) { 16 fprintf(stderr, "Input Error\n"); 17 exit(1); 18 } 19 wa = a + b; 20 sa = a - b; 21 seki = a * b; 22 syou = a / b; 23 printf("和=%g, 差=%g, 積=%g, 商=%g\n", wa, sa, seki, syou); 24 return 0; 25 } |
さて、Java ではどうするか?実は初心者には結構な難題である。 Java には scanf() も sscanf() も存在しない。 これは scanf 系の関数が複雑過ぎるというのが一つの理由であろう (色々なエラーが起こり得るものを一つの関数に押し込めると、 エラーの解析が大変である)。 もう一つは、 Java の主たる応用では、 ユーザー・インターフェイスは標準入出力よりは GUI であり、 もともと複雑な入力を解析する必要性が低いためであろう5。
一行に一つの数値しかないのであれば、 次の ReadWrite1.java のように、 readLine() メソッドを使って文字列として読込み、 Double.valueof().doubleValue(文字列) を 使って double の値に変換する 6、 というコードが考えられる (これはまあまあ簡単である)。 (try 〜 catch 構文については後述する (予定は…)。)
ReadWrite1.java |
1 /* 2 * ReadWrite1.java 3 */ 4 5 import java.util.*; // StringTokenizer 6 import java.io.*; // BufferedReader 7 8 public class ReadWrite1 { 9 public static void main(String args[]) { 10 double a, b, wa, sa, seki, syou; 11 12 BufferedReader d = new BufferedReader(new InputStreamReader(System.in)); 13 try { 14 System.out.print("数を入力してください: "); 15 a = Double.valueOf(d.readLine()).doubleValue(); 16 System.out.print("数を入力してください: "); 17 b = Double.valueOf(d.readLine()).doubleValue(); 18 wa = a + b; 19 sa = a - b; 20 seki = a * b; 21 syou = a / b; 22 System.out.println("和=" + wa + ", 差=" + sa 23 + ", 積=" + seki + ", 商=" + syou); 24 } 25 catch(IOException e) { 26 System.out.println("IO Error"); 27 System.exit(1); 28 } 29 } 30 } |
一行の入力に二つ以上の数値を含める場合には、 一つの数を表わす文字列を切り出してから、 Double.valueof().doubleValue() を使って double の値に変換する、 という手順になる。 文字列の切り出しには StringTokenizer を用いる。 まとめると、次の ReadWrite2.java のようになる。
ReadWrite2.java |
1 /* 2 * ReadWrite2.java 3 */ 4 5 import java.util.*; // StringTokenizer 6 import java.io.*; // BufferedReader 7 8 public class ReadWrite2 { 9 public static void main(String args[]) { 10 double a, b, wa, sa, seki, syou; 11 System.out.print("二つの数を入力してください: "); 12 13 BufferedReader d = new BufferedReader(new InputStreamReader(System.in)); 14 try { 15 String str = d.readLine(); 16 StringTokenizer aSt = new StringTokenizer(str," "); 17 if (aSt.countTokens() != 2) { 18 System.out.print("Input Error\n"); 19 System.exit(1); 20 } 21 a = Double.valueOf(aSt.nextToken()).doubleValue(); 22 b = Double.valueOf(aSt.nextToken()).doubleValue(); 23 wa = a + b; 24 sa = a - b; 25 seki = a * b; 26 syou = a / b; 27 System.out.println("和=" + wa + ", 差=" + sa 28 + ", 積=" + seki + ", 商=" + syou); 29 } 30 catch(IOException e) { 31 System.out.println("IO Error"); 32 System.exit(1); 33 } 34 } 35 } |
ReadWrite1, ReadWrite2 の実行 |
1 yurichan% java ReadWrite1 2 数を入力してください: 12.34 3 数を入力してください: 56.78 4 和=69.12, 差=-44.44, 積=700.6652, 商=0.2173300457907714 5 yurichan% java ReadWrite2 6 二つの数を入力してください: 12.34 56.78 7 和=69.12, 差=-44.44, 積=700.6652, 商=0.2173300457907714 8 yurichan% |
この結果の表示を「何か汚いように感じる」人のために次の小節がある。