does not loop and display the error message - java

Ok, I have this code that asks an input for a username and a password. I used JOptionPane. What I want with the program is to display an error message if the the input on the username field has a number, and goes back to the previous dialog box asking for the username again. I have this while loop yet it does not function the way it should. Please do help. The program does not show the error message on my catch method and neither does it loop for the dialog box to display.
public class SwingExercise {
public static void main(String[] args) {
String name = "";
String pw = "";
boolean input = true;
boolean hasDigit = false;
while (input) {
try {
while (name.equals("")) {
name = JOptionPane.showInputDialog(null, "Enter username:");
if (name.equals("")) {
JOptionPane.showMessageDialog(
null, "No input.", "Error", JOptionPane.ERROR_MESSAGE);
name = "";
}
while (hasDigit) {
for (int i = 0; i < name.length(); i++) {
if (Character.isDigit(name.charAt(i))) {
throw new InputMismatchException();
}
}
hasDigit = false;
}
}
input = false;
while (pw.equals("")) {
pw = JOptionPane.showInputDialog(null, "Enter password:");
if (pw.equals("")) {
JOptionPane.showMessageDialog(
null, "No input.", "Error", JOptionPane.ERROR_MESSAGE);
pw = "";
}
}
} catch (NullPointerException e) {
System.exit(0);
} catch (InputMismatchException e) {
JOptionPane.showMessageDialog(
null, "Invalid input.", "Error", JOptionPane.INFORMATION_MESSAGE);
}
}
}
Please do mention any comments regarding the other lines in my code and if there are any unnecessary lines. Thank you in advance :)

There seems to be absolutley no way to get into the while(hasDigit) loop because you have it set to false, and there is nothing setting it to true.

One problem is that the value of hasDigit will always remain false. You probably will want to define hasDigit as true initially.
boolean hasDigit = true;

Some comments on style, since you asked:
In general, you want your try() blocks to be as short as possible, so it's clear which lines you're expecting to throw an exception. Otherwise you may unexpectedly catch an exception from a line that you didn't think could generate it, and then handle it incorrectly. This means the code will probably be longer, but it's far more important that it be easier to maintain and debug.
When it's legitimate for a string to be null, it's common to write if ("".equals(name)) rather than if (name.equals("")). Since the hard-coded empty string can never be null, you needn't surround the code with a try/catch block.
There's no need to set name or pw to the empty string inside an if() that tests to see if they're empty.
You probably don't want to echo the password. See JOptionPane to get password.
The code explicitly forbids digits in the name but accepts every other character, including punctuation and special characters. It's generally good programming practice to use a whitelist of acceptable input, rather than a blacklist of forbidden input. That way you'll never be surprised by invalid data that's unexpectedly accepted.
The outermost while() loop will exit if the password is invalid, since input only depends on the name. Better to set input to false at the top of the loop, then set it to true if either input is invalid.
Since the name and pw blocks are almost identical (they prompt for a non-empty string), consider extracting them into a helper function. You'll want to pass parameters that specify the prompt and whether or not to echo the input back to the user.

Related

Java exception, RegEx

i'm new to java programming and i'm trying to validate an email value using RegEx, the program should throw an exception when the user provides a wrong value, i managed to do this with an if-else. However, when i try to handle the error using a try-catch block the RegEx does not work anymore and the wrong value gets displayed anyways. How can i solve this?
here's the code
try {
String emailRegex = "^(.+)#(.+).(.+)$";
if(email.matches(emailRegex)) {
Pattern pattern = Pattern.compile(emailRegex);
System.out.println(pattern.matcher(email).matches());
} else {
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException ex) {
System.out.println(ex.getLocalizedMessage());
}
This regular expression rejects valid email addresses. Even if you did fix it. For example, foo#bar is actually valid (top-level domains can contain MX records. A few do!). This is the general formula for 'is it valid email':
Does it contain spaces? If yes, reject.
Does it contain at least 1 #? If no, reject.
Is the last # at position 0 (i.e. at the start), or at the end? Reject.
Otherwise, pass. There are a few invalid emails that would nevertheless pass, but this is by and large no problem: foo#bar is not really legal, but the only real way to know that, is to send an email to it and request the user click a link inside it before they can continue. No regexp is ever going to figure out if the email address entered by a user is in fact a valid email address, let alone an email address that belongs to that user, hence, there is no real point in trying to go any further than that. You're attempting to catch honest typoes, not actually validate anything, because that is impossible. Note that it can easily become legal tomorrow - someone just needs to set up the bar top level domain and make sure there's an MX record for it in its DNS registration and voila. foo#bar is now legal.
Your regex is close to this ideal; you just want ^.+#.+$
NB: If you want to break spec and reject any email addresses to top-level domains, your regex is broken. Your intent is clearly to want foo#a.b, but you don't do that - that middle ., nestled between (.+), is still a regex dot operator, meaning: "any character". You'd want \\. for that instead. But, don't - as I said, TLDs are themselves rare as mail servers, but valid according to spec!
Fix this and your code 'works', but note that your code can go only one of two ways:
The regexp matches, in which case you again run the string through the regexp (seems rather pointless to do it twice!), and then trivially prints 'true'. The entire Pattern pattern = ...; System.out.println(...) might as well be System.out.println("true"); - that's what it will always do - yes, the regexp that just matched, is still going to match, of course.
The regexp does not match, in which case we get to the else block, which throws an exception. This then goes to the catch block which can only catch this (as nothing else throws IllegalArgumentEx here), and prints the 'localized message', which is null here.
So, this code prints true if it matches, and null if it does not. That seems.. weird. And is needlessly complicated if that's what you wanted.
Better:
class Test {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^.+#.+$");
public static boolean isValidEmail(String email) {
return EMAIL_PATTERN.matcher(email).matches();
}
public static void main(String[] args) {
var keyboard = new Scanner(System.in);
while (true) {
System.out.print("Enter an email address: ");
String line = keyboard.nextLine().trim();
if (line.isEmpty()) System.exit(0);
if (isValidEmail(line)) {
System.out.println("Valid");
} else {
System.out.println("Not valid");
}
}
}
}
The try/catch block do not add anything useful here. You use try/catch when you want to transfer an error condition across method calls, not within the same method call, and not when the only meaningful data you can convey is a boolean flag. If that's all you have ('valid' or 'not valid'), almost always you just want a boolean.
If you really want the exception instead:
class Test {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^.+#.+$");
public static void validateEmail(String email) throws IllegalArgumentException {
if (!EMAIL_PATTERN.matcher(email).matches()) {
throw new IllegalArgumentException("Email '" + email + "' is not valid");
}
}
public static void main(String[] args) {
var keyboard = new Scanner(System.in);
while (true) {
System.out.print("Enter an email address: ");
String line = keyboard.nextLine().trim();
if (line.isEmpty()) System.exit(0);
try {
validateEmail(line);
System.out.println("Valid");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
}

How to compare a returned string from a method with another string in the main method?

The idea is that the while loop should loop through the code if the result is "wrong password",
until the correct password is entered and breaks the loop when it matches the login method return value.
while (true){
System.out.println("\nLogin: ");
System.out.println("\nEnter a username: ");
String loginUsername = sc.nextLine();
System.out.println("Enter a password: ");
String loginPassword = sc.nextLine();
System.out.println(login(loginUsername,loginPassword));
if (login(loginUsername,loginPassword).equalsIgnoreCase("Successfully logged in!")) {
break;
}
}
this code is the return statements from the login method
if (check == true){
return ("\nSuccessfully logged in!");
} else {
return ("\nWrong username/password");
}
But "Successfully logged in!" is not the same string as "\nSuccessfully logged in!".
More importantly... Why use strings for this at all? If you want to know whether something is true or false, there's a perfectly good data type to convey that information. Return that type instead:
return check;
Rename the method to something more meaningful than login, and use its result in a semantically clear condition:
if (isLoginSuccessful(loginUsername,loginPassword)) {
break;
}
This puts the semantics of what you're doing in the code itself, rather than in magic strings that you need to copy/paste everywhere and manually keep track of. Which, already in this one tiny example, you've lost track of by making the strings different. (With the added benefit that using booleans for conditional logic probably performs a little better than string comparison.)

Can't figure out a proper way to do a loop that loops until input is valid

I'm still learning java programming so forgive my lack of knowledge.
It probably is the most simplest thing ever, but I just can't for the life of me figure out a better way to have the checkTaskDescription method loop until the user input description is below the character limit. So far this is the only way I've been able to do it but it clearly repeats the input dialog twice.
This is the part that executes it
do{
checkTaskDescription();
}
while (checkTaskDescription() == false);
This is the checkTaskDescription method that is being executed:
public boolean checkTaskDescription() {
taskDesc = JOptionPane.showInputDialog(null, "Please enter a short description of the task");
if (taskDesc.length() > 50) {
JOptionPane.showMessageDialog(null, "Please enter a task description of less than 50 characters.", "ERROR",3);
taskDesc = JOptionPane.showInputDialog(null, "Please enter a short description of the task");
return false;
}
JOptionPane.showMessageDialog(null, "Task successfully captured.");
return true;
}
You need to use the results of your method call.
boolean ready = false;
do{
ready = checkTaskDescription();
} while ( ! ready );
That will enter the do block, assign ready to the return value of checkTaskDescription(), then check if it is false. If it is false, it will continue to loop, until it is true.
Your checkTaskDescription is also broken. If you fail the first time, it will show the dialog again, then always return false.
public boolean checkTaskDescription() {
taskDesc = JOptionPane.showInputDialog(null, "Please enter a short description of the task");
if (taskDesc.length() > 50) {
JOptionPane.showMessageDialog(null, "Please enter a task description of less than 50 characters.");
return false;
}
JOptionPane.showMessageDialog(null, "Task successfully captured.");
return true;
}
I updated the method so it would "work" when there is a failed input, it will show an error message, then loop and show the dialog again. This is why you should validate the data from the dialog, and not open the dialog in the loop.
It will be much easier if you do something like this
public String getTaskDescription() {
String taskDescription = "";
do {
taskDescription = JOptionPane.showInputDialog(null, "Please enter a short description of the task");
}
while (taskDescription.length() > 50);
return taskDescription;
}
When you design your methods, try to make them as self-contained as possible. Now you return a flag and rely on a caller method to call it again in case the input isn't valid.

Stopping/Resetting a Function in Java if Validation Criteria is not met

I am using this function below to check a value entered in a textbox and if it's valid under the try catch criterias, the function should return a True via the boolean Variable. The program is set up so the final calculation only happens if all my inputs come back as being OK or true in this case.
What I need to get working properly is the return for the try, if the number is not valid the function should stop and get the user to try again, I'm thinking of something like an Exit Sub from VB. My searches have turned up to use a return like I have below, but that just causes an error since the compiler thinks I am trying to return a function result.
There is a tiny bit more to the function, but I cut it out since it is irrelevant; it's pretty much just the bGarage = true; and return bGarage;.
public boolean fnGarageLevel() {//Beginning of Garage Validation Function
int nGarage;
boolean bGarage;
try {//Garage Number Validation Try
nGarage = Integer.parseInt(tfGarage.getText());
if (nGarage != 1 || nGarage != 2 || nGarage != 3 || nGarage != 4) {
JOptionPane.showMessageDialog( null,
"Enter a valid Garage Level, 1, 2, 3 or 4",
"Error",
JOptionPane.ERROR_MESSAGE);
tfGarage.setText("");
tfGarage.grabFocus();
return;
}//End of Error Message
}//End of try
catch (NumberFormatException nfe) {//Beginning of Catch
JOptionPane.showMessageDialog(null,
"Value Entered for Garage is not a Number",
"Error",
JOptionPane.ERROR_MESSAGE);
tfGarage.setText("");
tfGarage.grabFocus();
}//End of Catch for Garage field
bGarage = true;
return bGarage;
}//End of Garage Function
When the try section finishes its running successfully (that is, without catching any exception), the control goes right to the end of catch section or (if it exists) enters the section finally. In this case, the control jumps to bGarage=true sentence when the try ends. Remove the return; statement, it's not necessary.

TextInputFile, TextOutputFile (with username, pass in a login system)

int menuoptions;
String userinput;
String usercheck="";
String username="user";
String password;
int intCounter=0;
con.println("TYPING GAME\n");
con.println("1. Sign in");
con.println("2. Create a new account");
menuoptions = con.readInt();
con.clear();
if(menuoptions==1){
while(!username.equals(usercheck) && intCounter==0){
con.println("Please type in your username.");
userinput = con.readLine();
con.clear();
TextInputFile infile = new TextInputFile("logins.txt");
while(infile.eof() == false && intCounter==0){
usercheck=infile.readLine();
infile.readLine();
if(username.equals(usercheck)){
intCounter=intCounter+1;
}
}
if(!userinput.equals(usercheck) && intCounter==0){
con.println("No such username.");
pause(2000);
con.clear();
}
else if(userinput.equals(usercheck)){
intCounter = intCounter+1;
}
}
con.println("What is your password?");
}
if(menuoptions==2){
con.println("What will be your username?");
username = con.readLine();
con.clear();
con.println("What will be your password?");
password = con.readLine();
con.clear();
TextOutputFile outfile = new TextOutputFile("logins.txt", true);
outfile.println(username);
outfile.println(password);
}
}
public static void pause (int intMS){
try{Thread.sleep(intMS);
}catch(InterruptedException y){}}
In logins.txt, i have 'voidturbulence' in one line, and in the next line, i have '80'.
when i type in 'voidturbulence', it jumps to 'no username found', when it should be asking for the password.
However, if userinput (voidturbulence) is equal to usercheck (the first line [voidturbulence]), then shouldn't it break out of the loop and ask me for the password?
A. The code
usercheck=infile.readLine();
infile.readLine();
looks suspicious to me. You probably have a blank line, a line with the user name, and some other text in the file read by infile. Thus, usercheck probably never receives the user name you target. (You skip every second line from infile.)
B. instead of
infile.eof() == false
use
!infile.eof ()
for better readability.
Otherwise,
(((infile.eof() == false) == true) == true)
would be considered more readable, right?
C. instead of
if (menuoptions == 1)
{
}
if (menuoptions == 2)
{
}
use
if (menuoptions == 1)
{
}
else if (menuoptions == 2)
{
}
since menuoptions cannot equal 2 when you just found it was equal to one (and did not change it in the first then-block).
D. What is intCounter good for?
You initialize it to 0.
You increment it if the username equals
usercheck.
The while loop loops as long as username is not equal to
usercheck and intCounter equals 0.
Thus, both condition will be fullfilled if username equals usercheck.
You could eliminate intCounter.
This is a good example for a bad variable name. "intCounter" neither guarantees that it is an int, nor that it contains a count of anything. You will find that if you try to create useful names, you'll tend to create useful code. In your example, you created a useless name, and useless code that manipulates the value behind the name, but really don't accomplish anything.
E. What are you trying to accomplish?
Except for the headline of the question, there is no specification of the requirements your code tries to cover. Better specify what you want to do, then present the code, and specify your problem. DonĀ“t just throw some general keywords at us, followed by code. Please ;)

Categories

Resources