未来エンジニア養成所Blog

月単価180万以上のプログラミング講師がプログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】基本構文に関する問題1-23

title


問題1-23

あるアパートに住む住人を表すapartmentというString型の変数があります。

配列の1次元目はアパートの階数、2次元目は号室を表現しています。

(つまりapartment[0][1]は1階2号室の住人の名前になります)

キーボードから検索したい人の名前を入力し、アパートにその人が住んでいるかを調査してください。

System.console().readLine() の記述は、キーボードから文字列の入力を受け付けるもので、その値でString型変数nameを初期化しています。

見つかった場合は、「○人目の○○さんは、○階の○号室に住んでいます」と表示してください。

ポイントは同名の方が住んでいる場合を考慮することです。

また、見つからなかった場合は「○○さんはこのアパートには住んでいません」と表示してください。


【実行結果】

検索する名前を入力してください
後藤
1人目の後藤さんは、1階の1号室に住んでいます
2人目の後藤さんは、3階の4号室に住んでいます
3人目の後藤さんは、4階の3号室に住んでいます
検索する名前を入力してください
上戸
上戸さんはこのアパートには住んでいません


【StringArrayPractice.java】

public class StringArrayPractice {
    public static void main(String[] args) {

        // アパートに住む住人2次元配列変数
        String[][] apartment = {
                    {"後藤", "矢口", "石川", "吉澤", "藤本"},
                    {"亀井", "小川", "紺野"},
                    {"石川", "安部", "安田", "後藤"},
                    {"石黒", "福田", "後藤"}
                };

        System.out.println("検索する名前を入力してください");

        // 検索するname変数の宣言とキーボード入力値による初期化
        String name = System.console().readLine();

        // ここからコーディングしてください


    }
}


解答例

【StringArrayPractice.java】

public class StringArrayPractice {
    public static void main(String[] args) {

        // アパートに住む住人2次元配列変数
        String[][] apartment = {
                    {"後藤", "矢口", "石川", "吉澤", "藤本"},
                    {"亀井", "小川", "紺野"},
                    {"石川", "安部", "安田", "後藤"},
                    {"石黒", "福田", "後藤"}
                };

        System.out.println("検索する名前を入力してください");

        // 検索するname変数の宣言とキーボード入力値による初期化
        String name = System.console().readLine();

        // 見つけた人数変数の宣言と初期化
        int count = 0;

        // 階のループ
        for(int i = 0; i < apartment.length; i++) {

            // 号室のループ
            for(int j = 0; j < apartment[i].length; j++) {

                // 見つかった場合
                if(apartment[i][j].equals(name)) {

                    // 情報の出力
                    System.out.println(++count + "人目の" + name + "さんは、" +
                        (i + 1) + "階の" +
                        (j + 1) + "号室に住んでいます");
                }
            }
        }

        // 最後まで見つからなかった場合
        if(count == 0) {
            System.out.println(name + "さんはこのアパートには住んでいません");
        }
    }
}


Eclipseで動作させた場合、System.console()の返却値がnullになり動作せず、Null Pointer Exceptionが発生してしまうので、下記のようにする必要があります。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class StringArrayPractice {
    public static void main(String[] args) throws IOException {

        // アパートに住む住人2次元配列変数
        String[][] apartment = {
                    {"後藤", "矢口", "石川", "吉澤", "藤本"},
                    {"亀井", "小川", "紺野"},
                    {"石川", "安部", "安田", "後藤"},
                    {"石黒", "福田", "後藤"}
                };

        System.out.println("検索する名前を入力してください");

        // 検索するname変数の宣言とキーボード入力値による初期化
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String name = br.readLine();

        // 見つけた人数変数の宣言と初期化
        int count = 0;

        // 階のループ
        for(int i = 0; i < apartment.length; i++) {

            // 号室のループ
            for(int j = 0; j < apartment[i].length; j++) {

                // 見つかった場合
                if(apartment[i][j].equals(name)) {

                    // 情報の出力
                    System.out.println(++count + "人目の" + name + "さんは、" +
                        (i + 1) + "階の" +
                        (j + 1) + "号室に住んでいます");
                }
            }
        }

        // 最後まで見つからなかった場合
        if(count == 0) {
            System.out.println(name + "さんはこのアパートには住んでいません");
        }
    }
}


解説

今回の問題は、Stringと配列を組み合わせた重要度の高い内容になっています。



String二次元配列をアパートに見立てているわけですが、同姓の方が住んでいるケースがあります。

よって、見つけた人数を保持するための変数の宣言が必須になります。

ここでは変数countを宣言し、初期値0を代入しておきましょう。



次にループによる走査ですが、for文をネストさせます。

今回は「○階○号室」と表示するためにループ変数を使うことになりますので、拡張for文より通常のfor文の方が向いています。



外側のfor文が階のループ、内側のfor文が号室のループになるわけですが、くれぐれも次のように記述しないようにしましょう。

// 階のループ
for(int i = 1; i <= apartment.length; i++) {

    // 号室のループ
    for(int j = 1; j <= apartment[i - 1].length; j++) {


確かにループ変数iは階の表現に、ループ変数jは号室の表現に使用しますが、この2つの変数の初期値を1にすると、結局名前を取得するときにインデックス番号を1減算する必要が出てきます。

配列を走査するときのfor文のループ変数は、あくまで基本として初期値0を使用してください。



キーボードから入力した名前と、String型の変数apartmentの各要素との等値チェックは間違えないようにしましょう。

String型の等値チェックはequalsメソッド

これが鉄則です。

くれぐれも==を使わないようにしてください。



最後に、入力した名前の人がいない場合の処理ですが、「○○さんはこのアパートには住んでいません」の出力処理を、次のようにforループの中に書こうと四苦八苦する人がいます。

// 見つかった場合
if(apartment[i][j].equals(name)) {

    // 情報の出力
    System.out.println(++count + "人目の" + name + "さんは、" +
        (i + 1) + "階の" +
        (j + 1) + "号室に住んでいます");

}
// 見つからなかった場合
else {
    System.out.println(name + "さんはこのアパートには住んでいません");
}


確かに、気持ちはわかります。

if文の条件式は「見つかった場合」を表現しているので、else文に「見つからなかった場合」の処理を記述してしまうわけです。

しかし、「見つからなかった」というのは、アパートのすべての住人をチェックし終わって初めてわかることですから、for文の中、つまり検索途中に書くのはおかしいことがわかります。

for文を抜けてから「見つからなかった」かどうかをチェックするわけです。


解答例にもあるように、見つけた人数を保持する変数countが0のままという条件文をforループが終わった後に書くだけです。



ちなみに、見つかった場合の情報出力のprintlnメソッドで、count変数を前置インクリメントを用いてインクリメントしています。

変数の左側に++をつけると、先に値がインクリメントされてからその値を使用する事ができます。

後置インクリメントの方がよく見かけますが、前置インクリメントも知っておきましょう。


参考図書



LINE公式アカウント

仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】


LineOfficial

友だち追加