Java | while文の練習問題

Java Java
スポンサーリンク

では while 文の練習問題を 6 問 用意して、それぞれに「解答(実行可能な Java コード)」「ステップごとの解説」「よくあるミス」「発展課題」を付けます。手を動かして確かめやすいように、入出力例も載せます。コピーしてそのまま実行できるコードです。

練習問題 1(やさしい) — 1 から n までの偶数の合計

問題
ユーザーが入力した正の整数 n に対して、1 から n までの 偶数 の合計を while を使って求めて表示せよ。

入力例
n = 10

期待出力
2 + 4 + 6 + 8 + 10 = 30

解答(サンプル)

import java.util.Scanner;
public class SumEven {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("n を入力: ");
        int n = sc.nextInt();
        int i = 1;
        int sum = 0;
        while (i <= n) {
            if (i % 2 == 0) {
                sum += i;
            }
            i++;
        }
        System.out.println("偶数の合計 = " + sum);
        sc.close();
    }
}
Java

ステップ解説

  1. i1 で初期化(ループの開始値)。
  2. 条件 i <= n を満たす間ループ。
  3. if (i % 2 == 0) で偶数か判定し、偶数なら sum に加算。
  4. i++ で必ず i を進める(更新忘れ防止)。
  5. ループ終了後に sum を表示。

よくあるミス

  • i++ を忘れる → 無限ループ。
  • i = 2 から i += 2 にして最初から偶数だけ回す(効率的だが初心者は忘れがち)。

発展
i = 2; while (i <= n) { sum += i; i += 2; } に書き換えて効率化してみよう。


練習問題 2(基本アルゴリズム) — n の階乗(factorial)

問題
正の整数 n を入力し、n!(階乗)を while で計算して表示せよ。n0 以上とする(0! = 1)。

入力例
n = 5

期待出力
5! = 120

解答(サンプル)

import java.util.Scanner;
public class Factorial {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("n を入力 (0以上): ");
        int n = sc.nextInt();
        long result = 1;
        int i = 1;
        while (i <= n) {
            result *= i;
            i++;
        }
        System.out.println(n + "! = " + result);
        sc.close();
    }
}
Java

ステップ解説

  1. result1 で初期化(掛け算の単位元)。
  2. ループ変数 i1 から n まで増やす。
  3. 各ループで result *= i(累積的に掛ける)。
  4. i++ を忘れずに。
  5. n = 0 の場合、ループは実行されず result1 のまま(正しく 0! = 1)。

よくあるミス

  • 結果を int にしてオーバーフロー(20! あたりで int は不適)。long を使うか大きな数は BigInteger を検討。

発展
BigInteger を使ってさらに大きな階乗を計算してみよう。


練習問題 3(文字列操作) — 整数の桁を逆順にする

問題
正の整数 n を入力し、数の桁を逆順にして表示せよ(数学的操作で行う — 文字列操作は使わない)。

入力例
n = 12340

期待出力
04321(数値として出すなら 4321 になるが、0 を保持したい場合は文字列に変換して扱う)

解答(サンプル)(数値として逆にして表示するパターン)

import java.util.Scanner;
public class ReverseDigits {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("正の整数を入力: ");
        int n = sc.nextInt();
        int rev = 0;
        while (n > 0) {
            int digit = n % 10;   // 末尾の桁を取り出す
            rev = rev * 10 + digit; // 逆順に追加
            n /= 10;              // 末尾の桁を削る
        }
        System.out.println("逆順 = " + rev);
        sc.close();
    }
}
Java

ステップ解説

  1. n % 10 で末尾の桁を取得。
  2. rev = rev * 10 + digit で桁を左に詰めつつ追加。
  3. n /= 10 で元の数の末尾を切り落とす。
  4. n0 になるまで続ける。

注意点

  • 先頭に 0 があるような表示(例: 1234004321)を厳密に再現したい場合は、文字列操作で桁数を保存しておく必要がある(このサンプルは数値型で扱うため 043214321 と表示される)。

発展
負の数の処理を追加したり、文字列で 0 を保持して出力するバージョンを作ってみよう。


練習問題 4(入力バリデーション) — 正の数が来るまで読み直す

問題
ユーザーに正の整数を入力してもらう。もし負の数や 0 が入力されたらエラーメッセージを出して再入力を促す(正しい入力が来るまで while で繰り返す)。

入出力の流れ(例)
入力: -305 → 終了(5 を受け付ける)

解答(サンプル)

import java.util.Scanner;
public class ReadPositive {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x;
        System.out.print("正の整数を入力してください: ");
        x = sc.nextInt();
        while (x <= 0) {
            System.out.println("入力エラー: 正の整数を入力してください。");
            System.out.print("再入力: ");
            x = sc.nextInt(); // 再読み込み(必須)
        }
        System.out.println("入力された正の数 = " + x);
        sc.close();
    }
}
Java

ステップ解説

  1. 最初に値を読み込む(ループ前読み込みパターン)。
  2. x <= 0 の間は「エラー」→再入力を要求し続ける。
  3. 正の数が来たらループ終了。

よくあるミス

  • ループの中だけで読み込みをして 初回読み込み を忘れると変な挙動に。
  • nextInt() が例外を投げる(数以外の入力)ケースは未対処 → try-catch で扱うとより堅牢。

発展
try-catch を使って “数以外” 入力時に sc.next() で不正なトークンを捨て、再入力を促すようにする。


練習問題 5(ループ制御) — パスワード試行(失敗回数制限)

問題
正しいパスワード(文字列)を secret として用意し、ユーザーに最大 3 回まで入力させる。正解したら「ログイン成功」、3 回失敗したら「ロック」して終了する。ループは while を使う。

解答(サンプル)

import java.util.Scanner;
public class PasswordTry {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        final String SECRET = "openSesame";
        int attempts = 0;
        boolean loggedIn = false;

        while (attempts < 3) {
            System.out.print("パスワード: ");
            String input = sc.nextLine();
            attempts++;
            if (input.equals(SECRET)) {
                System.out.println("ログイン成功");
                loggedIn = true;
                break; // 成功したら抜ける
            } else {
                System.out.println("パスワードが違います。残り " + (3 - attempts) + " 回");
            }
        }

        if (!loggedIn) {
            System.out.println("アカウントはロックされました。");
        }
        sc.close();
    }
}
Java

ステップ解説

  1. attempts(試行回数)を 0 で初期化。
  2. 条件 attempts < 3 で最大回数を保証。
  3. 各回 attempts++ を行い、equals で文字列比較(== はダメ)。
  4. 正解なら break でループを抜ける。
  5. ループ後に loggedIn フラグで成功/失敗を判定。

よくあるミス

  • 文字列比較で == を使ってしまう(オブジェクト参照の比較になり失敗する)。
  • attempts++ の位置を間違えると残り回数表示がズレる。

発展
while(true) にして、成功か失敗(回数超過)で break する別スタイルに書き換えてみよう。


練習問題 6(応用) — セントネル値 -1 で最大最小を求める(先頭が -1 の場合の扱い)

問題
ユーザーが整数を何個でも入力する。-1 が入力されたら入力終了(-1 は集計に含めない)。入力された値の最大値と最小値を表示せよ。もし最初の入力が -1(すなわちデータがない)なら、その旨を表示する。

解答(サンプル)

import java.util.Scanner;
public class MinMaxUntilMinusOne {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("整数を入力(-1で終了):");
        int num = sc.nextInt();

        if (num == -1) {
            System.out.println("データがありません。");
            sc.close();
            return;
        }

        int min = num;
        int max = num;

        while (true) {
            num = sc.nextInt();
            if (num == -1) break;
            if (num < min) min = num;
            if (num > max) max = num;
        }

        System.out.println("最小 = " + min + ", 最大 = " + max);
        sc.close();
    }
}
Java

ステップ解説

  1. 最初の入力をループの外で取り、-1 なら「データなし」で終了(特別処理)。
  2. 最小・最大 min max を最初の値で初期化。
  3. while(true) で次々読み込み、-1 が来たら break
  4. 各値で minmax を更新。
  5. 最後に結果を表示。

よくあるミス

  • 最初の -1 をそのまま min/max に入れてしまう(すると集計に含まれてしまう)。
  • while (num != -1) という書き方でもできるが、初回とその後の読み方に注意(読み込み位置の取り扱いを間違いやすい)。

発展
平均や個数も同時に保持して表示する(0 除算やデータなしのケースに注意)。


最後に(学習のコツ)

  • まずは 紙に処理の流れを図示(初期値→条件→本体→更新→終了)すると書きやすくなります。
  • 自分で「想定入力」を決めて、手で変数を書きながらループを追い、各変数がどう変わるか確認すると理解が深まります。
  • エラーや無限ループに出会ったら、ループの最初に System.out.println で変数を出力して値の変遷を追跡しましょう。

タイトルとURLをコピーしました