I have this validation to check that user input is not blank and is only letters. If it's blank, it catches it, and if if includes digits it also catches it. If I input the 2 characters it asks for, however, it doesn't go through. I'm not sure how to go about this.
private static boolean isValidSt(String aSt) {
boolean result = false;
try {
if (aSt.length() == 2) {
result = true;
} else if (aSt.length() != 2) {
result = false;
}
for (int i=0; i <aSt.length();){
if (!Character.isLetter(i));{
return false;
}
}
return true;
} catch (NumberFormatException nfex) {
if (aSt == null) System.exit(0);
} catch (Exception ex) {
if (aSt == null) System.exit(0);
}
return result;
}
One problem that I can see right of the bat is this:
if (!Character.isLetter(i));{
return false;
}
That semi-colon after your if does not belong there. After checking your conditional statement, if it was true, it will execute until the semi-colon. The return false; isn't part of the if and will ALWAYS be executed.
As David Wallice rightly pointed out, you also never increment the counter in your for-loop, so were it not the case that the program always returned with false in the first iteration, it would indeed get stuck in an eternal loop. A very commonly used syntax for for-loops would be:
for(int i = 0; i < string.length(); i++) { }
A third and final note from me, this time nothin that would give an error, just good form:
You use System.exit(0); to exit the program as result of an exception. The zero you pass as an argument is usually only used when the program shuts down normally. This is a crash as a result of an error, so I'd use 1 or something.
Well, you could use StringUtils methods, isBlank and isAlpha, for validate what you need
Related
I have a boolean Guess function:
public boolean guess() {
String checkInput = scanner.nextLine();
try {
guess = Integer.parseInt(checkInput);
} catch (NumberFormatException e) {
return false;
}
return true;
}
which is called by another function in a do while loop:
while (!player.guess()) {
player.guess();
}
If I enter an int, the program runs properly and terminates. But if input is a non-int character, the program gets stuck in the while loop. I don't know what's going on here.
Your guess function is designed that way.
It returns false if the input is not numeric (catch). So it stays in the loop until you input a numeric value.
Another problem is that you are calling the function twice every loop (once on the loop condition check and another inside the loop). So if you type a non numeric character on the first (loop condition) and a numeric on the second (inside the loop) it will still ask for an input a third time.
I don't know what your intention is but you probably would want something like:
while (!player.guess()) {
continue;
}
Unless you really want it to be called twice.
Your scanner.nextLine() reads the line forever, it doesn't ask for another input.
while (!player.guess()) { // Entered Integer. (!true) and loop breaks
player.guess();
}
while (!player.guess()) { // Entered Non-Integer. (!false) and program enters the loop
player.guess(); // You are not storing the result in some boolean variable
//Therefore, it doesn't matter whether true or false
//while (!player.guess()) will be checked once again
}
SOLUTION:
boolean flag = player.guess(); // capture the result
while (!flag) { // verify the result
flag = player.guess(); // capture the result again
}
So here's a snippet of code I'm working on:
String direction = s.readLine();
System.out.println(direction);
if (direction.equals("up") != true && direction.equals("down") != true &&
direction.equals("left") != true && direction.equals("right") &&
direction.equals(null) != true) {
System.out.println("Invalid Solution file");
System.exit(0);
}
What it is supposed to do is read a line from a text file (using a BufferedReader) and then if the line isn't either a valid direction or blank then it should print "Invalid Solution" and exit.
The problem is that no matter what the direction string is the if statement still runs. I put in a println to check whether the direction was being read correctly but it seems absolutely fine. So why isn't the code working as intended?
Part of your problem is readability. Fix that and your problem is 90% solved:
private static List<String> DIRECTIONS = Arrays.asList("up", "down", "left", "right");
then
if (!DIRECTIONS.contains(direction)) {
System.out.println("Invalid Solution file");
System.exit(0);
}
The other 10% was how to check for null, which is direction == null, but if you use this code you don't need to, because contains(null) will conveniently return false.
You code is much more complex than it is needs to.
Consider this instead:
Set<String> validDirections = new HashSet<>(Arrays.asList("up", "down", ...
if (validDirections.contain(direction.toLowerCase()) {
// good ...
} else {
// bad ..
}
You can make validDirections a global constant for example; so it could be used in other places as well.
What I am trying to explain here is: your code is low-level. Low level code is hard to write, read, maintain and extend. Programming is always about creating good abstractions. Or vice versa: if you don't use abstractions, you end up with pretty abstract code, like the one you are showing here!
For example: if you need another direction, you have to put into your already way too complicated if condition. In my solution, you just put it into the statement that builds that Set.
Finally: your error message, is saying nothing. So, that string is bad; but why is it? Wouldn't it be better to at least print the string that caused the error?!
Here && direction.equals("right") I think you have done a mistake since it is on contradiction with the rest :
direction.equals("up") != true &&
direction.equals("down") != true &&
direction.equals("left") != true
You test the negation in the most of conditions but direction.equals("right") tests the affirmation.
Try it , it's the same thing but less verbose and more readable :
if (direction !=null && !direction.equals("up") &&
!direction.equals("down") &&
!direction.equals("left") &&
!direction.equals("right") ){
System.out.println("Invalid Solution file");
System.exit(0);
}
First, you should not use != true with a boolean statement, it is bad form. Rewrite like this:
direction !=null &&
!direction.equals("up") &&
!direction.equals("down") &&
!direction.equals("left") &&
!direction.equals("right")
Your error was that you did not include the != true part on one of your statements within the compound if. Replace with the above code to solve the issue.
I'm confused why you are using !=true when your .equals method already returns a boolean. Try this.
String direction = s.readLine();
System.out.println(direction);
if ( direction!=null && !direction.equals("up") && !direction.equals("down")&& !direction.equals("left")&& direction.equals("right")){
System.out.println("Invalid Solution file");
System.exit(0);
}
Try the following code:
boolean match = false;
if (direction.equals("up"))
{ match = true; }
if (direction.equals("down"))
{ match = true; }
if (direction.equals("left"))
{ match = true; }
if (direction.equals("right"))
{ match = true; }
if (direction.equals(null))
{ match = true; }
if (match == false){
System.out.println("Invalid Solution file");
System.exit(0);
}
You might also want to trim the direction string after reading from file.
The quals method returns a boolean so the result does not need to be compared with the true or false value. Also, I would start with null comparison - boolean expressions in Java are shortened so if this part will be fulfilled rest of the expression is not evaluated. The correct expression might look like this:
if (direction == null || (!direction.equals("up") && !direction.equals("down") && !direction.equals("left") && !direction.equals ("right "))) {
}
But this code is not readable. You could use enums or list of Strings like below
List<String> directions = Arrays.asList("up", "down", "left", "right");
String direction = "readValue"
if (!directions.contains(direction)) {
System.out.println("Invalid direction");
System.exit(0)
}
So I need to create a method isValidDNA which works like this:
public boolean isValidDNA()
Returns true if the DNA is valid, i.e, only contains the letters,
A,T,C,G (in uppercase) and at least one of these characters.
All I could think of was this, which apparently doesn't work:
public boolean isValidDNA(){
for (int i=0;i<dna.length();i++){
if (dna.charAt(i)=='A' || dna.charAt(i)=='T' || dna.charAt(i)=='C' || dna.charAt(i)=='G' ){
return true;
}
return false;
}
}
You can use this regular expression:- [ATCG]+ In code this could look like this:
public boolean isValidDNA(){
return dna.matches("^[ATCG]+$")
}
You make a return statement immediately, which will exit during the first iteration and only check the first character.
You need to store this information in a boolean and return it after you've checked the whole string:
public boolean isValidDNA(String dna){
Boolean result = true;
// Add an extra check for the "at least one character" thing.
for (int i=0; i<dna.length(); i++){
if (dna.charAt(i)!='A' && dna.charAt(i)!='T' && dna.charAt(i)!='C' && dna.charAt(i)!='G' ){
result = false;
}
}
return result;
}
However, you would be better off using regular expressions for these problems.
Try it this way:
public boolean isValidDNA(){
boolean res = true;
for (int i=0;i<dna.length();i++){
if ((dna.charAt(i) != 'A') && (dna.charAt(i)!='T') && (dna.charAt(i)!='C') && (dna.charAt(i)!='G') ){
res = false;
break;
}
}
return res;
}
if your startpoint is that the DNA is valid, it's much more easy to test if it's really so. You only have to test each char of your dna and can stop by the first entry that doesn't satisfy your if-statement.
Using your way, you've almost got it.
Right now, you return true if you find one that's OK, and only return false if all are wrong. You can negate your if condition, and return false as soon as you find one that's not OK, and only return true if all are fine.
I'll leave the coding part up to you.
As others pointed out, regex will be a cleaner solution here.
You can try this implementation.
First declare a constant:
private static final String bases = "ATCG";
And then use it in the method like this:
public boolean isValidDNA() {
boolean isValid = true;
for (char c : dna.toCharArray()) {
if (bases.indexOf(c) < 0) {
isValid = false;
break;
}
}
return isValid;
}
Scanner sc = new Scanner(System.in);
System.out.print("Enter a DNA sequence: ");
seq=sc.nextLine();
if(seq.matches(".*[^ATCG].*")){
System.out.println("Not a valid sequence.");
System.exit(0);
}
This regular expression works so that only sequences containg A,C,T or G with no other charcters, spaces, etc included will continue
Here is my method:
//usedLetters method to check if user's guess has already been guessed
private boolean usedLetters(char used[], char alphabet) throws IOException
{
for(int x=0; x<used.length; x++){
if(alphabet == used[x])
{
return true;
}
else
{
used[dataSize] = alphabet;
return false;
}
}
}//End of usedLetters method
IT checks to see if the alphabet that the user entered in an another method has already been guessed. If it has already been guessed, it returns true, and if has not been already guessed, it adds the alphabet into used, and returns false. But the error says that there are no return statements...I am not familiar with methods in general, so I am confused. Any help would be appreciated!
What if used.length==0? Then the for-loop is never entered.
Therefore you need a return statement after the loop.
What if the for is never entered? i.e. used.length == 0 (used is an empty array). In this case - nothing will be returned.
The compiler forbids a flow that can terminate without returning the value, and that's why it shows the error.
Also note, I believe even after fixing this issue - the program will yield a wrong result, it will only check the first element of used, without advancing to the next one.
You should move the return false; to just before the last }. Otherwise it will return in the first iteration of the loop.
/usedLetters method to check if user's guess has already been guessed
private boolean usedLetters(char used[], char alphabet) throws IOException
{
for(int x=0; x
if(alphabet == used[x])
{
return true;
}
else
{
used[dataSize] = alphabet;
return false;
}
}
}//End of usedLetters method
There should be return statement after for loop, currently there is no return statement that's why you are getting error.
As you have written your code, the method will always return on the first iteration of the cycle, while I doubt this is what you want.
I believe that you should return false outside the for. I am not sure what does to "guess an alphabet" mean but I think this is what you are trying to do.
Yep, all the above are correct. You would be better off defining the return variable at the top, setting it to values wherever you need to within the method body, breaking out of the 'for' loop and returning it once at the end.
I have a java scanner and two loops to handle user input, However it throws an NoSuchElement exception the second it hits the first loop with out asking for any input from the user.
Scanner Guess_input = new Scanner( System.in );
while (guess > 0){
failure = true;
while(failure)
{
System.out.println("Please input");
try
{
if (Guess_input.nextLine().length() == 1 && guesses.size() >= 1) {
guesses.add(Guess_input.nextLine());
System.out.println("You guessed" + guesses.get(guesses.size()) + "");
}
else if (Guess_input.nextLine().length() == 0) {
System.err.println("ERROR:");
Guess_input.nextLine(); //Clean Buffer
failure = true;
}
else
{
System.err.println("ERROR");
Guess_input.nextLine(); //Clean Buffer
failure = true;
}
}
catch(InputMismatchException ime)
{
System.err.println("error");
}
finally
{
Guess_input.close();
}
}
}
From the java documentation, when using the next() method of the Scanner class, you'll get
NoSuchElementException - if no such tokens are available
Whenever you call the nextLine() method, you are supposed to enter a String. You should first store the result of nextLine() in local variable unless that's what you want.
Another problem is that your try catch finally is done in your while loop. It means that for each iteration, your finally bloc will be executed everytime, so you'll think that there is an exception, while might be none. Apply these changes
try {
while (guess > 0) {
while (.....) {
.....
}
}
} catch (...){
....
}
finally{ .... }
The errant statement is guesses.get(guesses.size()). In Java lists use zero-based indexes, i.e. the index of the first element is always 0 and the last element is size - 1. By definition the size of a list is an invalid index.
You probably should just hold the next line in its own variable before adding it to the list so that your sysout statement can just reference the variable instead of pulling the value back out of the list. But the easy solution is to just change the code to guesses.get(guesses.size() - 1)
You're calling guesses.nextLine() way too many times. Every call to nextLine() will block the app and expect input. Furthermore, theres other issues to worry about there... like other people pointed out.
I'll stick to the scanner though.