我对 scanner.next() 在 JAVA 中的使用感到困惑

I'm confused the use of scanner.next()in JAVA

我的目的是打印字符串中的所有字符。而我想检查一个字符是“q”还是“Q”,只要打破循环并结束程序即可。假设我使用“Hello World You”作为输入,输出只能是

World
Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.Scanner.throwFor(Scanner.java:937)
    at java.base/java.util.Scanner.next(Scanner.java:1478)
    at tictactoe.ScannerDemo.main(ScannerDemo.java:22)

但是如果我评论那个if语句,输出是正确的,就是

Hello
World
K

所以,我不知道为什么会发生这种情况以及如何解决? 这是我的代码:

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

        String s = "Hello World K";

        
        Scanner scanner = new Scanner(s);

        
        while (scanner.hasNext()) {
            //if I comment the if statement, the result is normal
            if(scanner.next().equalsIgnoreCase("q")){
                break;
            }

            System.out.println(scanner.next());
        }

        // close the scanner
        scanner.close();
    }
}

查看 scanner.hasNext() 以及您调用 scanner.next() 的频率,即每次调用 hasNext() 的 2 次。由于 next() return 是下一个元素,第一个调用将 return “Hello”,第二个 return 将是“World”,正如您已经注意到的那样。

现在,在循环的第二次迭代中,仍然有一个值为“You”的“下一个”元素,它是通过 if 语句中对 next() 的调用 return 编辑的。然而,下一次调用 next() 中断,因为没有更多的输入。

要解决此问题,请仅调用 next() 一次并保留对字符串的引用:

while (scanner.hasNext()) {
   String token = scanner.next();
   if(token .equalsIgnoreCase("q")){
       break;
   }

   System.out.println(token );
}

顺便说一句,I want to check if one character is "q" or "Q" 与您的代码不匹配,因为您只检查了整个 字符串 。如果这是预期的行为,那么你没问题,但否则你需要使用 toCharArray()charAt(index) 来检查 individual 字符(虽然这可能很奇怪,例如,如果输入是“我可以问一个问题吗:这是打印出来的吗?”它将在“问题”处停止。

你调用 next() 两次而没有检查是否有剩余的令牌...

尝试

while (scanner.hasNext()) {

  String nextValue = scanner.next();
            
  if(nextValue.equalsIgnoreCase("q")){
    break;
  }

  System.out.println(nextValue);
}

看看你的代码

        while (scanner.hasNext()) {
            //if I comment the if statement, the result is normal
            if(scanner.next().equalsIgnoreCase("q")){
                break;
            }

            System.out.println(scanner.next());
        }

在调用 next() 的 if 语句的条件下。这不会抛出任何异常,因为它已经被 hasNext() 调用检查过。但是稍后您在 hasNext() 调用未检查的情况下打印令牌。此外,在 next() 调用期间,先前的标记在 if 条件中丢失。

尝试使用..

        while (scanner.hasNext()) {
            String nextToken = scanner.next();
            if (nextToken.equalsIgnoreCase("q")) {
                break;
            }

            System.out.println(nextToken);
        }