1

Possible Duplicate:
JAVA: check a string if there is a special character in it

I'm trying to create a method to check if a password starts or ends with a special character. There were a few other checks that I have managed to code, but this seems a bit more complicated.

I think I need to use regex to do this efficiently. I have already created a method that checks if there are any special characters, but I can't figure out how modify it.

Pattern p = Pattern.compile("\\p{Punct}");
Matcher m = p.matcher(password);
boolean a = m.find();
if (!a)
  System.out.println("Password must contain at least one special character!");

According to the book I'm reading I need to use ^ and $ in the pattern to check if it starts or ends with a special character. Can I just add both statements to the existing pattern or how should I start solving this?

EDIT:

Alright, I think I got the non-regex method working:

for (int i = 0; i < password.length(); i++) {
  if (SPECIAL_CHARACTERS.indexOf(password.charAt(i)) > 0)
  specialCharSum++;
}
Community
  • 1
  • 1
dichrit
  • 11
  • 1
  • 4

3 Answers3

5

Can't you just use charAt to get the character and indexOf to check for whether or not the character is special?

final String SPECIAL_CHARACTERS = "?#"; // And others

if (SPECIAL_CHARACTERS.indexOf(password.charAt(0)) >= 0
        || SPECIAL_CHARACTERS.indexOf(password.charAt(password.length() - 1)) >= 0) {
    System.out.println("password begins or ends with a special character");
}

I haven't profiled (profiling is the golden rule for performance), but I would expect iterating through a compile-time constant string to be faster than building and executing a finite-state automaton for a regular expression. Furthermore, Java's regular expressions are more complex than FSAs, so I would expect that Java regular expressions are implemented differently and are thus slower than FSAs.

Adam Mihalcin
  • 14,242
  • 4
  • 36
  • 52
  • 2
    That's pretty much exactly what I have typed in an edit box right now, but you were quicker. I share your thoughts about (ab)using regex for trivially simple cases like this. – Barend Mar 04 '12 at 18:37
  • You certainly can. It just depends whether you happen to like the succinctness of regular expressions, or prefer some more verbose code in exchange for more explicitness if you're not familiar with regular expressions. If you know what you're doing, regular expressions have the potential to compress various checks into a single succinct line of code. So it's really a matter of preference-- which code is more readily readable and understandable for you? – Neil Coffey Mar 04 '12 at 18:39
  • @NeilCoffey A check like this should be packaged into a method, regardless of whether you are using regular expressions or not. In other code, then, the check is equally verbose because it's a single method call either way. Inside the method, the meaning is clear either way. – Adam Mihalcin Mar 04 '12 at 18:43
  • Yes -- I suppose I was maybe thinking more of the person maintaining the method in question. I don't disagree with your solution-- I think it's just a matter of preference, that's all. – Neil Coffey Mar 04 '12 at 18:46
  • Never use `charAt`. It’s broken. You need `codePointAt`. – tchrist Mar 04 '12 at 18:49
  • I think I'll go with this approach, couldn't quite get regex work... But how can I check if there is at least one special character in the password? I tried to create a for loop that checks every character on the password string and adds +1 to an integer. Then check if the integer is greater than 0 at the end to see if there were any. I edited the code in the first post. – dichrit Mar 04 '12 at 19:49
  • @dichrit The version you posted in your answer would not work, because you need to check for `SPECIAL_CHARACTERS.indexOf(password.charAt(i)) >= 0` rather than `> 0`. Also you don't really need to count the special characters, just know if one is in the string. So, you can simply cut out of the loop (e.g. by returning `true` from the `containsSpecialCharacter` method that this should be contained in) as soon as you find a special character. – Adam Mihalcin Mar 05 '12 at 03:06
4

The simplest approach would be an or with grouping.

Pattern p = Pattern.compile("(^\\p{Punct})|(\\p{Punct}$)");
Matcher m = p.matcher(password);
boolean a = m.find();
if (!a)
  System.out.println("Password must contain at least one special character at the beginning or end!");
David Souther
  • 8,125
  • 2
  • 36
  • 53
  • Though I'd maybe be tempted to make this less long-winded by writing if (!passowrd.matches(...)) [with appropriate modification to the regex, of course]. – Neil Coffey Mar 04 '12 at 18:43
  • Sure- I went with the minimum modification to dichrit's code. I had also considered something along the lines of Adam Mihalcin's charAt approach, but again, the poster seems to understand this code, so why change it? – David Souther Mar 04 '12 at 20:49
3

Use this pattern:

"^\\p{Punct}|\\p{Punct}$"
  • ^\\p{Punct} = "start of string, followed by a punctuation character
  • | = "or"
  • \\p{Punct}$ = "punctuation character, followed by end of string"
Amber
  • 507,862
  • 82
  • 626
  • 550