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?
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.
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.
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;
}
Related
I need to validate user input string to make sure it contains a comma. If it does not contain a comma it must print "Error" and allow for the user to re-enter input. I'm just not sure which loop to use. If else may work, but I need it to loop back to the scanner for the user input. Or a while loop that uses .contains? Thanks.
If you want to use a loop, I recommend the for-each loop:
boolean found = false;
while (found == false) {
String input = "this is a sentence, with a comma"; // read input here
for (char ch: input.toCharArray()) {
if (ch == ',') {
found = true;
}
}
if (found == false) {
System.out.println("Error");
}
}
there will probably be functions built-in in Java for this, like "string.contains(character)" returning a boolean value
input.contains(",")
I couldn't figure out how to solve this problem using a single isValidPassword method so I broke it down into 3 and got it to work. Can someone explain to me how I could use the code I wrote and if possibly condense it?
Create a program Password that prompts for a password from the user and determines if the password is valid or invalid. There should be a static method isValidPassword that validates the password (String) and returns either true or false. A user has ONLY three tries to enter a valid password.
A valid password follows these three rules:
- Must have at least eight characters.
- Must contain ONLY letters and digits.
- Must contain at least two digits.
Use dialog boxes for the program. You must use the String and Character classes for this program. You may NOT use regular expressions. The program only needs to run once.
import javax.swing.JOptionPane;
public class Password {
public static void main(String[] args) {
int retryCount = 0;
while (retryCount < 3) {
retryCount++;
String password = JOptionPane.showInputDialog("Please Enter the Password");
if (CheckPassword(password)) {
JOptionPane.showMessageDialog(null, "Congrats! Correct Password!");
break;
}
else {
JOptionPane.showMessageDialog(null, "Sorry, Invalid Password, you tried " + retryCount + " times");
continue;
}
}
}
public static boolean CheckPassword(String password) {
if (password.length() >= 8 & CheckAlphanumeric(password) && Check2digits(password)) {
return true;
}
else {
return false;
}
}
public static boolean CheckAlphanumeric(String string) {
for (int i = 0; i < string.length(); i++) {
char x = string.charAt(i);
if (x < 0x30 || (x >= 0x3a && x <= 0x40) || (x > 0x5a && x <= 0x60) || x > 0x7a) {
return false;
}
}
return true;
}
public static boolean Check2digits(String string) {
int count = 0;
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (Character.isDigit(c)) {
count++;
}
if (count > 2) {
return true;
}
}
return false;
}
}
Lets give a quick code review:
Read about java naming conventions. Method names go camelCase; and things that return boolean should be named like isPasswordValid() for example
What your are doing here is actually a good approach: one should prefer many small methods (that carry good meaningful names!) over having a few large methods (the thing behind is called the "Single Layer of Abstraction" Principle)
You could read about regular expressions in order to do most of that checking; especially checking for "ascii chars only" is a good candidate there! So even when your assignment says "dont use them"; you might want to learn how to use them. Just for your own learning progress! But as Kayaman pointed out, the Character class has many static helper methods for such checks; so there is no need to implement all of that manually.
Your code is "logically inconsistent". Your code is validating if some string adheres to certain password rules (minimum length, minimum number of digits). But your messages are implying that this code is checking if a provided password is correct; like in: user enters his password, and then code checks if that password is known and matching a previously stored password. In that sense: make sure messages and code content are consistent!
Beyond that; a suggestion how to enhance your design for "real world" usage. Thing is: there can be many many different rules that make a password valid. Which might change over time. And typically, you would want to tell your user which of that rules his input is conflicting with. One option to address these concerns:
public interface PasswordValidator {
public void checkPassword(String password) throws InvalidPasswordException;
}
Then you create various implementations, such as
public class MinimumLengthValidator implements PasswordValidator {
#Override
public void checkPassword(String password) throws InvalidPasswordException {
if (password.lenght() < 8) {
throw new InvalidPasswordException("Given password is not long enough; expecting at least 8 characters");
}
}
And then, you create instances of those different validator classes; and store them in some array. You iterate the array, and call each validation on its own; and when it fails, you directly receive an exception with a nice message for the user.
As said: the above is meant as inspiration only (and just typed down, so beware of typos).
Look at below code which may fulfill your all requirements-
This is pure java class. you can check logic from the below code.
program edit1 - To specify why password is incorrect.
public class Demo {
private final int passwordAttempts = 3;
private int countAttempts = 0;
private String password;
private int digitCounter = 0;
public Demo() {
init();
}
public static void main(String[] args) {
new Demo();
}
private String checkPassword(String pass) {
if (pass.length() >= 8) {
if (StringUtils.isAlphanumeric(pass)) {
char[] toCharArray = pass.toCharArray();
for (int i = 0; i < toCharArray.length; i++) {
char check = toCharArray[i];
if(Character.isDigit(check)){
digitCounter++;
}
}
if (digitCounter >= 1) {
return "success";
}else{
return "digit";
}
}else{
return "alphanumeric";
}
}else{
return "length";
}
}
private void init() {
while (countAttempts < passwordAttempts) {
password = JOptionPane.showInputDialog("Please Enter the Password");
digitCounter = 0;
String passwordResult = checkPassword(password);
if (passwordResult.equals("success")) {
JOptionPane.showInputDialog("yes you entered correct password...");
} else if(passwordResult.equals("length")){
JOptionPane.showInputDialog("password must contain atleast 8 characters...");
}else if(passwordResult.equals("alphanumeric")){
JOptionPane.showInputDialog("only alphanumeric password accept...");
}else if(passwordResult.equals("digit")){
JOptionPane.showInputDialog("password must contain atleast two digits...");
}
countAttempts++;
}
}
}
Now only you need to replace JOptionPane.showInputDialog() method with some other method which only specify message because showInputDialog() method prompts input text field also to enter value and we don't want this. I don't have idea any idea about swing.
Based on your comment -
This method returning string values like success,length,alphanumeric,digit ect. and below we are comparing this values with all above in if else if. whenever it get equal that means we have to show length message ,alphanumeric string message ,digit message accordingly.
Dependency -
I'm using maven. following dependency need to add into pom.xml file.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
If you are not aware about maven then simply download jar file from here and provide in lib folder of your project.
... if instead of a number I get a letter, or a symbol, or 2 decimals.
I am making a change maker program in java.
Everything works good, the only thing i am confused about is checking the string to see if is invalid for my use,
I did this for when is left empty;
if (s1.isEmpty()) {
JOptionPane.showMessageDialog(null, "Invalid input! ");
System.exit(0);
}
That works perfect, now how can I do the else to check for letters or dots or symbols, anything that is not a number?
You could use regular expressions.
Here's some sample code to check for digits only (\\d) in your input string.
The code that actually checks is pattern.matcher(in).matches() and it tries to match the regular expression defined by regex
Let me know if you need more explanations
public class HelloWorld{
public static void main(String[] args) {
String regex = "\\d+";
String inputNumber = "2";
String inputDecimal = "2.0";
String inputString = "two";
String[] inputs = {inputDecimal, inputNumber, inputString };
Pattern pattern = Pattern.compile(regex);
for(String in: inputs){
System.out.print( in + " ");
System.out.print( pattern.matcher(in).matches()? "":"does not");
System.out.print( " contain integer numbers" );
System.out.println("---");
}
}
}
If you need to perform all the processing only when the String is integer why not check for integer value in the if clause and let the else clause be common for all the letter, dots, symbols and also empty.
if(s1.isNum){
//all processing here
}
else{
JOptionPane.showMessageDialog(null,"Invalid Input");
System.out.exit(0);
}
Otherwise you could also use try and catch block.
try{
int num= Integer.parseInt(s1);
//rest of the processing
}
catch(Exception e){
JOptionPane.showMessageDialog(null,"Invalid Input");
System.out.exit(0);
}
Use either according to your requirement
You could use a regular expression1 and String.matches(String) which Tells whether or not this string matches the given regular expression. \\d+ should match one or more digits. Something like
System.out.println("12".matches("\\d+"));
Prints
true
1Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems. --jwz
To test whether it is an integer, parse it to an int like this:
Integer.parseInt(s1)
You might also want to make use of the value returned but I don't show it here. Now you can apply try catch blocks around the method call and catch NumberFormatException like this:
try {
Integer.parseInt(s1);
//The code here will run if s1 is an integer.
} catch (NumberFormatException e) {
//this will be executed when s1 is not an integer
}
You can also extract a method from the above code. A method that returns true when the exception is not thrown. However, a disadvantage of try catch is that throwing an exception needs time and thus, it slows down your program.
To test whether the string is a letter, you loop through all the chars in the string and use one of the methods of the Character class.
boolean isLetter = true;
for (int i = 0 ; i < s1.length() ; i++) {
if (!Character.isLetter(s1.charAt(i))) {
isLetter = false;
break;
}
}
If isLetter is true, it is a letter. Again, you can also extract this as a method.
To check whether it is a symbol, use one of the methods of the Character class (again).
boolean isSymb = true;
for (int i = 0 ; i < s1.length() ; i++) {
if (!Character.isJavaIdentifierStart(s1.charAt(i))) {
isSymb = false;
break;
}
}
To check for dots in a string, just use
s1.contains(".")
Isn't that simple?
Ok, I solved the problem the following way... I took a little bit of every idea lol...
if (s1 == null) {
JOptionPane.showMessageDialog(null, "You must enter a valid integer");
System.exit(0);
}
if (s1.isEmpty()) {
JOptionPane.showMessageDialog(null, "You must enter a valid integer");
System.exit(0);
}
for (int i = 0; i < s1.length(); i = i + 1) {
if (!Character.isDigit(s1.charAt(i))) {
JOptionPane.showMessageDialog(null, "You must enter an integer value");
System.exit(0);
}
}
I have created an ArrayList of users. I have made a method to add new users. The users must have an email and the program has to check the ArrayList to see if the user already exists in the ArrayList. If I run the check for a correct email and correct name separately, it works, but when I combine it using this while(userExists || matchFound), it doesn't work. I have tried everything, so hope you can help me. Thanks in advance.
public void addUser()
{
System.out.println("-----------------------------"); //separation of previous screen
System.out.println("Create a new user.");
boolean userExists = false;
boolean matchFound = false;
String userToAdd;
do {
System.out.println("Username: ");
userToAdd = input.next();
Pattern p = Pattern.compile(".+#.+\\.[a-z]+");
Matcher m = p.matcher(userToAdd);
matchFound = m.matches();
if (matchFound) {
System.out.println("just a check if it is a email");
}
if(!matchFound) {
System.out.println("no email. Try again.");
matchFound = true;
}
for(User currentUser : db.getUsers()) {
if (currentUser.getName().equals(userToAdd)) {
System.out.println("User already exist. Try again.");
userExists = true;
}
}
} while(userExists || matchFound);
}
You want to stay in the loop as long as the user is not a valid email or it already exists. Therefore you need :
while(userExists || !matchFound);
and you probably shouldn't set matchFound to true when it's false :
if(!matchFound){
System.out.println("no email. Try again.");
matchFound = true; // remove this line
}
It should only be set by matchFound = m.matches();
I think your code would work better if you got the naming right. "matchFound" is not really telling and I guess that is where much of the confusion comes from. This is why I suggest you use "isEmail" instead. This makes the code much more readable. Another problem is that you're using variables inside the loop that you initialize only once outside of the loop. This works well for the first iteratation of the loop but leads to uncertain behaviour the second time. For example if you're entering an email that is already in the system, userExists would be set to true and stay true for consecutive iterations of the loop.
I also removed the output for the case where the email is valid. The user experience is better if you just present errors in the case where they occur. You're surely going to present the user with further functionality after they have entered a valid username. This will be enough feedback so that the user understands that the operation was successful.
This should work:
public void addUser()
{
System.out.println("-----------------------------"); //separation of previous screen
System.out.println("Create a new user.");
boolean userExists = false;
boolean isEmail = false;
do
{
userExists = false;
isEmail = false;
System.out.print("Username: ");
String userToAdd = input.next();
Pattern p = Pattern.compile(".+#.+\\.[a-z]+");
Matcher m = p.matcher(userToAdd);
isEmail = m.matches();
if (!isEmail)
{
System.out.println("Not an email. Try again.");
}
for(User currentUser : db.getUsers())
{
if (currentUser.getName().equals(userToAdd))
{
System.out.println("User already exist. Try again.");
userExists = true;
break;
}
}
}while(userExists || !isEmail);
}
I think you need to stay unless and until the user name does not exist and has valid email id. You should do the following:
while(!userExists || !matchFound);
With this you will loop until and unless you have both valid data.
you should not set matchfound to false when it is false. other wise in the next loop it will be true by default. and you did not change it to false in your first block.
then you should use !matchfound instead match found. so that when you didn't found a match you will loop again
You might want to reintialize the booleans to false as the first statements inside the do loop. Otherwise, if userExists is assigned true for an iteration, it will stay true for all the successive iterations.
do
{
userExists = false;
matchFound = false;
System.out.println("Username: ");
userToAdd = input.next();
}
Hey guys so heres my question. I've got a class that manipulates a stack of Fractions and it is an RPN Evaluator. I'm newer to Java and only know basic data structures. This is a project for a class but I'm kinda bummed. I need to print out the expression that I used OR print out the expression until the RPN expression isn't valid denoted by valid = false/true I have a specific way I have to print it out and ill give an example but I cannot figure out how to do it... I have a queue available to me to use but I must use both a stack and a queue. I realize the code is yuck but its because I haven't begun my cleanup of that class yet. Here is an example of the output I need if the inputs are as follows.... Note that the input is in quotes minus the quotes
Input************************************Output
"(2/5)(1/2) * * #" *********** Expression 3 is: (2/5)(1/2)**
"(3/1)T ^ (3/2) #" *********** Expression 4 is: (3/1)T
Here is my class(I know it's sloppy...and the rules are very restrictive on what I can and can't use. No linked lists etc....)
import java.util.Scanner;
public class RpnEvaluator
{
private final int MAX_TOKEN = 20;
private Scanner stdin;
private int count = 0;
public void run() throws java.io.IOException
{
runOnce();
}
public boolean isOperator(String input)
{
String[] oprtr = {"+", "-", "*"};
for(String choice: oprtr)
if(choice.equals(input))
return true;
return false;
}
public boolean isOperation(String input)
{
if(input.startsWith("(", 0))
return true;
return false;
}
public Fraction runOperation(String choice, Fraction op2, Fraction op1)
{
Fraction newFract = new Fraction();
if(choice.equals("*"))
newFract = new Fraction(op1.times(op2));
else if(choice.equals("+"))
newFract = new Fraction(op1.plus(op2));
else if(choice.equals("-"))
newFract = new Fraction(op1.minus(op2));
return newFract;
}
public void runOnce()
{
String readIn = "";
boolean valid = true;
Fraction op1 = null, op2 = null, answer = null, myFract;
Queue myQueue = new Queue(MAX_TOKEN);
Stack myStack= new Stack(MAX_TOKEN);
stdin = new Scanner(System.in);
while(stdin.hasNext() && valid == true)
{
readIn = stdin.next();
if(readIn.equals("#"))
{
break;
}
else if(!isOperator(readIn) && isOperation(readIn))
{
myFract = new Fraction(readIn);
myStack.push(myFract);
}
else if(isOperator(readIn))
{
if(myStack.isEmpty())
valid = false;
else
op2 = (Fraction)myStack.pop();
if(myStack.isEmpty())
valid = false;
else
op1 = (Fraction)myStack.pop();
myStack.push(runOperation(readIn, op2, op1));
}
else
valid = false;
}
if(myStack.isEmpty())
valid = false;
else
answer = (Fraction)myStack.pop();
if(!myStack.isEmpty())
valid = false;
if(valid == false)
{
System.out.print("Expression " + ++count + ": ");
System.out.println("Invalid Expression");
}
else
{
System.out.println("Expression " + ++count + ": ");
System.out.println("The value is: " + answer.toString());
}
clear(myStack, myQueue);
}
public void clear(Stack myStack, Queue myQueue)
{
myStack.clear();
myQueue.clear();
}
}
I've got a class that manipulates a stack of Fractions and it is an RPN Evaluator.
No it isn't. It's an attempt, but it doesn't handle parentheses at all, or operator precedence. You need to look up the Dijsktra shunting-yard algorithm. If this is an assignment I have no doubt that this algorithm was mentioned in class, probably at great length.
I realize the code is yuck but its because I haven't begun my cleanup of that class yet.
The best way to cleanup a class is not to fill it with dirt in the first place. Writing code that has to be subsequently removed is a double waste of time.
Ok it is very unclear what you are asking and your code doesn't make too much sense and the fraction variable fraction is unknown.
and just a note here always clean up your code as write it since later you will never know where it is and will always be confusing.
try http://www.planet-source-code.com/vb/scripts/search.asp?lngWId=2.
for some examples, they always have what i need.
and if you are new to java and want to know more i would suggest the book Java Programming: From Problem Analysis to Program Design, it explains everything from main method to GUI design.
and in future please explain your problem in more detail, we have no idea what you are asking.
Thanks.