首页 > 解决方案 > 需要帮助修复我的代码中的异常错误

问题描述

我正在 Zybooks 网站上的实验室工作,我已经完成了以下代码:

import java.util.Scanner; 

public class LabProgram {
public static void main(String[] args) {
    Scanner scnr = new Scanner(System.in);

    String firstName;
    String middleName;
    String lastName;

    firstName = scnr.next();
    middleName = scnr.next();
    lastName = scnr.nextLine();
   

    if (lastName.contains("")){
        System.out.println(middleName + ", " + firstName.charAt(0) + ".");
    }
    else {
        lastName = lastName.substring(1);
        System.out.println(lastName + ", " + firstName.charAt(0) + "." + middleName.charAt(0) + ".");
    }
  }
  }

我收到的异常错误是这样的:

Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at LabProgram.main(LabProgram.java:13)

当我在 IDE 中运行以下代码时,一切正常。但是,当我尝试在 Zybooks 中运行它时,出现异常错误。我了解到这是因为当我在输入两个名称后不添加空格时,Zybooks 会出现异常错误。但是,当我在姓氏后添加一个空格时,代码会按预期编译。出于评分目的,我需要在没有键盘空格的情况下编译代码,因此我在问如何才能编译此代码。我试过手动添加空格,但没有任何效果。

任何帮助将不胜感激

标签: javadebuggingerror-handlingcompiler-errorsruntime-error

解决方案


查看代码很明显,您需要处理三 (3) 个特定的用户输入提示。用户必须提供名字,然后用户需要提供中间名,最后用户需要提供姓氏。与任何输入一样,这些名称中的每一个都需要针对正确的上下文进行验证。这将包括名称规则,例如每个人都有名字姓氏,但不是每个人都有中间名,名字和姓氏也可以包含两个名字词(例如:De Vanderholt)。

当您有三个特定提示供用户填写时,请让他们确切知道他们在哪里。在屏幕上显示用户预期输入的内容。将每个提示放入一个循环中总是一个好主意,以便可以验证输入,如果有问题,用户有机会提供实际的有效数据(在这种情况下是有效的名称)。

在您的代码中,您使用Scanner#next()方法来检索名字中间名的输入,但是此方法不适用于多词名称,因为next()方法是基于令牌的。这意味着如果将两个单词的名称提供给First Name提示,则仅检索第一个单词,而将第二个单词自动应用于 Middle Name 提示。你甚至没有机会输入中间名。除非设置特殊代码来处理这种情况,否则这是不好的。在这种情况下最好不要使用next()方法,而只需对所有使用Scanner#nextLine()方法你的提示。但是请记住,如果您知道用户只提供一个名称单词,则Scanner#next()方法将正常工作,但此方法最好与Scanner#hasNext()方法结合使用。

看看你的代码。如前所述,每个人都有一个姓氏,但不是每个人都有一个中间名,那么为什么有这行代码(除非你的规则包括姓氏可以是任何东西):

 if (lastName.contains("")){

实际上,绝不应该允许出现姓氏不包含任何内容的情况,甚至不接受这个事实,除非它是中间名。如果提供的姓氏经过验证,那么您将永远不需要担心这种情况,除非您的规则当然允许。下面的示例代码不允许这样做。

因为有三个提示基本上做同样的事情并且需要相同的基本验证,所以使用了一个辅助方法(getName())来消除重复代码的需要:

public static void main(String[] args) {
    Scanner scnr = new Scanner(System.in);
     
    // First Name:
    String firstName = getName(scnr, "First");
    
    // Middle Name:
    String middleName = getName(scnr, "Middle");

    // Last Name:
    String lastName = getName(scnr, "Last");

    System.out.println(new StringBuilder("")
            .append(lastName).append(", ")
            .append(firstName.charAt(0))
            .append(". ")
            .append(middleName.isEmpty() ? "" : middleName.charAt(0))
            .append(middleName.isEmpty() ? "" : ".").toString());

    //                    O R
    /*
    System.out.println(new StringBuilder("")
                       .append(lastName).append(", ")
                       .append(firstName)
                       .append(" ")
                       .append(middleName)
                       .toString());
    */
    //                    O R
    /*
    System.out.println(new StringBuilder("")
                       .append(firstName)
                       .append(" ")
                       .append(middleName)
                       .append(middleName.isEmpty() ? "" : " ")
                       .append(lastName)
                       .toString());
     */
}

辅助方法(getName()):

private static String getName(final Scanner scnr, final String nameTitle) {
    String name = "";
    while (name.isEmpty()) {
        System.out.print("Enter your " + nameTitle + " Name: --> ");
        // Get input and trim off leading/trailing whitespaces, etc 
        name = scnr.nextLine().trim();
        // Is this for a Middle Name?
        if (nameTitle.equalsIgnoreCase("middle")) {
            // If nothing was supplied then there is no 
            // middle name so break out of prompt loop.
            if (name.isEmpty()) {
                break;
            }
        }
        // Validate name...
        /* Does the supplied name only contain A to Z characters 
           in any letter case. Add characters to the regular 
           expression as you see fit. (?i) means any letter case. */
        if (name.matches("(?i)[A-Z. ]+")) {
            // Yes, it does...
            /* Ensure 'first' character of each name word (if more than one) 
               is upper letter case.       */
            String[] tmp = name.split("\\s+");
            StringBuilder nme = new StringBuilder("");
            for (String str : tmp) {
                if (!Character.isUpperCase(str.charAt(0))) {
                    str = str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
                }
                if (!nme.toString().isEmpty()) {
                    nme.append(" ");
                }
                nme.append(str);
            }
            name = nme.toString();
        }
        // No it doesn't so inform User of the mistake and to try again.
        else {
            System.err.println("Invalid " + nameTitle + " Name Supplied! (" + name + ") Try Again...");
            name = ""; // Set to null string so as to re-prompt.
        }
    }
    return name;
}

推荐阅读