Javaによるプログラミング入門3
キーボードからの入力

 こんにちは。前回は画面への出力を見ました。今回はデータを入力する方法を学びます。Javaは比較的入門し易い言語だと思うのですが、「入力」は、Javaの一番難しい部分を含んでいて簡単ではありません。
 難しいところも簡単に説明しますが、とりあえず「おまじない」と思って進むのがよいと思います。「おまじない」の深い意味はあとで必ず説明します。このような説明方法をよいと思う人、そう思わない人いろいろのようですが、これは信じてください。「プログラムを書いていれば、いずれわかるようになる」のです。逆に、考え込んでとまってしまっては先に進めません。
 また、今回は、ちょっとはりきって2回分くらいの量があります。あまり、いそがずゆっくり読んでください。


 今日は、まず、「コンピュータが名前をきいて、それに答えると、コンピュータがあいさつする」というようなプログラムを考えてみましょう。もちろん、コンピュータは本当に質問したりしませんから、そのように見せかける必要があります。それは前回やったSystem.out.printlnでできそうです。
 しかし、「質問された人」(これからは、「ユーザ」といいます)の入力はどうやって受け取ればよいでしょう。入力を受け取るためには、まず、入力をいれる「いれもの」が必要です。
 実は、名前のような文字の列をいれる「いれもの」は

   String name;

などとして用意することができます。
 ここでStringは、「文字列」などという意味です。こうすると、文字列をいれる「いれもの」が内部的に用意され、それをnameが表すようになっているのです。nameはプログラマがかってに作る「いれもの」の名前なので、なんでもかまいません。ここでは、たまたまnameとしただけです。
 とりあえず、上で述べたプログラムを完成させてみます。以下をみてください。ちょっと難しそうですね。でも、考えるのは解説を見てからにしてください。

//Hello2.java
import java.io.*;
class Hello2
{
    public static void main(String[] args) throws IOException {
        System.out.println("こんにちは。私はコンピュータです。");
        System.out.println("あなたの名前を入力してください。");
        String name;
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        name = br.readLine();

        System.out.println(name + "さん。よろしく。");
    }
}

 とりあえず、プログラムの上の方にある「import java.io.*;」とmainの横にある「throws IOException」のことは忘れて、mainの中を見てください。プログラムの本体は、mainの中にあるのでした。1行目2行目のSystem.out.printlnは画面に字を出力するだけですね。
 そのため、このプログラムをコンパイルして実行すると、まず画面に

こんにちは。私はコンピュータです。
あなたの名前を入力してください。

と出力されます。
 3行目の「String name;」は、上に書いたように、「文字列のいれもの」を用意する行です。これでnameが「文字列のいれもの」を表わすようになるのです。これ自体は、内部の処理なので、画面には何も出力されません。
 mainの4行目5行目はとても複雑そうです。ここが今回の(そして初心者にとっての)最大の山場です。
 Javaでは、いろいろな「もの」を

 種類 名前 = new 種類(条件などなんたらかんたら);

などという形で生成し、それに仕事をしてもらう、ということがよくあります。こう書くと、このような「種類」の「もの」が生成され、それが「名前」で表わされるようになるのです。mainの4行目5行目の

    BufferedReader br =
        new BufferedReader(new InputStreamReader(System.in));

は、実は、1行で書いてもよいのですが、長いので2行になっています。1行にすると、たしかに、上の形と同じですね。よく見るとさらに丸カッコの中にnewがあって入れ子状態になっていますが、はじめは、細かいことは気にしないことにしましょう。とにかく、上の形と同じで、「種類」がBufferedReaderで、「名前」がbrなのです。
 つまり、この行は、BufferedReaderという種類の「もの」を作り、その名前(その「もの」を指すもの)をbrとするということになるのです。ここで、BufferedReaderは、「文字列を受け取る専門家」などという意味です。「バッファという一時的なデータ格納場所を内部に持っている」という意味もあるのですが、今はあまり考えなくてよいと思います。また、右の方で「System.in」とありますが、これは一般にはキーボードという意味です。これにより、brは「キーボードから文字列を読み込む専門家」の「名前」になるのです。
 タイプをするのも面倒だし、意味もよくわからないしでちょっとめげてしまいそうですが、しばらくガマンしてみてください。要するに、こうすると

 brという名前の「キーボードからの文字列読み込みの専門家」

ができるということなのです。なお、brは生成した「専門家」の「名前」です。したがって、これはプログラマが勝手に選んでよいものです。この処理も内部的なものなので、画面には何も出力されません。
 さて、「文字列読み込みの専門家」ができました。あとは働いてもらいましょう。それが6行目の

    name = br.readLine();

です。nameは「文字列のいれもの」を表すのでした。上のように書くことで、brという名前の「専門家」が、キーボードから文字列を読み込み、それをnameで表わされる「文字列のいれもの」に格納してくれるのです。今回は、この一点がわかればいいのです。そう思えば、簡単です...よね。^^;)
 ただし、この行はまずユーザの入力待ちになるので、プログラムを実行すると、いったんここでプログラムがとまります。そして、ユーザが何かを入力すると、それがnameのいれものに格納されるのです。
 すると、すぐに最後の行が実行されてしまいます。これは入れられた名前のあとに続けて、「さん。よろしく。」という文字列をつなぎ、それを出力するものです。したがって、もし、ユーザが「小林」と入力していれば、

小林さん。よろしく。

と画面に出ることになります。以上、なんとなくでもわかったら、実際に試してみてください。プログラムを学ぶ基本は自分で入力し、コンパイルし、実行することです。

Fig.1 Hello2の実行例

 ただし、少し説明していない個所がありました。プログラムの上の方にある「import java.io.*;」とmainの横にある「throws IOException」です。実は、これも初心者には難しいところです。
 入力という作業には、いつも「危険」がともないます。想定外の何かが起こるかもしれないのです。想定外の何かを、一般に、例外と言います。そして、Javaでは、入力を行う場合、「入力時に例外が発生した場合の指示」を書いておかなければならないことになっているのです。そういう決まりなのです。
 そして、その指示がmainの横の「throws IOException」です。この意味は、なんのことはない、「mainの中で、何か入(出)力に関する例外が発生するかもしれないが、もし、発生したら、そこでは何もしないよ」ということです。これでも、「入力時に例外発生場合の処理方法」を書いたことになるので、OKなのです。逆に、これを書かなければ、コンパイル時にエラーになるのです。(このエラーを回避する別法もありますが、本質は同じです。)Javaはそのように作られているのです。
 「throws IOException」のIOExceptionは、「入出力時の例外」というものを表しています。throwsは、「投げ出せ」という程度の意味なのです。

 ところが、実は、このIOExceptionの正式な名前は、java.io.IOExeptionというのです。また、BufferedReaderもjava.io.BufferedReaderといいます。このような長い名前を使ってもよいのですが、面倒ですよね。そこで、短い名前を使いたい場合は、プログラムの上の方に「import java.io.*;」を書けばよいことになっているのです。このようなものをインポート文などといいます。

 結局、まとめると、文字列をキーボードから受け取りたいときは、

import java.io.*;
class クラス名
{
    public static void main(String[] args) throws IOException {
        String ○○;
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        ○○ = br.readLine();
        ...
    }
}

のようにすればよいということなのです。こうすると、...の部分では、○○がユーザの入力した文字列を表すようになるということなのです(上の例では、nameとしました)。ややこしくて嫌ですが、とにかく、基本は同じ形を使うのです。まず、この形を使って、慣れてみましょう。

 なお、Javaでは、メモリ上の「もの」を、オブジェクトなどといいます。上の例で言うと、「文字列のいれもの」や「文字列を受け取る専門家」がオブジェクトです。そして、それらを扱うために用意されたnameやbrのことは変数といいます。(「String name;」のnameはString型の変数、「BufferedReader br = ...」のbrはBufferedReader型の変数などといいます。)

 疲れたら、この辺で一息いれてください。コーヒーでも飲んだり、なんでしたら、続きは明日にでも。初心者にとってはなかなか飲み込みにくい「かたまり」だったと思うのですが、Java初心者は誰もが通る道なのです。そして、(初心者の範囲で)ここまで難しい話はもうありません。


 次に、「ユーザに整数を2回連続で入力してもらい、その合計を表示するプログラム」を書いてみましょう。もちろん、そんなに意味のあるプログラムではありませんが、勉強のためのサンプルプログラムです。「文字列の読み込み」はもうワンパターンとして使ってしまいましょうね。
 たとえば、次のようなプログラムはどうでしょう。(プログラムにコメントをいれる話は前回しました。以後、解説も兼ねたコメントをいれることにします。このコメントはあってもなくてもプログラムの実行には何の関係もないのでした。)

//Sum.java
//実はまちがい
import java.io.*;
class Sum
{
    public static void main(String[] args) throws IOException {
        String temp1, temp2;                 //temp1とtemp2を用意
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        System.out.println("整数を入力してください。");
        temp1 = br.readLine();               //入力をtemp1に受け取る
        System.out.println("整数を入力してください。");
        temp2 = br.readLine();               //入力をtemp2に受け取る
        System.out.println("合計を出力します。");
        System.out.println(temp1 + temp2);
    }
}

 変数は、

    String temp1, temp2;

のようにまとめて用意することができます。つまり、これで「文字列のいれもの」を表わす2つの変数temp1とtemp2ができたことになるのです。
 あとは、ユーザからの入力を続けてこれらに格納し、最後に「temp1 + temp2」を出力しているだけです。どうでしょう。うまくいくでしょうか。実行してみると、次のようになります。

Fig.2 10 + 10 = 1010?

 変ですね。なぜでしょうか。temp1とtemp2は文字列なので「temp1 + temp2」とすると、それらが文字列としてつなげられてしまうのです。
 実は、コンピュータの世界では、たとえば、「10という数字(数を表す文字)の列」と「10という数」はまったく別のものなのです。そして普通の計算ができるのは「数」であって「文字列」ではありません。しかし、br.readLineで読み込むものは「文字列」なのです。実際、temp1とtemp2はString型の変数でした。
 もし、数を扱いたいなら、文字列のいれものではなく、一般には、数のいれものが必要になります。(実は、このプログラムでは、工夫すれば、数の「いれもの」は必要ありません。しかし、必要になるときもあるわけです。)
 整数の「いれもの」は

    int x;

などとして、用意することになっています。ここでintが整数を表し、xが「いれもの」の名前です。「いれもの」の名前は自分でかってにつけてかまいません。このような「基本的なデータのいれもの」も変数といいます。つまり、xはint型の変数というのです。
 そして、「整数を表わす文字列を実際の整数に変換する方法」も用意されています。それは、Integer.parseIntというものです。今の場合、

    x = Integer.parseInt(temp1);

とすれば、「temp1の文字列が表す整数」が、xに格納されることになるのです。これも、とにかく、そういうものなのです。^^;)

 以上を使うと、正しいプログラムは次のようになります。

//Sum.java
//今度は正しい
import java.io.*;
class Sum
{
    public static void main(String[] args) throws IOException {
        String temp1, temp2;                 //temp1とtemp2を用意
        int x, y;                            //xとyを用意
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        System.out.println("整数を入力してください。");
        temp1 = br.readLine();               //入力をtemp1に受け取る
        System.out.println("整数を入力してください。");
        temp2 = br.readLine();               //入力をtemp2に受け取る
        x = Integer.parseInt(temp1);         //temp1の文字列を整数に変換したものをxに格納
        y = Integer.parseInt(temp2);         //temp2の文字列を整数に変換したものをyに格納
        System.out.println("合計を出力します。");
        System.out.println(x + y);           //x + yを出力
    }
}

 ここで、main内最後の行の「System.out.println(x + y);」では、まず整数の足し算「x + y」を計算して、それをまた文字列として出力しているのです。

Fig.3 正しいSum.javaの実行画面

 今回は内容もりだくさんの上「おまじない」もたくさんありました。とにかく、あまり悩んだり、考え込んだりせず、サンプルの形を受け入れ、すこしだけ違ったプログラムを書いて、楽しんでください。そのようにしているうちに、いろいろなことがわかってくるはずです。
 それでは、この辺で。


目次のページ

前のページ  後のページ