Hey guys i have this code I am working on for a class and I can't figure out what I've screwed up. I'm sure its something simple, so if you could look at it I and help me with my mistake.
Background: This is supposed to check a word to make sure it contains a punctuation char, an Uppercase letter and a lowercase letter, and a number with in the first 8 digits.
When I step through it in netbeans the for loop will only go to the second if statement before returning to the top and iterating again. it won't enter the if statement concerning the numFlag or the upperFlag and lowerFlag
I have those if statements checking to see if the flags are true or not so that if I have already detected the corresponding char type it wont enter and continue on.
It does compile, and runs i have included the main method I'm using to test as well for convenience if you want to compile and test it
Any other suggestions are welcome as well. If I haven't provided enough info please let me know what you need.
Problematic Code:
public final class Checker {
private Checker() {}
public static boolean checkLegality(String _pass) {
boolean puncFlag = false;
boolean numFlag = false;
boolean upperFlag = false;
boolean lowerFlag = false;
char[] pass = _pass.toCharArray();
if (pass.length < 8) {
return false;
}
for (int i = 0; i < 9; i++) {
if (!puncFlag) {//enters check for puncuation only if it hasint detected any yet
int ascii = (int) pass[i];//converts to ascii
if (32 < ascii && ascii < 47) {
puncFlag = true;
}
} else if (!numFlag) {//enters check for numbers only if it hasint detected any yet
if (Character.isDigit(pass[i])) {
numFlag = true;
}
} else if (!upperFlag || !lowerFlag) {//enters check for letters only if it hasint detected both upper and lower yet
if (Character.isLetter(pass[i])) {
if (Character.isUpperCase(pass[i])) {//checks if upper case
upperFlag = true;
} else if (Character.isLowerCase(pass[i])) {
lowerFlag = true;
}
}
}
}
if (puncFlag
&& numFlag
&& upperFlag) {
return true;
} else {
return false;
}
}
}
Main Method I use to test
public class PasswordCheckermMain {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//TO DO CODE HERE
Scanner in = new Scanner(System.in);
String pass;
boolean flag = false;
while (flag == false) {
System.out.println("Enter password: ");
pass = in.next();
if(Checker.checkLegality(pass)){
flag = true;
}
System.out.println("The password meets criteria: " + flag);
}
}
}
You shouldn't do the tests in the else-if because then all the checks won't be done unless the previous was done.
E.g.
if (!puncFlag) {//enters check for puncuation only if it hasint detected any yet
...
}
if (!numFlag) {//enters check for numbers only if it hasint detected any yet
...
}
if (...)
Sidenote, you don't have to do
if (32 < ascii && ascii < 47) {
This will work
if (' ' < pass[i] && pass[i] < '/') {
numFlag only gets true when you see a digit, otherwise it stays false. When it's false, you get inside the if statement and do nothing else. So if you pass a password with only letters, you will never set numFlag to true, and never check for letters.
I think you shouldn't read the flags at all. You should read each character and check if it's a punctuation sign (set the flag) a number(set the flag) or letters (set appropriate flags).
Why do you even check if a flag is already set? Just "or together" the results. Also, if you shorten the String with substring, you can use a "foreach" loop. And you don't have to cast a char in order to compare its value with an int:
public static boolean checkLegality(String _pass) {
boolean puncFlag = false;
boolean numFlag = false;
boolean upperFlag = false;
boolean lowerFlag = false;
if (_pass.length() < 8) {
return false;
}
char[] pass = _pass.substring(0,8).toCharArray();
for(char c : pass) {
puncFlag = puncFlag || (32 < c && c < 47);
upperFlag = upperFlag || (Character.isLetter(c) && Character.isUpperCase(c));
lowerFlag = lowerFlag || (Character.isLetter(c) && Character.isLowerCase(c));
numFlag = numFlag || Character.isDigit(c);
}
return puncFlag && upperFlag && lowerFlag && numFlag;
}
From what I see, if your password is 8 characters long, it will crash because you check the first 9 characters.
Your loop should be :
for (int i = 0; i < 8; i++) {
...
because the last index of a 8 elements array is 7 (since the first index is 0).
UPDATE
As mentioned in other answers, you shouldn't use else if but separate if statements if you want to allow to have letters before punctuation or numbers and so on...
May I also suggest you to check this by using a regular expression, which should do the same job in fewer lines.
Basically i done is to change else if(if (!numFlag) for just if, add the try{ }catch(excepction e){ } for any unlike output. Also in the main class, i change the Scanner in for inn and close inn properly.
PasswordCheckermMain class
import java.util.Scanner;
public class PasswordCheckermMain {
public static void main(String[] args) {
//TO DO CODE HERE
Scanner inn = new Scanner(System.in);
String pass;
boolean flag = false;
while (flag == false) {
System.out.println("Enter password: ");
pass = inn.next();
if(Checker.checkLegality(pass)){
flag = true;
}
System.out.println("The password meets criteria: " + flag);
}
inn.close();
}
}
Checker class
public class Checker {
private Checker() {}
public static boolean checkLegality(String _pass) {
boolean puncFlag = false;
boolean numFlag = false;
boolean upperFlag = false;
boolean lowerFlag = false;
int ascii =0;
char[] pass = _pass.toCharArray();
//adding try{ }catch{} for better programing
try{
if (pass.length < 8) {
return false;
}
for (int i = 0; i < 8; i++) {
if (!puncFlag) {
//if 1 enters check for puncuation only if it hasint detected any yet
ascii = (int) pass[i];//converts to ascii
if (32 < ascii && ascii < 47) {//if2
puncFlag = true;
}//end if2
}//end if 1
//Note change else if for if
if (!numFlag) {
//enters check for numbers only if it hasint detected any yet
if (Character.isDigit(pass[i])) {
numFlag = true;
}
} else if (!upperFlag || !lowerFlag) {//enters check for letters only if it hasint detected both upper and lower yet
if (Character.isLetter(pass[i])) {
if (Character.isUpperCase(pass[i])) {//checks if upper case
upperFlag = true;
} else if (Character.isLowerCase(pass[i])) {
lowerFlag = true;
}
}
}
}//end for
if (puncFlag && numFlag && upperFlag && lowerFlag ) {
return true;
} else {
return false;
}
}catch(Exception e){ return false; }
}//end checklega
OUTPUT :
Enter password:
12#Abxyz
The password meets criteria: false
Enter password:
12.Abxyz
The password meets criteria: true
Related
is this the most efficient method to determine that there is a minimum of two unique characters in a String? Should I have used arrays to hold the characters? Thank you
public static Boolean checkPW(String pw) {
Boolean validLower = false, validUpper = false, validNumber = false;
char lowerCompare = '0', upperCompare = '0', numberCompare = 'a';
for(int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if(character >= 'a' && character <= 'z') {
if(lowerCompare == '0')
lowerCompare = character;
else if(lowerCompare != character)
validLower = true;
} // lower-case if END
} // for-loop END
if(validLower)
return true;
else
return false;
} // checkPW END
If I had to do this in Java, in production, I might just use a set here:
String input = "abcdefgzz";
char[] letters = input.toCharArray();
Set<Character> set = new HashSet<>();
boolean valid = false;
for (char letter : letters) {
set.add(letter);
if (set.size() > 1) {
valid = true;
break;
}
}
if (valid) {
System.out.println("Minimum of two unique letters");
}
else {
System.out.println("Only one unique letter");
}
is this the most efficient method to determine that there is a minimum of two unique characters in a String?
No. The loop continues to run after 2 unique valid characters are found, which is unnecessary. It could stop immediately, and then it will be more efficient. Consider for example the string "ab" followed by a million characters. There's no need to go further than the first two.
Should I have used arrays to hold the characters?
The question is not clear. To make it meaningful, you would need to include reasoning for the benefits of both methods. And it's not clear what technique you're referring to.
It would be good to remove all the unnecessary variables from the program.
After fixing the inefficiency, and a bit of cleanup:
public static boolean checkPW(String pw) {
char first = '0';
for (int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if ('a' <= character && character <= 'z') {
if (first == '0') {
first = character;
} else if (first != character)
return true;
}
}
}
return false;
}
I'd do this:
public static boolean checkPW(String pw) {
Character lowerCompare = null;
for (int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if(Character.isLowerCase(c)) { // this handles non-ASCII lower case characters
if(lowerCompare == null) {
lowerCompare = character;
} else if(lowerCompare != character) {
return true;
}
}
}
return false;
}
I have an assignment that requires me to create a password checking program.
The password must be at least 8 characters, contain both capital and lower case letters, a digit and a special character.
I believe I am close to solving this problem but my skills are still developing and I've hit a wall.
package project1;
/**
*
* #author danechristian
*/
import java.util.*;
public class Project1
{
static Scanner console = new Scanner(System.in);
static final String SPECIAL_CHARACTERS = "!,#,$,%,^,&,*,|";
static String password;
public static void main(String[] args)
{
System.out.println("Create a password: ");
password = console.next();
if (validPassword(password))
{
System.out.println("Password Saved");
}
else
{
System.out.println("Invalid Passowrd. Password "
+ "must contain atleast 1 capital letter"
+ "1 lower case letter, 1 digit, 1"
+ "special character (!#$%^&*|) and "
+ "be atleast 8 characters long");
}
}
public static boolean validPassword(String password)
{
boolean upCase = false;
boolean loCase = false;
boolean isDigit = false;
boolean spChar = false;
if (password.length() >= 8)
{
for (int i = 0; i < password.length() - 1; i++)
{
if (Character.isUpperCase(password.charAt(i)))
{
upCase = true;
}
if (Character.isLowerCase(password.charAt(i)))
{
loCase = true;
}
if (Character.isDigit(password.charAt(i)))
{
isDigit = true;
}
if (SPECIAL_CHARACTERS.contains(password))
{
spChar = true;
}
}
}
return (upCase && loCase && isDigit && spChar);
}
}
In order to check have something like this:
public static boolean validPassword(String password){
boolean upCase = false;
boolean loCase = false;
boolean isDigit = false;
boolean spChar = false;
if (password.length()>7){
if (password.matches(".+[A-Z].+")){
upCase = true;
}
if (password.matches(".+[a-z].+")){
loCase = true;
}
if (password.matches(".+[1-9].+")){
isDigit = true;
}
if (SPECIAL_CHARACTERS.contains(password)){
spChar = true;
}
}
return (upCase && loCase && isDigit && spChar);
}
solved by changing
if (SPECIAL_CHARACTERS.contains(password)){
spChar = true;
to
if (SPECIAL_CHARACTERS.contains(password.substring(i,i+1))){
spChar = true;
this checks for the string within the string.
also, I removed the "- 1" from my for statement so that the bounds were corrects. also removed the commas from the SPECIAL_CHARACTERS constant.
the program now runs without issue, thanks for the advice everyone.
Hey all I am working on a program in Java that checks a password for a few things such as is it 8 characters, is one character Uppercase, is one lowercase, and is there a number in the password. So far I have wrote the methods for checking length, upper and lower case, with no problems. I cannot for the life of my understand why it isn't working with the isDigit().
No matter what input I throw in the method, it always returns true. Anyone see my error?
Thanks in advance!
public void setOneDigit(){
int i;
char ch;
boolean hasNumber = false;
for ( i = 0; i < password.length(); i++ ) {
ch = password.charAt(i);
if (Character.isDigit(ch));
{
hasNumber = true;
}
}
if(hasNumber == true)
{
hasOneDigit = true;
}
else
{
hasOneDigit = false;
}
}
Classic mistake:
if (Character.isDigit(ch));
{
hasNumber = true;
}
has to be
if (Character.isDigit(ch))
{
hasNumber = true;
}
public static boolean isValidNumber(String a1)
{
String x = ("0123456789");
boolean valid = false;
for (int i = 0; i < 4; i++) {
char c = a1.charAt(i);
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
valid = true;
}
else {
valid = false;
}
}
}
return valid;
}
The above method checks to see whether an input of a four character string is composed of the characters 0123456789. However, regardless of what the input is, the method always returns as false.
If I were to change the valid value in the else statement to true, the method would always return as true.
What is the error that I have made in this method?
As soon as you find a non matching character, break the loop otherwise the next matching character will set valid to true.
e.g. "123a456" is considered valid.
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
valid = true;
}
else {
valid = false;
break;
}
}
If for some reason you don't want to break the loop, you could keep an "invalid counter" and make sure that is 0 at the end.
Of course for what you are doing here, Integer.parseInt() might be your best bet ;-)
a String.equals method will check these two strings in a single statement if you are permitted to use that.
public static boolean isValidNumber(String a1)
{
String x = ("0123456789");
return x.equals(a1);
}
I would rewrite your function as given below,
String x = ("0123456789");
boolean valid = false;
for (int i = 0; i < 4; i++) {
char c = a1.charAt(i);
boolean isCharOK = false;
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
isCharOK = true;
break;
}
}
if (!isCharOK) {
valid = false;
break;
}
}
return valid;
John3136 is quite correct, but I would like to propose even better solution to your whole task:
final static String x = "0123456789";
public static boolean isValidNumber(String a1) {
for (int i = 0; i < a1.length(); ++i) {
if (x.indexOf(a1.charAt(i)) == -1) return false;
}
return true;
}
In short: the above code "looks up" every character in your parameter string a1 in the string composed of digits. If it can find it, continues. If it can't, it means a1 consist not only digits and returns false. If it passes through all a1 characters then it returns true :)
And as asked and described in the comments - handling of duplicate characters in argument string:
final static String x = "0123456789";
public static boolean isValidNumber(String a1) {
for (int i = 0; i < a1.length(); ++i) {
final char currentChar = a1.charAt(i);
if (x.indexOf(currentChar) == -1 || a1.indexOf(currentChar, i+1) != -1)
return false;
}
return true;
}
The function call a1.indexOf(currentChar, i+1) essentially checks if there is any duplicate character in the rest of the string (from position i+1 and farther). Which means if it will be able to find duplicate char, the method return false :) Hope this helps, here is more info on String.indexOf(int, int) function if you want:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int, int)
You can use this one liner function to check for validity of a String as Number using Regular Expression
public static boolean isValidNumber(String a1)
{
return a1.matches("[\\d]+");
}
Hope this helps.
So I need to write a method which allows me to find the next number without using anything but String and StringBuffer classes (so no parse or whatsoever).
when I run my code everything seems to work fine except for the last input (String k). It causes an outofbounds error in the while loop. But I don't see how It could do that because since my boolean should be false (I think because it only consists out of nine's) it shouldn't enter te loop in the first place.
public class Palindroom {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="347"
+ ""; System.out.println("s "+increment(s));
String p="199919";System.out.println(" p "+increment(p));
String d="199999";System.out.println( " d "+increment(d));
String k ="999999";System.out.println(" k "+increment(k));
}
static String increment (String s) {
StringBuffer sb = new StringBuffer (s);
char laatst = sb.charAt(sb.length()-1);
int laatste = sb.length()-1;
if(laatst == '9') {
int a = 1;
boolean nine = false;
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) != 9 ) {
nine = true;
} else nine = false;
}
if (nine == true) {
while (sb.charAt(sb.length()- a) == '9'){
sb.setCharAt(sb.length()- a, '0' );
a++;
}
sb.setCharAt(sb.length()-a, ((char)((sb.charAt(sb.length()-a)+1))));
} else if( nine == false) {
System.out.println("negen "+nine);
sb.insert(0, '1');
for (int i = 0; i < sb.length(); i++) {
if(sb.charAt(i)=='9') {
sb.setCharAt(i, '0');
}
}
}
} else {
sb.setCharAt(laatste,(char) (laatst+1) );
}
return sb.toString();
}
}
EDIT: based on the comments :) . Correct your logic for true and false.
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) == '9' ) {
nine = true;
}
else
{
nine = false;
break;
}
}
also you are getting an out of bounds exception because
while (sb.charAt(sb.length()- a) == '9'){
sb.setCharAt(sb.length()- a, '0' );
a++;
}
after the fifth iteration sb.length()- a will be negative when the control comes to check the condition.
you are not getting the same error in other cases because the control never goes to the while loop (as nine == false)
OLD OBSERVATION
in
if(laatst == '9') {
int a = 1;
boolean nine = false;
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) != 9 ) {
nine = true;
} else nine = false;
}
you are doing
if (sb.charAt(i) != 9 ) {
nine = true;
} else nine = false;
instead do, if you want to compare against the character 9,
if (sb.charAt(i) != '9' ) {
nine = true;
} else nine = false;
otherwise you are just comparing the ASCII value of the charAt(i) and so your boolean will only be false, if charAt(i) has ascii value 9
The problem is that when your string consists only of 9s, your while loop causes a to exceed sb.length(). Then, you end up trying to access the character at place -1 of sb.