Code Fix

中級

nextInt の後の nextLine が読み飛ばされる理由

改行文字の読み残しが原因です。判定と読み取りの単位を揃える設計を扱います。

なぜエラーが出ないのか

出力: 5:
(エラーなし)
javacは何も報告しません。文法として正しいためです
出力: 5:
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  import java.util.Scanner;
 2  
 3  public class Main {
 4      public static void main(String[] args) {
 5          Scanner sc = new Scanner(System.in);
 6          int n = sc.nextInt();
 7                        
                   ^
 8          String name = sc.nextLine();
 9          System.out.println(n + ":" + name);
10      }
11  }
出力: 5:期待: 5:Taiyo (コンパイルは通っています)

nextInt()は改行を読み残します。次のnextLine()がその改行を拾って空文字になる有名な罠です。

直し方: (空)sc.nextLine(); にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  import java.util.Scanner;
 2  
 3  public class Main {
 4      public static void main(String[] args) {
 5          Scanner sc = new Scanner(System.in);
 6          String s = sc.next      ();
                               ^
 7          System.out.println("[" + s + "]");
 8      }
 9  }
入力: Taiyo Sato / 出力: [Taiyo]期待: [Taiyo Sato] (コンパイルは通っています)

next()は空白までの1単語だけを読みます。行全体を読むのはnextLine()です。

直し方: nextnextLine にします。

この問題を解いてみる →

パターン3

 1  import java.util.Scanner;
 2  
 3  public class Main {
 4      public static void main(String[] args) {
 5          Scanner sc = new Scanner(System.in);
 6          while (sc.hasNext    ()) {
                           ^
 7              System.out.println(sc.nextLine());
 8          }
 9      }
10  }
最終行が読み飛ばされることがある(コンパイルは通っています)

nextLineで読むならhasNextLineで判定します。判定と読み取りの単位を揃えるのが原則です。

直し方: hasNexthasNextLine にします。

この問題を解いてみる →

よくある誤解

Scannerを2つ作れば直ると思いがちですが、悪化します。読み取り位置は入力ストリーム側にあり、共有されています。

まとめ

nextInt の後の nextLine が読み飛ばされる理由は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)