简体   繁体   中英

Need Help Fixing An Exception Error in my Code

I am working on a Lab on the site Zybooks and I have completed the following code below:

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) + ".");
    }
  }
  }

The Exception Error that I receive is this:

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)

When I run the following code in an IDE everything works just fine. However when I try running it in Zybooks I get an exception error. I've come to learn that this is because when I don't add a space after I enter two names that Zybooks gives an exception error. However when I add a space after the last name the code compiles as intended. For grading purposes I need the code to compile without a space from the keyboard, thus I am asking how I can get this code to compile. I've tried manually adding whitespace but nothing has worked.

Any help would be very much appreciated

Looking at the code it's obvious that you have three (3) specific User entry prompts to deal with. The User must supply a First Name , then the User needs to supply a Middle Name , and then finally the User needs to supply a Last Name . As with any input each of these names needs to be validated for proper context. This would include the rules for names, for example everyone has a First Name and Last Name but not everyone has a Middle Name also first and last names can contain two name words (ex: De Vanderholt).

When you have three specific prompts for the User to fill in then let them know exactly where they are at. Display on Screen what the User is expected to enter. It's always a good idea to place each prompt into a loop so that the input can be validated and if there is a problem the User is given the opportunity to provide actual valid data (in this case a valid name).

In your code you use the Scanner#next() method to retrieve the input for both First Name and Middle Name(s) however this method will not play well with multi word names since the next() method is token based. This means that if a two word name is supplied to the First Name prompt then only the first word is retrieved and the second word is automatically applied to the Middle Name prompt. You don't even get a chance to enter the middle name. This is no good unless special code is put in place to take car of this situation. It's just better not to use the next() method in this case and simply use the Scanner#nextLine() method for all your prompts. Keep in mind however that the Scanner#next() method will work just fine if you know that only a single name word will be provided by the User but this method is better used in conjunction with the Scanner#hasNext() method.

Look at your code. As said earlier, everyone has a Last Name but not everyone has a Middle Name so why have this line of code (unless your rules include the fact that last names can be nothing):

 if (lastName.contains("")){

It should actually never be allowed to come to this scenario where the last name contains nothing, don't even accept the fact unless it's a middle name. If the supplied Last Name was validated then you would never need to worry about this situation unless of course your rules allow it. The example code below does not allow it.

Because there are three prompt which basically do the same thing and require the same basic validation a helper method ( getName() ) is used so as to eliminate the need for duplicate code:

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());
     */
}

The Helper Method ( 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM