Scanner.hasNext()导致需重复输入done/exit的问题求助
问题描述
作业要求实现程序完成以下功能:创建树、输出前/中/后序遍历结果并保存至文件。但输入环节存在异常:输入节点值后,必须输入两次done或exit才能触发对应操作(done继续执行,exit关闭程序),而节点值无需重复输入即可正常创建。相关输入逻辑代码如下:
//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检测功能。
问题原因
原逻辑的核心问题在于循环判断顺序:
- 先读取一个
response,进入循环时首先执行scanner.hasNext()——该方法会阻塞等待下一个输入,哪怕当前的response已经是done或exit。 - 只有再次输入内容后,
scanner.hasNext()返回true,才会继续判断response是否为终止词,此时才会退出循环,导致需要两次输入终止指令。
解决方案
调整循环逻辑,先检测是否有下一个输入(保留EOF检测),再读取内容,读取后立即判断是否为终止词,这样既保留EOF检测能力,又无需重复输入终止指令。修改后的逻辑如下:
//gets input from console until "exit" or "done" is typed or EOF is reached while (scanner.hasNext()) { response = scanner.next(); if (response.equals("exit") || response.equals("done")) { break; } fileWriter.write(response + " "); }
修改说明
- 先通过
scanner.hasNext()检测是否还有输入(包含EOF检测),避免不必要的阻塞。 - 读取输入后立即判断是否为终止词,若是则直接跳出循环,无需等待下一次输入。
- 仅当输入不是终止词时才写入文件,逻辑更清晰直观。
修改后的完整代码
P0类
/** * 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."); // 修改后的输入逻辑 while (scanner.hasNext()) { response = scanner.next(); if (response.equals("exit") || response.equals("done")) { break; } fileWriter.write(response + " "); } //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."); } }
Tree类
/** * 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; } }
Node类
/** * 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; } }
内容的提问来源于stack exchange,提问作者The Dog on the Log
相关产品推荐
相关产品推荐

