Question

I have to tokenize a string which looks like this:
4830673048;Tony White
There must be two tokens separated by a ;
The first token must contain 10 digits, and ONLY digits
The second token may not contain digits.

  private static boolean isValid(String accountLine) throws BankAccountException
  {
     StringTokenizer strTok = new StringTokenizer(accountLine, ";");
     boolean valid = true;
     if(strTok.countTokens() == 2)
     {
        if(strTok.nextToken().length() == 10 && strTok.nextToken().matches(".*[0-9].*"))
        {
           if(!strTok.nextToken().matches(".*[0-9].*"))
           {
              valid = true;
           }
        }
     }
     else
     {
        System.out.println("Invalid Bank Account info. " + strTok.nextToken());
        valid = false;
     }
     return valid;
  }

Here is the code I came up with, but it doesn't do what I expected it to do. I know the problem probably lies in my use of .nextToken(). So then my question is, what's the proper StringTokenizer method for ONLY checking the first or the second token?

Was it helpful?

Solution 2

See if this works for you:

private static boolean isValid(String accountLine) throws BankAccountException
{
   StringTokenizer strTok = new StringTokenizer(accountLine, ";");
   boolean valid = true;
   if(strTok.countTokens() == 2)
   {
      String acctNum = strTok.nextToken();
      String acctHolder = strTok.nextToken();
      if(acctNum.length() == 10 
        && acctNum.matches(".*[0-9].*") 
        && !acctHolder.matches(".*[0-9].*"))
      {

        valid = true;

      }
   }
   else
   {
      System.out.println("Invalid Bank Account info. " + strTok.nextToken());
      valid = false;
   }
   return valid;
}

In the code you posted, you were calling nextToken two times while evaluating the first token, inadvertently moving on to the second token too soon. By assigning the values to variables first, you can easily eliminate this issue.

OTHER TIPS

Just use String.matches() with the appropriate regex and you only need one line:

return accountLine.matches("\\d{10};[^\\d]+");

Unless this is used in more than place, I would just scrap the method and use the snippet in-line.

if(strTok.nextToken().length() == 10 && strTok.nextToken().matches(".*[0-9].*"))
{
    if(!strTok.nextToken().matches(".*[0-9].*"))
    {
        valid = true;
    }
 }

Now let's look at this code. You first say strTok.nextToken().matches(".*[0-9].*") and than say !strTok.nextToken().matches(".*[0-9].*"). Just delete the inner if and try. You don't need a regex match for second token, so no action is needed for that.

I did some research and found this solid example from Mkyong whose tutorials I admire. In the tutorial he wrote:

while (st.hasMoreElements()) {
    System.out.println(st.nextElement());
}

Instead of directly using nextToken().

This tutorial of Oracle gives more decent and all-around explanation. In that, nextToken() is deeply explained and exampled.

As you'll see in both examples, nextToken() and nextElement() functions both take the next token from the tokenizer. So you'll need to assign the first call of one of these functions to a variable and do controls on that. Such as:

String firstToken = st.nextToken().toString();
if(firstToken .length() == 10 && firstToken .matches(".*[0-9].*")) {
    ...
}

Don't forget to use toString() after nextToken().

Try this:

private static boolean isValid(String accountLine) throws BankAccountException
  {
     StringTokenizer strTok = new StringTokenizer(accountLine, ";");
     boolean valid = true;
     String bankAccount = (String)strTok.nextElement();
     if(strTok.countTokens() == 2)
     {
        if(strTok.nextToken().length() == 10 && bankAccount.matches(".*[0-9].*"))
        {
            valid = true;
        }
     }
     else
     {
        System.out.println("Invalid Bank Account info. " + bankAccount);
        valid = false;
     }
     return valid;
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top