首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scanner.hasNext()导致需要输入两次

Scanner.hasNext()导致需要输入两次
EN

Stack Overflow用户
提问于 2022-09-14 20:02:51
回答 2查看 35关注 0票数 0

我正在做作业,遇到了一个问题。该程序创建一个Tree,输出前/in/postorder遍历,然后将它们保存到多个文件中。我遇到的问题是得到输入。输入输入后,键入不同Node的值后,可以键入“已完成”或“退出”。“完成”继续程序与给定的输入,而“退出”只是关闭程序。奇怪的是,以后在代码中不需要键入Nodes的值两次就可以创建Nodes,但是您必须键入“已完成”或“退出”两次才能让程序听你的话。有关守则如下:

代码语言:javascript
复制
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
    fileWriter.write(response + " ");
    response = scanner.next();
}

我已经发现,删除scanner.hasNext()可以使它正常工作,但随后它会消除对此分配所必需的EOF的感知。

下面是程序中使用的完整的三个类: P0:

代码语言:javascript
复制
/**
 * Sources for this class:
 * https://www.w3schools.com/java/java_regex.asp
 * https://stackoverflow.com/questions/14353947/how-to-represent-a-single-space-character-in-a-square-bracket-group
 * https://upload.wikimedia.org/wikipedia/commons/1/1b/ASCII-Table-wide.svg
 * 
 * Sources for shell script and makefile:
 * https://www.cyberciti.biz/faq/run-execute-sh-shell-script/
 * https://www.dummies.com/article/technology/computers/operating-systems/linux/linux-how-to-run-make-150284/
 * https://www.cs.swarthmore.edu/~newhall/unixhelp/javamakefiles.html
 */





package mikefitzgibbon.p0;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class P0{
    public static void main(String args[]) {
        File file = new File("file");
        String input = "";
        
        //there can only be one or 0 arguments in the command line operation
        if(args.length > 1) {
            System.out.println("Please only enter the name of 1 file.");
            System.exit(1);
        }
        //if a filename is specified, try getting the input from it
        else if(args.length == 1){
            file = new File(args[0]);
        }
        //else read from System.in
        else {
            Scanner scanner = new Scanner(System.in);
            String response;
            
            file = new File("input");
            try (FileWriter fileWriter = new FileWriter(file)) {
                System.out.println("Please enter strings to put into the tree.");
                System.out.println("Type \"done\" to end taking in input, and type \"exit\" to prematurely quit.");

                //gets input from console until "exit" or "done" is typed
                response = scanner.next();
                while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
                    fileWriter.write(response + " ");
                    response = scanner.next();
                }

                //exits the program with OK return value
                if(response.equals("exit")) {
                    System.out.println("Prematurely ending program now.");
                    System.exit(0);
                }
            }
            catch(IOException e){
                System.out.println("Had trouble writing to file from System.in.");
            }
        }
        
        //scans file for strings until there are no more data or eof is reached
        try(Scanner scanner = new Scanner(file)){
            while(scanner.hasNextLine()){
               input += scanner.nextLine() + " ";
            }
            scanner.close();
        }
        //exit the program is file name is invalid
        catch(FileNotFoundException e){
            System.out.println("The file name you entered does not exist.");
            System.exit(2);
        }

        //checks input for characters outside of the appropriate ASCII range
        for(char c : input.toCharArray()){
            if(!Character.isLetterOrDigit(c) &! Character.isWhitespace(c)) {
                System.out.println("Your file or console input was not readable."
                        + "\nPlease only use alhpanumeric characters.");
                System.exit(3);
            }
        }
        
        //this is only used as a reference for the filename
        if(file.getName().equals("input"))
            file = new File("output");
            
        //creates the tree from the input and then converts it to the output
        Tree tree = new Tree(input);
        
        //displays the input
        System.out.println("Here is your input for the program.");
        System.out.println(input);
        System.out.println();

        //writes to the files
        System.out.println("Outputting data to files " + 
                file.getName() + ".preorder, " + 
                file.getName() + ".inorder, and " + 
                file.getName() + ".postorder.");
        System.out.println();
        System.out.println("Output for " + file +".preorder: ");
        tree.printPreorder(file.getName());
        System.out.println();
        System.out.println("Output for " + file +".inorder: ");
        tree.printInorder(file.getName());
        System.out.println();
        System.out.println("Output for " + file +".postorder: ");
        tree.printPostorder(file.getName());
        System.out.println();

        System.out.println("Ending program now.");
    }

}

树:

代码语言:javascript
复制
/**
 * Sources for this class:
 * https://www.w3schools.com/java/java_files_create.asp
 * https://www.softwaretestinghelp.com/binary-search-tree-in-java/
 * https://www.youtube.com/watch?v=WLvU5EQVZqY&ab_channel=TECHDOSE
 */


package mikefitzgibbon.p0;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class Tree {
    //nodes that make up this part of the tree
    Node root;

    //constructor calls the buildTree() function
    public Tree(String input){
        buildTree(input);
    }
    
    //takes a list of strings and a root node and creates the tree structure recursively using the addNode helper function
    private void buildTree(String input) {
        Scanner scanner = new Scanner(input);
        
        //recursively builds tree with each word
        while(scanner.hasNext()){
            root = addNode(root,scanner.next());
        }
    }
    
    private Node addNode(Node root, String value){
        //checks root for null and sets it if it is
        if(root == null){
            root = new Node(value);
            return root;
        }
        //compares the first letter of the input to the root's value and recursively traverses tere
        else if(root.getValue().charAt(0) > value.charAt(0))
            root.setLeftNode(addNode(root.getLeftNode(),value));
        else if(root.getValue().charAt(0) == value.charAt(0))
            root.setMiddleNode(addNode(root.getMiddleNode(),value));
        else if(root.getValue().charAt(0) < value.charAt(0))
            root.setRightNode(addNode(root.getRightNode(),value));
        
        //return root if all else fails
        return root;
    }

    //prints the tree printPreorder recursively
    public void printPreorder(String filename){
        try(FileWriter myWriter = new FileWriter(filename + ".preorder")) {
            printPreorder(myWriter, root, 0);
            myWriter.close();
            System.out.println();
            System.out.println("Successfully wrote to the preorder file.");
        } 
        catch (IOException e) {
            System.out.println("An error occurred while writing to the preorder file.");
        }
    }
    
    //helper function for printPreorder()
    private void printPreorder(FileWriter fileWriter, Node root,int depth) {
        //base case
        if(root == null)
            return;
        //write to file and recursive cases
        try{
            String indent = "";
            for(int a = 0 ; a < depth ; a++){
                indent += "  ";
            }
            fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
            System.out.println(indent + root.getValue().charAt(0) + ":" + root.getValue());
        }
        catch(IOException e){
            System.out.println("Something went wrong while writing to the .preorder file.");
            System.exit(4);
        }
        depth++;
        printPreorder(fileWriter, root.getLeftNode(), depth);
        printPreorder(fileWriter, root.getMiddleNode(), depth);
        printPreorder(fileWriter, root.getRightNode(), depth);
    }

    //prints the tree printInorder recursively
    public void printInorder(String filename){
        try(FileWriter myWriter = new FileWriter(filename + ".inorder")) {
            printInorder(myWriter, root, 0);
            myWriter.close();
            System.out.println();
            System.out.println("Successfully wrote to the inorder file.");
        } 
        catch (IOException e) {
            System.out.println("An error occurred while writing to the inorder file.");
        }
    }
    
    //helper function for printInorder()
    private void printInorder(FileWriter fileWriter, Node root,int depth) {
        //base case
        if(root == null)
            return;
        
        //write to file and recursive cases
        int previousDepth = depth;
        depth++;
        printInorder(fileWriter, root.getLeftNode(), depth);
        
        try{
            String indent = "";
            for(int a = 0 ; a < previousDepth ; a++){
                indent += "  ";
            }
            fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
            System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
        }
        catch(IOException e){
            System.out.println("Something went wrong while writing to the .preorder file.");
            System.exit(4);
        }
        
        printInorder(fileWriter, root.getMiddleNode(), depth);
        printInorder(fileWriter, root.getRightNode(), depth);
        
        depth++;
    }

    //prints the tree printPostorder recursively
    public void printPostorder(String filename){
        try(FileWriter myWriter = new FileWriter(filename + ".postorder")) {
            printPostorder(myWriter, root, 0);
            myWriter.close();
            System.out.println();
            System.out.println("Successfully wrote to the postorder file.");
        } 
        catch (IOException e) {
            System.out.println("An error occurred while writing to the postorder file.");
        }
    }
    
    //helper function for printPostorder()
    private void printPostorder(FileWriter fileWriter, Node root,int depth) {
        //base case
        if(root == null)
            return;
        
        //write to file and recursive cases
        int previousDepth = depth;
        depth++;
        
        printPostorder(fileWriter, root.getLeftNode(), depth);
        printPostorder(fileWriter, root.getMiddleNode(), depth);
        printPostorder(fileWriter, root.getRightNode(), depth);
        
        try{
            String indent = "";
            for(int a = 0 ; a < previousDepth ; a++){
                indent += "  ";
            }
            fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
            System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
        }
        catch(IOException e){
            System.out.println("Something went wrong while writing to the .postorder file.");
            System.exit(4);
        }
    }

    //getter and setter
    public void setRoot(Node node) {
        root = node;
    }

    public Node getRoot() {
        return root;
    }

}

节点:

代码语言:javascript
复制
/**
 * Sources for this class:
 * https://www.softwaretestinghelp.com/binary-search-tree-in-java/
 */
package mikefitzgibbon.p0;

public class Node {
    //this is how the tree branches out, 3 children per node
    Node left, middle, right;
    String value = "";
    
    public Node(String val) {
        value=val;
    }
    
    //getters and setters
    public void setRightNode(Node node) {
        right=node;
    }

    public void setLeftNode(Node node) {
        left=node;
    }

    public void setMiddleNode(Node node) {
        middle=node;
    }

    public Node getRightNode() {
        return right;
    }

    public Node getLeftNode() {
        return left;
    }

    public Node getMiddleNode() {
        return middle;
    }

    public String getValue() {
        return value;
    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-14 20:51:08

scanner.hasNext()将阻塞(冻结线程),直到用户输入发生。您可能会认为“不,它将返回false,因为目前没有可用的令牌--没有'next'",但这不是它的工作方式。事实上,目前可能没有下一个。但谁知道以后会发生什么呢?也许用户键入CTRL+C,关闭管道,因此,hasNext()现在将返回false,因为永远不会有下一个令牌。或者,用户键入某些内容,然后返回true,因为现在显然有了下一个令牌。这就是为什么它阻碍:它不能给出一个特定的答案,除非你做某事。

这可能是没有意义的-记住‘标准输入’不是键盘。这是..。连接到标准输入的任何流。默认情况下,这是一个键盘,但运行您的应用程序与java -jar whatever.jar <somefile.txt,现在是该文件。有一个有限的大小。当您到达“文件的末尾”时,hasNext()将开始返回false。您通常无法到达“键盘的末端”,但是抽象并不是专门为键盘设计的。

换句话说,您的代码:

代码语言:javascript
复制
response = scanner.next();
while(scanner.hasNext() && ....

威尔:

从标准input.

  • Will...读取令牌的
  1. 再次从标准输入读取令牌(因为hasNext()会这样做。如果它成功了,它将返回true。如果现在没有令牌,也永远不会有令牌,则返回false)。

这解释了为什么您必须输入两次输入。解决方案是删除那里的hasNext调用。把它移到while循环中。不要在循环中使用response = scanner.next(),而是执行如下操作:

代码语言:javascript
复制
  if (!scanner.hasNext()) return; // or break, or System.exit(0), or whatever you want.
  response = scanner.next();
}
票数 2
EN

Stack Overflow用户

发布于 2022-09-14 20:11:50

我发现将scanner.hasNext()放在表达式的末尾解决了问题,但我不完全确定如何解决这个问题。以下是更新的代码:

代码语言:javascript
复制
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(!response.equals("exit") && !response.equals("done") && scanner.hasNext()) {
    fileWriter.write(response + " ");
    response = scanner.next();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73722590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档