第4回目-2002/11/11

Java文法の基本(制御構造)


文字列を扱う

テキストのp80〜84を自分でやってみてください。

テキストについては話題がたくさんあるのですが、おいおい学習することにして、ここでは単純に、数値と同じような雰囲気で文字列も扱えると理解してくれればOKです。

配列

テキストp85〜86を自分でやってみてください。

配列は便利なのですが、実は理解するのが大変な概念でもあります。ここではいちばん単純なところだけを理解してくれるのでOKです。

ところで、プログラミングの本などでは初心者レベルで配列の話がけっこう掲載されているのですが、実はJavaでは配列を完全に理解するというのはかなり高度な知識が必要になります。特に、2次元以上の配列というものは、オブジェクト指向が理解していないとわからないと思います。ここでは、1次元のものだけの理解でかまいません。また、こうした集合的なデータを扱う方法は配列以外に実に多彩な機能をJavaでは利用できますし、実用的なプログラミングではむしろそうした配列以外の方法を使うことの方が多いでしょう。

繰り返しと条件判断

p87〜94を自力でやってみましょう。

p95〜97の話は自分で読んでおいてください。ただ、理解はしにくいかと思います。ここでは、同じ文字列かどうかの判断って、とっても難しい・・・ということを覚えておいてくれればそれでOKです。


練習問題

4-1:ある整数を変数numberに入力する。その数が奇数か偶数かを標準出力に表示せよ。そのとき、たとえば、ある数値が13なら、「13は奇数です」といった風に表示されるようにすること。

ヒント:10 + "は数値です" の結果はStringになる。つまり、10を、文字列の"10"として処理してくれる。

検討課題:numberに代入する数をいろいろ変更して、結果を見てみること。

4-2:フラグというテクニック。以下のようなプログラムを作ること。目的は「奇数で、5の倍数でないものなら、ビンゴ!と表示し、そうでないならはずれー!と表示する」ということにする。(数学的な意味はほとんどないので、単なる練習問題として深く考えないように)

補足:どこかで判断した結果を別のところで使いたい場合、こうしたフラグ変数は便利である。一般にフラグはbooleanを使うが、これだとtrue/falseの2通りのみである。たとえば、3通りの結果をある変数に記録したい場合には、byteやshortなどの整数型を使う。ただ、3通りだと、byteでいいが、条件式で使うことを考えれば、効率的ではなくてもint型を使ったほうが悩まなくてすむということにもつながる。

4-3:4-2のプログラムをフラグ変数を使わないで作成してみること。

ヒント:条件文で&&を使うと・・・

4-4:ある整数を変数numberに入力する。その数が素数かどうかを判断して、判断結果を表示すること。

ヒント:素数とは、1とその数以外に割り切れる整数がない数のこと。たとえば、3,5,7,11...。ということは、たとえば、13が素数かどうかを判断するには、2,3,4,5,6....12までの数値で順番に剰余を求めてみて、もし、剰余が0になる数字があれば、その数は素数ではないと言える。ただ、効率の上では、2で割り切れないのに、4で割り切れるはずはない。また、13の場合だと、7以上の数値で割り切れるわけではないので、その意味では、2〜(その数の半分)までをチェックするということでことは足りる。ただ、そこまでの機能を組み込んでもいいし、組み込まなくてもいい。まずは正しい結果が得られるようにがんばってみよう。

ヒント:フラグを使う。

 


解答

練習問題4-1

奇数かどうかという判断は、2で割ったあまりが1かどうかで判断できる。つまり、1なら奇数、2なら偶数。以下のプログラム例は、「2で割ったあまりが0であるなら」という条件判断にしてみた。もちろん、このような、2通りにしかならないような判断の場合は、「2で割ったあまりが1でないなら」など何通りも条件判断の式は作成できることになる。基本的にはどれも正解である。

{
    System.out.println("********* Ex 4-1");

    int number = 11;

    if(number % 2 == 0)
        System.out.println(number + "は偶数です");
    else
        System.out.println(number + "は奇数です");
}

練習問題4-2

ちょっと回りくどい解説になってしまっているが、とにかく指定通りにプログラムを組んでみること。このとき、ある場所での判断結果を、それより後の別の場面で使いたいような場合、そのつど判断をするのでもかまわないが、問題が発生する恐れがある。1つにはプログラムの修正を行ったとき、同じ判断のある場所すべてに修正が必要になるかもしれない。また、判断処理が非常に時間がかかるような場合には、効率が悪くなる。そこで、ある段階での判断結果を、変数に記憶させておき、その後はいちいち条件判断するのではなく、変数の値を参照して判断結果を知るという手法がある。こうしたテクニックを一般的にフラグと言うが、少し複雑な処理を組む場合には知っておく必要があるものである。

{
    System.out.println("********* Ex 4-2");

    int number = 25;

    boolean flag = false;

    if(number % 2 != 0) {
        if(number % 5 != 0) {
            flag = true;
        }
    }
    if(flag)
        System.out.println("びんごー!");
    else
        System.out.println("はずれー");
}

練習問題4-3

前の設問は、フラグ変数を説明するための強引なサンプルでした。本当は、この程度の条件判断ならば、2つまとめて行ってもかまわない。こうした2つの条件が両方満たされた場合・・・といったような判断をするときに使うのが&&演算子である。

{
    System.out.println("********* Ex 4-3");

    int number = 25;
    if((number % 2 != 0) && (number % 5 != 0))
        System.out.println("びんごー!");
    else
        System.out.println("はずれー");
}

練習問題4-4

素数かどうかの判断方法は、いろいろ考えるところが多い。もちろん、人間が判断する方法をそのまま利用してもいいが、場合によっては、プログラムがやたら複雑になる。コンピュータは、単純な処理を高速にするという特徴があり、多くのプログラムではそうした力技を使うことはよくある。

素数かどうかの判断でも、常識としては「その数の半分よりも小さな素数で割り切れるものがあれば、その数は素数ではない」というのが基本になる。だけど、これをプログラミングするのは難しい(挑戦してもいいですよ)。むしろ、2〜その数の半分までの整数について、割り切れるかどうかを判断するということの 方がプログラムは作りやすくなる。もちろん、2で割り切れないのに、4で割り切れるはずはないなどの無駄もあるが、状況によっては容認してもいいだろう。

こうした、繰り返しを行うときには、forを使う。forの使い方のポイントを知って欲しいので、ちょっと難しいプログラムではあるのだが、じっくり吟味してほしい。forの繰り返しの中で、変数がどう変化するのかを追うために、以下のプログラムでは、途中の変数の値を標準出力に随時出力してみた。

{
    System.out.println("********* Ex 4-4");

    int number = 23;
    boolean flag = true;
    for(int j=2; j < number/2 ; j++) {
        System.out.println("Number="+number+", j="+j+", number % j="+(number%j));
        if(number % j == 0)    {
            flag = false;
            break;        //テキストでは詳しく書いていないが、これにより、
                            //forの繰り返しを強制的に終わらせることができる
        }
    }
    if(flag == true)
        System.out.println(number + "は素数です");
    else
        System.out.println(number + "は素数ではありません");
}

breakについては、説明はありませんが、繰り返しを途中で終わらせるものです。これがある場合、ない場合でどんな結果の違いになるかを実際に確かめてみましょう。

それから、{ }の使い方はなれないとわかりにくいかもしれませんが、たとえば、ifの中の命令が1つだけなら{ }はあってもなくてもかまいません。2つ以上だと、{ }は必ず必要です。後者のように必ず必要な場合が出てくることもあるので、1つだけの命令の場合でも、{ }をつけておくことはよくあります。後から命令を加えたのに、{ }を忘れることってよくあるので、そうした予防線でもあります。