【问题标题】:Endless loop in a text menu when handling InputMismatchException处理 InputMismatchException 时文本菜单中的无限循环
【发布时间】:2016-10-29 11:48:56
【问题描述】:

我有一个家庭作业,要创建一个带有循环菜单的课程来管理汽车队列。我们在上一节课中学习了队列。

我的菜单运行良好,直到它捕获InputMismatchExceptionQueueEmptyException,之后它进入无限循环,甚至没有在userInput.nextInt(); 处停止。它在捕获 QueueFullException 时有效,但在其他时无效。

我的代码是:

import java.util.*;

public class CarQueueManagement {

    public static void main(String[] args) throws InputMismatchException, QueueFullException{
        ArrayQueue queue = new ArrayQueue(3);;
        Scanner userInput = new Scanner(System.in);
        int carNum;
        int choice = 0;

        queue.add(1);

        OUTER:
        while (true) {
            try{
                System.out.println("ΜΕΝΟΥ:\n\t1. Άφιξη αυτοκινήτου");
                System.out.println("\t2. Αναχώρηση αυτοκινήτου\n\t3. Κατάσταση ουράς\n\t4. Έξοδος");
                System.out.print("\n\tΕπιλογή (1-4): ");
                choice = userInput.nextInt();

                switch (choice){
                    case 1:
                        System.out.print("\n\tΆφιξη αυτοκινήτου:\n\t\tΑριθμός Αμαξιού");
                        carNum = userInput.nextInt();
                        queue.add(carNum);
                        break;
                    case 2:
                        if(queue.isEmpty()){
                            System.out.println("\n\tΗ ουρά είναι άδεια, δεν χριάζεται διαγραφή.\n\n");
                            break;
                       }
                       String answer;
                        while(true){
                            System.out.print("\n\tΑναχώρηση αυτοκινήτου\n\t\tΕπιβεβαίωση; (y/n): ");
                            answer = userInput.next();
                            if(answer.equals("y")){
                                queue.remove();
                                break;
                            }
                            else if(answer.equals("n"))
                            break;
                        }
                        break;
                    case 3:
                        System.out.println("\n\tΚατάσταση ουράς:");
                        if(queue.isEmpty()) System.out.println("\t\tΗ ουρά είναι άδεια.\n\n");
                        else if(queue.isFull()) System.out.println("\t\tΗ ουρά είναι γεμάτη.\n\n");
                        else System.out.println("\t\tΗ ουρά έχει άδιες θέσοις.\n\n");
                        break;
                    case 4:
                        System.out.print("\n\nΕξοδος");
                        break OUTER;
                    default:
                        break;
                }
            }catch (InputMismatchException exc){
                System.out.println("\t\tΛΑΘΟΣ ΕΙΣΑΓΩΓΗ\n");  
            }catch(QueueEmptyException exc){
                System.out.println("\t\t" + exc.getMessage() + "\n");
            }catch(QueueFullException exc){
                System.out.println("\t\t" + exc.getMessage() + "\n");
            }
        }    
    }
}

【问题讨论】:

  • 你知道while (true)在做什么吗?
  • 我知道,直到我休息一下;指向它循环,但我也知道当我有输入代码时,它需要停止接受输入。它适用于QueueFullException,但不适用于其他人。其他 2 个异常循环遍历所有内容,甚至没有停在 userInput.nextInt();
  • 我打赌你输入数字后按回车键?
  • 我按 Enter 我使用 NetBeans 并使用已实现的 Run 选项测试我的代码,因为您可以告诉我,我只希望我的代码退出循环并通过选择 4 女巫终止程序用希腊语说“退出”。

标签: java loops exception while-loop switch-statement


【解决方案1】:

来自java.util.Scanner docs 的介绍部分(强调我的):

当扫描器抛出InputMismatchException时,扫描器不会传递导致异常的令牌,因此它可能会被其他方法检索或跳过。

没有详细信息,您的 while(true) 循环是:

while (true) {
    try{
        choice = userInput.nextInt();
        switch (choice){
            case 1:
             ...
        }
    } catch (InputMismatchException exc){
        // Do nothing.
    }
}

当用户输入无法转换为整数的内容时,Scanner 会抛出 InputMismatchException,您会捕获并忽略它。然后while 循环回到顶部,尝试执行userInput.nextInt()... 但Scanner 仍在查看相同的无效输入,因此它立即抛出另一个@ 987654332@,您再次捕获并忽略它。在while 循环的顶部继续执行,它再次调用nextInt()...并且循环永远继续。

您必须强制 Scanner 跳过错误输入,因此您的 catch 块应如下所示:

}catch (InputMismatchException exc){
    System.out.println("\t\t[chastise the user in Greek]\n");  
    userInput.next();  // Skip invalid input.
}

其他建议

一般来说,很多小方法比一个大方法更容易理解。嵌套的while 循环和switch 语句特别难以理解。我只能通过将巨大的 main 方法分解为许多更小的私有静态方法来找到错误。

至少,每个菜单项都可以用自己的方法处理。我还去掉了break 标签,将整个菜单放入一个单独的方法中,该方法返回一个boolean,指示用户是否完成。这将main 内部的整个循环减少到:

boolean done = false;
while (! done) {
    try{
        done = handleUserInput(queue, userInput);
    } catch (InputMismatchException exc) {
        System.out.println("\nINPUT ERROR\n");
        userInput.next();
    } // Other catch blocks as before...
}

我的handleUserInput 并没有做太多 --- 它获取用户输入,确定应该处理该输入的方法,然后返回 truefalse... 它也可以比这更简单.

private static boolean handleUserInput(
  final ArrayQueue queue,
  final Scanner userInput
) {
    boolean done = false;
    printMenu();
    int choice = userInput.nextInt();
    switch (choice) {
        case 1:
            addToQueue(queue, userInput);
            break;
        case 2:
            removeFromQueue(queue, userInput);
            break;
        case 3:
            displayQueue(queue);
            break;
        case 4:
            printExitMessage();
            done = true;
            break;
        default:
            break;
    }
    return done;
}

将各种菜单活动拆分为单独的方法使它们更加更易于遵循。例如,当 main 中的所有逻辑都混合在一起时,很难判断像 carNumanswer 这样的变量是否是问题的一部分。在这个版本中,carNum 是一个被困在 addToQueue 方法中的局部变量,所以当我在其他任何地方工作时,我可以完全忽略它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2018-07-13
    相关资源
    最近更新 更多