问题:扫描仪在使用next()或nextFoo()之后跳过nextLine()吗?

我正在使用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()被执行,因此我的输出看起来像这样:

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()都会按照我的意愿执行。

标签:java,io,java.util.scanner

回答1:

这是因为 code> Scanner.nextInt 方法不会在您按" Enter"键创建的输入中读取 newline 字符,因此对 Scanner.nextLine 返回读完 newline 之后。

Scanner.next() 或任何Scanner.nextFoo方法(除外)nextLine 本身。

解决方法:

  • 在每个Scanner.nextIntScanner.nextFoo之后都放置一个Scanner.nextLine调用,以消耗该行的其余部分,包括换行符

    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();
    

回答2:

问题出在 input.nextInt()方法上-它只读取int值。因此,当您继续阅读input.nextLine()时,会收到" \ n"回车键。因此,要跳过此步骤,您必须添加 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();

回答3:

这是因为当您输入数字然后按 Enter 时,input.nextInt()仅使用数字,而不使用"行尾"。当input.nextLine()执行时,它会消耗掉第一个输入中缓冲区中的"行尾"。

相反,请在input.nextInt()

之后立即使用input.nextLine()

回答4:

java.util.Scanner似乎对此问题有很多疑问。我认为更易读/惯用的解决方案是调用nextInt()后,调用scanner.skip("[\r\n]+")删除所有换行符

编辑:如下@PatrickParker所述,如果用户在数字后面输入任何空格,则将导致无限循环。请参阅他们的答案以获取与跳过一起使用的更好模式: https://stackoverflow.com/a/42471816/143585 < / p>

回答5:

之所以这样做是因为input.nextInt();不会捕获换行符。您可以像在下面添加一个input.nextLine();一样提出其他建议。
或者,您也可以执行C#样式并将nextLine解析为一个整数,如下所示:

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

这样做同样有效,并且可以节省一行代码。

回答6:

TL; DR在每个scanner.newLine()调用之前使用scanner.skip("\\R"),该调用将在之后执行:

  • scanner.next()
  • scanner.next*TYPE*()方法。

您需要了解的事情:

    表示几行的
  • 文本在行之间也包含不可打印的字符(我们称为行分隔符),例如

    • 回车(CR-以"\r"表示的字符串文字)
    • 换行符(LF-以"\n"表示的String文字)
  • 当您从控制台读取数据时,它允许用户键入其响应,完成后,他需要以某种方式确认该事实。为此,要求用户按下键盘上的"输入" /"返回"键。

    重要的是,此键除了确保将用户数据放入标准输入(由Scanner读取的System.in表示)外, )之后还会发送与操作系统相关的行分隔符(例如Windows \r\n)。

    因此,当您要求用户提供age之类的值,并且用户键入42并按Enter键时,标准输入将包含"42\r\n"。

问题

Scanner#nextInt(和其他Scanner#nextType方法)不允许Scanner < em>消耗这些行分隔符。它将从System.in中读取它们(否则Scanner怎么会知道从用户那里得到的代表age值的数字没有面对空白?),这将删除它们。从标准输入中输入,但还将在内部缓存这些行分隔符。我们需要记住的是,所有Scanner方法始终从缓存的文本开始进行扫描。

现在Scanner#nextLine()仅收集并返回所有字符,直到找到行分隔符(或流的末尾)为止。但是,由于从控制台读取数字后的行分隔符会立即在Scanner的缓存中找到,因此它返回空字符串,这意味着Scanner在这些行分隔符(或流的末尾)之前找不到任何字符。
BTW nextLine 还会使用这些行分隔符。

解决方案

因此,当您要先输入数字然后再查询整行,同时又要避免由于nextLine的结果而产生空字符串时,

  • 使用nextInt从扫描仪缓存中保留的行分隔符
    • 调用nextLine
    • 或IMO 更具可读性 的方式是调用skip("\\R")skip("\r\ n | \ r | \ n")允许扫描程序跳过由行分隔符匹配的部分(有关\R的更多信息: https://stackoverflow.com/a/31060125 )
  • 完全不使用nextInt(也不使用next或任何nextTYPE方法)。而是使用nextLine逐行读取整个数据,并通过Integer将每行中的数字(假设一行仅包含一个数字)解析为适当的类型,例如int .parseInt

BTW 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

回答7:

代替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();
}

回答8:

如果要同时读取字符串和整数,则一种解决方案是使用两个扫描仪:

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();

回答9:

为了避免该问题,请在nextInt();之后立即使用nextLine();,因为它有助于清除缓冲区。当您按ENTER时,nextInt();不会捕获新行,因此,稍后会跳过Scanner代码。

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer

回答10:

如果您想快速扫描输入而不会与Scanner类nextLine()方法混淆,请为其使用Custom Input Scanner。

代码:

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()-扫描单个字符
  • scanInt()-扫描整数值
  • scanLong()-扫描Long值
  • scanString()-扫描字符串值
  • scanDouble()-扫描Double值
  • scanInt(int [] array)-扫描完整的Array(Integer)
  • scanLong(long []数组)-扫描完整的Array(Long)

用法:

  1. 将给定代码复制到Java代码下方。
  2. 给定类的初始化对象

ScanReadersc=新的ScanReader(System.in); 3.导入必要的类:

importjava.io.BufferedInputStream;导入java.io.IOException;导入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....

回答11:

与解析输入相比,

sc.nextLine()更好。因为明智的做法会很好。

回答12:

我想我参加聚会很晚了。

如前所述,在获取int值后调用input.nextLine()将解决您的问题。您的代码无法正常工作的原因是,您的输入(在其中输入int的内容)没有其他内容可存储到string1中。我将为整个主题提供更多信息。

nextLine()视为Scanner类中 nextFoo()方法中的奇数。让我们举个简单的例子。假设我们有如下两行代码:

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

如果我们在下面输入值(作为单行输入)

54 234

我们的firstNumbersecondNumber变量的值分别变为54和234。之所以如此工作,是因为当nextInt()方法采用新的换行符( ie \ n ) IS NOT 在值中。它只需要" next int" 继续前进。除了nextLine()之外,其余的nextFoo()方法都是相同的。

nextLine()在获取值后立即生成换行符;这就是@RohitJain表示新换行符已"消耗"的意思。

最后,next()方法仅采用最接近的字符串,而不会生成新行;这使它成为在同一行中采用单独的字符串的首选方法。

我希望这会有所帮助。.编码愉快!

回答13:

使用2个扫描仪对象代替一个

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();

回答14:

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);
    }

回答15:

如果我希望输入非空值

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

回答16:

除了nextLine()之外,

由于nextXXX()方法不读取newline。使用scanner.skip()<>读取任何non-string值(在这种情况下为int)后,我们可以跳过newline。 / code>如下:

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);

回答17:

在我的一个用例中,我有一个读取字符串值并加上几个整数值的场景。我必须使用" for / while循环"来读取值。在这种情况下,以上建议均无效。

使用input.next()代替input.nextLine()解决了该问题。希望这对处理类似情况的人可能有所帮助。

回答18:

为什么不为每个读数使用新的扫描仪?像下面。使用这种方法,您将不会遇到问题。

int i = new Scanner(System.in).nextInt();
回到顶部