简体   繁体   中英

try catch with a do while loop

Using my code I am trying to tell the user to enter not to enter a string until the user an integer but while running the program it is infinite.

public static void main(String[] args) {

  int age = 1;
  Utilisateur utilisateur = new Utilisateur();
  Scanner u = new Scanner(System.in);

  System.out.println("Enter your Name: ");
  utilisateur.setNom(u.nextLine());
  System.out.println("Enter your Surname: ");
  utilisateur.setPrenom(u.nextLine());
  System.out.println("Enter your Matricule: ");
  utilisateur.setMatricule(u.nextLine());
  System.out.println("Enter your Sexe: ");
  utilisateur.setSexe(u.nextLine());

  do {
    try {
      System.out.println("Enter your Age: ");
      utilisateur.setAge(u.nextInt());
      System.out.println(utilisateur.detail());
      age = 2;
    } catch (Exception e) {
      System.out.println("Enter a valid age ");

    }
  }
  while (age == 1);
}
}

You should add u.nextLine(); in catch block in order to skip invalid value entered in the scanner.

Okay, so let's start by cleaning up the code a bit. The whole "age" variable is a bit weird. It seems like it's containing some status on whether or not you've read the age. But that's kind of boolean, isn't it? So let's redo the code with that in mind. I'll change the do-while to a simple while first, but we can change it back afterwards. Furthermore, it might be a good idea to rename "u" to "keyboard", or "clavier" if you prefer french.

    public static void main(String[] args) {
        Utilisateur utilisateur = new Utilisateur();
        Scanner clavier = new Scanner(System.in);

        System.out.println("Enter your Name: ");
        utilisateur.setNom(clavier.nextLine());
        System.out.println("Enter your Surname: ");
        utilisateur.setPrenom(clavier.nextLine());
        System.out.println("Enter your Matricule: ");
        utilisateur.setMatricule(clavier.nextLine());
        System.out.println("Enter your Sexe: ");
        utilisateur.setSexe(clavier.nextLine());

        boolean hasEnteredAge = false;
        while(!hasEnteredAge) {
                System.out.println("Enter your Age: ");
                String ageInput = clavier.nextLine().trim(); // remove leading and trailing whitespace. " 21 " becomes "21".
            try {
                int age = Integer.parseInt(ageInput);
                utilisateur.setAge(age);
                System.out.println(utilisateur);
                hasEnteredAge = true;
            } catch (Exception e) {
                System.out.println("Enter a valid age.");
            }
        }
    }
}

Notice that I moved the variable to the beginning of the loop, which is where we need to know about this fact, and how we initialized it to false. We now have to set it to be true afterwards.

But there is a bit more to do here I think. We have a bunch of prints, followed by inputs. Surely, this can be farmed out to a method, that makes this look a bit nicer? But before we do that, we should take another look at the loop. We can do the loop in a multitude of ways. We can do

        do {
            System.out.println("Enter your Age: ");
            String ageInput = clavier.nextLine().trim(); // remove leading and trailing whitespace. " 21 " becomes "21".
            try {
                int age = Integer.parseInt(ageInput);
                utilisateur.setAge(age);
                System.out.println(utilisateur);
                break; // this means that we should exit the loop
            } catch (Exception e) {
                System.out.println("Enter a valid age.");
            }
        }while(true); // So if we ever get here, we're not done.

Here, we're relying on the break to get us out of the loop. This works, but personally I don't like it. It's not a wrong thing to do however, so I'll just leave it in. You can also have it like the old do-while loop:

boolean hasEnteredAge = false;
        do {
                System.out.println("Enter your Age: ");
                String ageInput = clavier.nextLine().trim(); // remove leading and trailing whitespace. " 21 " becomes "21".
            try {
                int age = Integer.parseInt(ageInput);
                utilisateur.setAge(age);
                System.out.println(utilisateur);
                hasEnteredAge = true;
            } catch (Exception e) {
                System.out.println("Enter a valid age.");
            }
        } while (!hasEnteredAge);

Whichever you choose though, it's fine. Now let me just tackle the issue of the printlines and reads:

If you add a method "prompt" that takes a prompt and returns a string, you can simplify this down quite handily like so:

public class EnterNameHere {
    private static Scanner clavier = new Scanner(System.in);

    public static String prompt(String prompt) {
        System.out.println(prompt);
        return clavier.nextLine().trim();
    }
    // ... The rest is as before.
}

Now, the reading in part becomes very simple:

    public static void main(String[] args) {
        Utilisateur utilisateur = new Utilisateur();

        utilisateur.setNom(prompt("Enter your Name: "));
        utilisateur.setPrenom(prompt("Enter your surname: "));
        utilisateur.setMatricule(prompt("Enter your matricule: "));
        utilisateur.setSexe(prompt("Enter your sex: "));

And an important question arises: If we are to do this for string inputs, why not for integer (int) inputs as well? I propose:

public static int promptInt(String prompt) {
        String value = prompt(prompt);
        try {
            return Integer.parseInt(value);
        } catch(NumberFormatException ignored) {
            System.out.println("Invalid number: '" + value + "'");
            return promptInt(prompt); // We try again!
        }
    }

Notice if you would be so kind, that if calling the method promptInt doesn't work, we print an error message and just try again. This will only work for a few hundred times before it all crashes, but that should be enough. (You can of course adapt the while-loop approach from earlier if you don't want that to happen.) This trick of a method or function calling itself multiple times until the work is done is called "recursion" and it is as powerful as looping is. It can be confusing to people who are new to programming, but I think this example is straightforward. If it isn't, you can simply substitute the whole loop thing as mentioned. Of course, there is one method called prompt, and another called promptInt. To avoid any confusion we rename the prompt-method to promptString, and the entire program simply becomes:

public class YourNameHere {
    private static final Scanner clavier = new Scanner(System.in);

    public static String promptString(String prompt) {
        System.out.print(prompt);
        return clavier.nextLine().trim();
    }

    public static int promptInt(String prompt) {
        String value = promptString(prompt);
        try {
            return Integer.parseInt(value);
        } catch(NumberFormatException ignored) {
            System.out.println("Invalid number: '" + value + "'");
            return promptInt(prompt); // We try again!
        }
    }

    public static void main(String[] args) {
        Utilisateur utilisateur = new Utilisateur();

        utilisateur.setNom(promptString("Enter your Name: "));
        utilisateur.setPrenom(promptString("Enter your surname: "));
        utilisateur.setMatricule(promptString("Enter your matricule: "));
        utilisateur.setSexe(promptString("Enter your sex: "));
        utilisateur.setAge(promptInt("Enter your age: "));

        System.out.println("You have created an utilisateur: " + utilisateur);
    }
}

Plus the definition of Utilisateur of course. I think this is a much simpler way to do it, by creating methods that does the boring work for you, you can read the code in the main method and immediately understand what is going on. If you need to understand how, you can go up and look at the helping prompt-methods.

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