next()またはnextFoo()を使用した後、スキャナーがnextLine()をスキップしていますか?

Oct 27 2012

私はScannerメソッドnextInt()nextLine()入力の読み取りに使用しています。

次のようになります。

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string"); 
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)

問題は、数値を入力した後、最初の値input.nextLine()がスキップinput.nextLine()され、2番目の値が実行されるため、出力が次のようになることです。

Enter numerical value
3   // This is my input
Enter 1st string    // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string    // ...and this line is executed and waits for my input

アプリケーションをテストしましたが、問題はの使用にあるようinput.nextInt()です。私はそれを削除する場合は、両方のstring1 = input.nextLine()string2 = input.nextLine()、私は彼らがなりたいように実行されています。

回答

898 RohitJain Oct 27 2012 at 23:39

それのためScanner.nextIntの方法は読まない改行押すことで、作成した入力中の文字「を入力し、」との呼び出しので、Scanner.nextLineそれを読んだ後リターン改行を

Scanner.nextLineafterScanner.next()または任意のScanner.nextFooメソッド(nextLineそれ自体を除く)を使用すると、同様の動作が発生します。

回避策:

  • 置くどちらのScanner.nextLineそれぞれの後に電話をScanner.nextIntScanner.nextFooなど、その行の残りの部分を消費するために改行を

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • または、さらに良いことに、入力をScanner.nextLine読み通して、入力を必要な適切な形式に変換します。たとえば、Integer.parseInt(String)メソッドを使用して整数に変換できます。

    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();
    
222 Prine Aug 14 2011 at 19:24

問題はinput.nextInt()メソッドにあります-それはint値を読み取るだけです。したがって、input.nextLine()で読み続けると、「\ n」Enterキーが表示されます。したがって、これをスキップするには、input.nextLine()を追加する必要があります。これが今明らかになることを願っています。

そのようにしてみてください:

System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();
85 Bohemian Aug 14 2011 at 19:25

これは、数字を入力してからを押すEnterinput.nextInt()、「行末」ではなく、数字のみが消費されるためです。ときにinput.nextLine()実行する、それが最初の入力からバッファ内に依然として「行の末尾」を消費します。

代わりに、input.nextLine()直後に使用してくださいinput.nextInt()

51 DenisTulskiy Mar 23 2014 at 23:35

でこの問題について多くの質問があるようですjava.util.Scanner。より読みやすく慣用的な解決策は、を呼び出しscanner.skip("[\r\n]+")た後に改行文字を削除するために呼び出すことだと思いますnextInt()

編集:以下で説明する@PatrickParkerのように、ユーザーが数字の後に空白を入力すると、無限ループが発生します。スキップで使用するより良いパターンについては、彼らの回答を参照してくださいhttps//stackoverflow.com/a/42471816/143585

37 ElectricCoffee Feb 24 2013 at 05:01

input.nextInt();改行をキャプチャしないため、これを行います。input.nextLine();下に追加することで、他の提案と同じように行うことができます。
または、C#スタイルで実行し、nextLineを次のように整数に解析することもできます。

int number = Integer.parseInt(input.nextLine()); 

これを行うことも同様に機能し、コード行を節約できます。

28 Pshemo Oct 10 2016 at 05:51

TL; DRscanner.skip("\\R")scanner.newLine()呼び出しの前に使用します。これは次の後に実行されます。

  • scanner.next()
  • scanner.next*TYPE*()のようなメソッドscanner.nextInt()

あなたが知る必要があること:

  • 数行を表すテキストには、次のように行間に印刷できない文字(行区切り文字と呼びます)も含まれます。

  • キャリッジリターン(CR-として表される文字列リテラル内"\r"

  • 改行(LF-として表される文字列リテラル内"\n"

  • コンソールからデータを読み取るとき、ユーザーは応答を入力できます。完了したら、何らかの方法でその事実を確認する必要があります。これを行うには、ユーザーはキーボードの「Enter」/「Return」キーを押す必要があります。

重要なのは、ユーザーデータを標準入力(によってSystem.in読み取られるScanner)に配置することを保証することに加えて、このキーは、\r\nその後にOSに依存する行区切り記号(Windowsの場合など)も送信することです。

したがって、のような値をユーザーに要求し、ユーザーがage42と入力してEnterキーを押すと、標準入力にはが含まれます"42\r\n"

問題

Scanner#nextInt(および他の方法)スキャナがすることはできません消費これらの行区切りを。それはからそれらを読み込みます(表現し、ユーザからのこれ以上の数字があることを知っているだろうか他のスキャナ標準入力から削除されますどの空白が直面しているよりも値が?)、しかし、それはまたしますキャッシュし、内部でこれらの行区切りを。覚えておく必要があるのは、すべてのScannerメソッドは常にキャッシュされたテキストからスキャンしているということです。Scanner#nextTypeSystem.inage

これでScanner#nextLine()行区切り文字(またはストリームの終わり)が見つかるまで、すべての文字を収集して返すだけです。ただし、コンソールから数値を読み取った後の行区切り文字はScannerのキャッシュですぐに見つかるため、空の文字列が返されます。つまり、Scannerはこれらの行区切り記号(またはストリームの終わり)の前の文字を見つけることができませんでした。
ところでこれらの行区切り文字nextLine使用します。

解決

したがって、の結果としてその空の文字列を避けながら、番号を要求してから行全体を要求する場合はnextLine

  • nextIntスキャナーキャッシュから残された行区切り文字を消費する
  • 呼び出しnextLine
  • またはIMOのより読みやすい方法は、を呼び出すskip("\\R")skip("\r\n|\r|\n")、スキャナーに行区切り文字と一致する部分をスキップさせることです(詳細\Rhttps//stackoverflow.com/a/31060125
  • nextInt(またはnext、または任意のnextTYPEメソッド)をまったく使用しないでください。代わりに、を使用してデータ全体nextLineを1行ずつ読み取り、各行の数値を解析して(1行に1つの数値しか含まれていないと想定)、intviaのように適切なタイプにしInteger.parseIntます。

ところで:メソッドは、次の非区切り値(トークン)が見つかるまで、スキャナーによってキャッシュされたものを含む区切り文字(デフォルトではタブや行区切り文字などのすべての空白)をスキップできます。コードのような入力をしてくれてありがとうScanner#nextType"42\r\n\r\n321\r\n\r\n\r\nfoobar"

int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

を適切に割り当てることができますnum1=42 num2=321 name=foobar

17 Castaldi Jul 23 2014 at 17:20

input.nextLine()使用する代わりにinput.next()、それは問題を解決するはずです。

変更されたコード:

public static Scanner input = new Scanner(System.in);

public static void main(String[] args)
{
    System.out.print("Insert a number: ");
    int number = input.nextInt();
    System.out.print("Text1: ");
    String text1 = input.next();
    System.out.print("Text2: ");
    String text2 = input.next();
}
16 AndréWillikValenti Jun 21 2017 at 01:52

文字列とintの両方を読み取りたい場合、解決策は2つのスキャナーを使用することです。

Scanner stringScanner = new Scanner(System.in);
Scanner intScanner = new Scanner(System.in);

intScanner.nextInt();
String s = stringScanner.nextLine(); // unaffected by previous nextInt()
System.out.println(s);

intScanner.close();
stringScanner.close();
13 NIKUNJKHOKHAR Jun 16 2017 at 15:12

ScannerクラスのnextLine()メソッドに混乱することなく入力を高速にスキャンしたい場合は、カスタム入力スキャナーを使用してください。

コード:

class ScanReader {
/**
* @author Nikunj Khokhar
*/
    private byte[] buf = new byte[4 * 1024];
    private int index;
    private BufferedInputStream in;
    private int total;

    public ScanReader(InputStream inputStream) {
        in = new BufferedInputStream(inputStream);
    }

    private int scan() throws IOException {
        if (index >= total) {
            index = 0;
            total = in.read(buf);
            if (total <= 0) return -1;
        }
        return buf[index++];
    }
    public char scanChar(){
        int c=scan();
        while (isWhiteSpace(c))c=scan();
        return (char)c;
    }


    public int scanInt() throws IOException {
        int integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public String scanString() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = scan();
        } while (!isWhiteSpace(c));
        return res.toString();
    }

    private boolean isWhiteSpace(int n) {
        if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
        else return false;
    }

    public long scanLong() throws IOException {
        long integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public void scanLong(long[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanLong();
    }

    public void scanInt(int[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanInt();
    }

    public double scanDouble() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = scan();
        }
        double res = 0;
        while (!isWhiteSpace(c) && c != '.') {
            if (c == 'e' || c == 'E') {
                return res * Math.pow(10, scanInt());
            }
            res *= 10;
            res += c - '0';
            c = scan();
        }
        if (c == '.') {
            c = scan();
            double m = 1;
            while (!isWhiteSpace(c)) {
                if (c == 'e' || c == 'E') {
                    return res * Math.pow(10, scanInt());
                }
                m /= 10;
                res += (c - '0') * m;
                c = scan();
            }
        }
        return res * sgn;
    }

}

利点:

  • BufferReaderよりも高速に入力をスキャンします
  • 時間の複雑さを軽減
  • 次の入力ごとにバッファをフラッシュします

方法:

  • scanChar()-1文字をスキャンします
  • scanInt()-整数値をスキャンします
  • scanLong()-Long値をスキャンします
  • scanString()-文字列値をスキャンします
  • scanDouble()-Double値をスキャンします
  • scanInt(int [] array)-完全なArray(Integer)をスキャンします
  • scanLong(long [] array)-完全なArray(Long)をスキャンします

使用法 :

  1. 指定されたコードをJavaコードの下にコピーします。
  2. 指定されたクラスのオブジェクトを初期化します

ScanReader sc = new ScanReader(System.in); 3.必要なクラスをインポートします。

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4.メインメソッドからIOExceptionをスローして、例外5を処理します。提供されたメソッドを使用します。6.お楽しみください

例:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Main{
    public static void main(String... as) throws IOException{
        ScanReader sc = new ScanReader(System.in);
        int a=sc.scanInt();
        System.out.println(a);
    }
}
class ScanReader....
12 UrvashiGupta Nov 17 2016 at 07:51

この問題を回避するには、バッファをクリアするのに役立つため、nextLine();直後に使用してくださいnextInt();。を押すとENTERnextInt();改行がキャプチャされないため、Scanner後でコードをスキップします。

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
10 shankarupadhyay Sep 14 2017 at 17:16

sc.nextLine()入力を解析するよりも優れています。パフォーマンス的には良いでしょうから。

6 TaslimOseni Jan 07 2018 at 17:33

私はパーティーにかなり遅れていると思います。

前に述べinput.nextLine()たように、int値を取得した後に呼び出すと、問題が解決します。コードが機能しなかった理由は、入力(intを入力した場所)からに格納するものが他になかったためですstring1。トピック全体にもう少し光を当てます。

nextLine()は、ScannerクラスのnextFoo()メソッドの中で奇妙なものと考えてください。簡単な例を見てみましょう。次のような2行のコードがあるとします。

int firstNumber = input.nextInt();
int secondNumber = input.nextInt();

以下の値を(1行の入力として)入力した場合

54 234

ourfirstNumbersecondNumbervariableの値はそれぞれ54と234になります。新しいラインフィード(ので、これはこのように動作理由は、すなわち\ nはれていませんnextInt()メソッドは値をとるときに自動的に生成します。それは単に「次のint」を取り、次に進みます。これは、nextLine()を除く残りのnextFoo()メソッドでも同じです。

nextLine()は、値を取得した直後に新しい改行を生成します。これは、@ RohitJainが、改行が「消費された」と言うことを意味します。

最後に、next()メソッドは、改行生成せずに最も近い文字列取得します。これにより、これは同じ1行内で別々の文字列を取得するための優先的な方法になります。

これがお役に立てば幸いです。メリーコーディング!

5 NeerajGahlawat Jul 30 2017 at 10:48
public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int i = scan.nextInt();
        scan.nextLine();
        double d = scan.nextDouble();
        scan.nextLine();
        String s = scan.nextLine();

        System.out.println("String: " + s);
        System.out.println("Double: " + d);
        System.out.println("Int: " + i);
    }
5 HarshShah Jan 17 2019 at 02:24

1つではなく2つのスキャナーオブジェクトを使用する

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
4 Kaplan Oct 02 2019 at 00:20

空でない入力を期待する場合

public static Function<Scanner,String> scanLine = (scan -> {
    String s = scan.nextLine();
    return( s.length() == 0 ? scan.nextLine() : s );
  });


上記の例で使用:

System.out.println("Enter numerical value");    
int option = input.nextInt(); // read numerical value from input

System.out.println("Enter 1st string"); 
String string1 = scanLine.apply( input ); // read 1st string
System.out.println("Enter 2nd string");
String string2 = scanLine.apply( input ); // read 2nd string
4 Giri Jan 24 2020 at 18:32

私のユースケースの1つでは、2つの整数値が前に付い文字列値を読み取るシナリオがありました。値を読み取るには、「for / whileループ」を使用する必要がありました。そして、上記の提案はどれもこの場合はうまくいきませんでした。

問題input.next()input.nextLine()修正する代わりに使用する。これが同様のシナリオを扱っている人たちに役立つことを願っています。

4 SandeepKumar Dec 18 2019 at 16:08

以下のようnextXXX()な方法読んでいないnewline除きますnextLine()。以下のように使用することで、newline任意のnon-string値(intこの場合)を読み取った後をスキップできscanner.skip()ます。

Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(x);
double y = sc.nextDouble();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(y);
char z = sc.next().charAt(0);
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(z);
String hello = sc.nextLine();
System.out.println(hello);
float tt = sc.nextFloat();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(tt);
2 JeewanthaLahiru Mar 08 2020 at 22:19

このコードを使用すると、問題が修正されます。

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
input.nextLine();
System.out.println("Enter 1st string"); 
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)
TobiasJohansson Mar 13 2015 at 18:06

すべての読み取りに新しいスキャナーを使用してみませんか?以下のように。このアプローチでは、問題に直面することはありません。

int i = new Scanner(System.in).nextInt();
PallavKhare Nov 22 2020 at 13:59

問題はinput.nextInt()メソッドにあります-それはint値を読み取るだけです。したがって、input.nextLine()で読み続けると、「\ n」Enterキーが表示されます。したがって、これをスキップするには、input.nextLine()を追加する必要があります。これが今明らかになることを願っています。

そのようにしてみてください:

System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();