Why is there a "deadbranch" in my code? - java

below my code was working fine until my last if-else. It appears I've done something wrong with my boolean variables canGraduate and onProbation. Perhaps I'm reassigning them incorrectly in the prior if-else statements. The deadbranch occurs at the else half of my last if-else.
package lab5;
import java.util.Scanner;
public class Lab5 {
public static void main(String[] args) {
//creates scanner object
Scanner scanner = new Scanner(System.in);
//PART II
//creating variables
double gpa;
int totalCreditsTaken;
int mathScienceCredits;
int liberalArtsCredits;
int electiveCredits;
boolean canGraduate = true;
boolean onProbation = false;
//prompts user for imput
System.out.println("What is your GPA?");
gpa = scanner.nextDouble();
System.out.println("What's the total amount of credits you've taken?");
totalCreditsTaken = scanner.nextInt();
System.out.println("How many math and science credits have you taken?");
mathScienceCredits = scanner.nextInt();
System.out.println("How many liberal arts credits have you taken?");
liberalArtsCredits = scanner.nextInt();
System.out.println("How many elective credits have you taken?");
electiveCredits = scanner.nextInt();
//creates first "if" statment to determine if GPA is high enough to be on track or on probation
if (gpa < 2.0){
System.out.println("You're on academic probation.");
onProbation = true;
}
//PART III
//creates a conditional to see if there's enough credits to graduate
if (totalCreditsTaken < 40 ){
System.out.println("You need more credit(s) to graduate.");
canGraduate = false;
}
else{
System.out.println("Examining credit breakdown...");
canGraduate = true;
}
//PART VI
//Nested if-else if-else to determine if the student qualifies for BA or BS
if ((mathScienceCredits >= 9) && (electiveCredits >= 10)){
System.out.println("You qualify for a BS degree.");
canGraduate = true;
}
else if ((liberalArtsCredits >= 9) && (electiveCredits >= 10)){
System.out.println("You qualify for a BA degree.");
canGraduate = true;
}
else{
System.out.println("You currently don't meet the degree requirments.");
canGraduate = false;
}
//PART V
//Uses an if statement to either congradulate the student or tell the student to take more classes
if ((onProbation = true) || (canGraduate = false)){
System.out.println("You don't qualify to graduate.");
}
else{
System.out.println("Congradualations you qualify to graduate.");
}
}
}

You are assigning the values here:
if ((onProbation = true) || (canGraduate = false)){
You need to compare them using == instead
UPDATE (after comments)
Better yet, don't compare boolean values. Instead, since onProbation and canGraduate are both boolean types, you can use:
if (onProbation || ! canGraduate ){
credit to #RealSkeptic and #FredK (in their comments)

A bit more explanation about what's happening here.
In Java, the = operator is assignment, not comparison (The comparison operator is ==). So if a is an int, a = 3 means "put the value 3 in the variable a".
But an assignment is also an expression. In addition to putting the value in that variable, the expression also evaluates to the value that was assigned.
So the value of the expression a = 3 is 3. You can do things like:
System.out.println( a = 3 );
This will both put 3 in a, and print 3 on the console.
Usually, Java doesn't allow you to confuse between = and ==. If the variable is an int or a float or a String, writing a statement like:
if ( a = 3 ) ... // Compilation error
will not work because the value of the expression is 3, an int value, and if expects an expression of type boolean. So it will tell you that the expression is wrong, and you'll notice: "Oh, I meant ==".
But if the type of a is boolean, then writing a = false or a = true is an assignment, that also returns the value that was assigned - which is a boolean. Because of that, you can write
if ( a = false ) ... // Compiles correctly
and the compiler won't complain, because the value of the expression is boolean and that's what the if expects. The compiler doesn't know you actually meant to compare. All it knows is that it got an expression of the appropriate type.
For this reason it is recommended never to compare boolean variables at all. Instead of
if ( a == true )
It is perfectly correct to write
if ( a )
Because the if will succeed when a is true and fail when a is false. No need to compare! It's important to give the variable a good name like you did - canGraduate is a good name, and a statement like
if ( canGraduate )
is nicely readable "If [the user] can graduate...".
For false, you can use
if ( ! canGraduate )
it's not as nice-sounding in English, but it's clear enough, and clearer than if ( canGraduate == false ), with the added bonus that you will not miss the = and write if ( canGraduate = false ) by mistake.

Related

Character Class Method issues

So I'm currently working on a school assignment which is to design a program that allows the user to enter some text, and then the program checks:
The first letter of the first word is a capital letter (it needs to be lowercase)
That there are only letters and numbers in the entire user input
That there are no spaces in the user input
So the program does work but the issue I'm having is with the print statements, I'll post my code below and explain:
public static void main(String[] args) {
try (Scanner stdln = new Scanner(System.in)) {
String userInput;
boolean legal = true;
boolean style = true;
char input; //Checks the userInput variable to be sure that boolean is false if there's no lowercase letter at char0 + if there are no letters
char loop;
System.out.println("The program checks the properness of a proposed Java variable name.");
System.out.println("\nPlease enter a variable name (q to quit): ");
userInput = stdln.nextLine();
input = userInput.charAt(0);
do
{
if (!(Character.isLetter(input)))
{
legal = false;
}
if (userInput.contains(" "))
{
legal = false;
}
if (!(Character.isLowerCase(input)))
{
style = false;
}
for (int i = 1; i < userInput.length() &&legal; i++)
{
loop = userInput.charAt(i);
if (!(Character.isLetterOrDigit(loop)))
{
style = false;
}
}
if (!(legal) && !(style))
{
System.out.println("Illegal.");
}
else if (legal && !(style))
{
System.out.println("Legal, but uses poor style.");
}
else
{
System.out.println("Good.");
}
System.out.println("\nPlease enter a variable name (q to quit): ");
userInput = stdln.nextLine();
input = userInput.charAt(0);
} while (!(userInput.equalsIgnoreCase("q")));
}
}
}
So the code works and the first input I test comes out as it should, however, once I get a response that isn't "Good.", then the same response will print for every entry, here's a sample from a session I just did:
The program checks the properness of a proposed Java variable name.
Please enter a variable name (q to quit):
streetAddress2
Good.
Please enter a variable name (q to quit):
StreetAddress2
Legal, but uses poor style.
Please enter a variable name (q to quit):
streetAddress2
Legal, but uses poor style.
Please enter a variable name (q to quit):
Street Address2
Illegal.
Please enter a variable name (q to quit):
streetAddress2
Illegal.
In that sample session, 3 and 5 should return the statement "Good." but for some reason, it just prints the statement from the previous entry. I'm still fairly new to Java so I'm a little stumped. Any ideas?
You have to reset legal and style to true at the start of each iteration. However, it is not the only problem with your code. The logic is not correct.
Right now in the for loop you check all the characters being letters or digits. If this condition fails you set style to false. However, you should set legal to false instead, because such identifiers are not allowed.
Also, when you print the result you don't check the conditions correctly. For example, if legal is false, but style is true your code will print Good.
You forgot to reset to true your legal and style boolean variables.
At every iteration, the legal and style variables will keep containing the result of the previous input. For example, if on your first input you immediately write a variable name with an illegal syntax and poor style, you'll see that any following name will show the same result. Even though those names are good or they only lack in style, the output will still be the same (wrong) because both variables have been left to false and nothing sets them back to true.
Besides, the logic to print the output messages didn't account for all combinations correctly.
Both variable logic and output printing could be re-written as follows:
do {
//forgotten reset
legal = true;
style = true;
//excat same implementation of yours
if (!(Character.isLetter(input))) {
legal = false;
}
if (userInput.contains(" ")) {
legal = false;
}
if (!(Character.isLowerCase(input))) {
style = false;
}
for (int i = 1; i < userInput.length() && legal; i++) {
loop = userInput.charAt(i);
if (!(Character.isLetterOrDigit(loop))) {
style = false;
}
}
//If it's illegal it does not matter whether the variable name has a poor or good style, it's illegal anyway
if (!legal) {
System.out.println("Illegal.");
//If we're in this else branch then the variable name is legal, but we have to check its style.
//If it has poor style then we print the "poor style" message.
} else if (!style) {
System.out.println("Legal, but uses poor style.");
} else {
//Last case where the variable name is legal and has a good style
System.out.println("Good.");
}
System.out.println("\nPlease enter a variable name (q to quit): ");
userInput = stdln.nextLine();
input = userInput.charAt(0);
} while (!(userInput.equalsIgnoreCase("q")));

How do you test the value of charAt(0)?

So I am writing a code that ask a user if they would like to be recommended a new pet. I give them a message dialog the ask them to enter Y for Yes and N for No. This is my code do far and there is something I am not getting. The big question is how do I test if the value they entered is Y or N. The answer they give can either be lower case or upper case. How do I code this?
public static void aPet()
{
char answer;
String newPet;
newPet = JOptionPane.showInputDialog(null,"Would you like to recommend another pet?(Y), or Stop (N)","Another Recommendation?", JOptionPane.QUESTION_MESSAGE);
answer = newPet.charAt(0);
if (answer == y || answer == Y)
{
//methods to recommend pet
}
if (answer == n || answer == N)
{
System.exit(-1);
}
}
You need to use actual character literals, not just the letter:
if (answer == 'y' || answer == 'Y')
Characters are denoted in code by surrounding the letter with single quotes (they can also be denoted in other ways, but this is the simplest).
You can read about this on The Java Tutorials > Primitive Data Types which says, among other things:
Always use 'single quotes' for char literals and "double quotes" for String literals.
You are missing single quotes around the values 'y' and 'n':
Try this:
char answer = newPet.charAt(0);
if('y' == answer || 'Y' == answer) {
// recommend pet
} else {
// exit
}
OR
Edited
if(newPet.matches("y|Y")) {
// recommend pet
} else {
// exit
}
OR
if("y".equalsIgnoreCase(newPet)) {
// recommend pet
} else {
// exit
}
You can use Character#toUpperCase() like that:
if (Character.toUpperCase(answer) == 'Y')
{
//methods to recommend pet
}

For loop and charAt problems, trying to determine whether a string is numeric [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to write a program is for checking a real number, so i input "99aa", it says it is a right, but in fact, it should be wrong. i have check many time and i still can't fix the problem. can some one give me some hints?
public class jj {
public static void main( String[] args ) {
String num;
// Create a Scanner object for console input
Scanner input = new Scanner(System.in);
System.out.print("Enter the number: ");
num = new String( input.nextLine() );
for ( int i=0; i<=num.length(); i++ ) {
int j = num.charAt(i);
if (j>57 || j<42 || j==44 || j==47 ) {
System.out.print("This is not a real number.");
break;
} else
System.out.print("This is a real number.");
break;
}
}
}
I commented what's wrong with your logic but don't reinvent the wheel.
Use NumberUtils.isNumber from org.apache.commons.lang.math.NumberUtils :
Checks whether the String a valid Java number.
Valid numbers include hexadecimal marked with the 0x qualifier, scientific notation and numbers marked with a type qualifier (e.g. 123L).
if(NumberUtils.isNumber(num))
System.out.println("This is a valid number");
else
System.out.println("This is not a valid number");
Alternatively, if you want to check that you have only digits in your String, you can use
NumberUtils.isDigits:
Checks whether the String contains only digit characters.
boolean valid = NumberUtils.isDigits(num);
Your logic is wrong.
try this instead
if ((j >= 48 && j <= 57) || j==44 || j==47 ) {
}
You want to check whether it is between 48 (0) and 57 (9), boundaries included.
See the ascii table.
Sidenotes:
You're allowing j==47. 47 is /, dot is 46. What one do you want?
Your second break; will leave the iteration after the first cycle.
Try,
char ch = num.charAt(i);
if (!Character.isDigit(ch)) {
System.out.print("This is not a real number.");
break;
}
I'd just like to point out some logic trouble that's giving you some fits:
if (j>57 || j<42 || j==44 || j==47 ) {
System.out.print("This is not a real number.");
break;
} else
System.out.print("This is a real number.");
break;
}
First of all, nevermind the problems with the if check. Jeroen Vannevel's answer covers this.
After any number returns true on the if check, you print the error and break; the loop. This is fine (assuming we fix the if check). You don't need to check every digit if you know the first one is wrong, you can quit checking.
But your else prints a message guaranteeing that the whole number is real despite just checking a single letter.
And then the break; isn't contain in the if or the else (not your brackets and my indentation that makes it more clear). No matter what happens, you'll break; after a single iteration.
What you need should look something more like this:
boolean numberFlag = true;
for ( int i=0; i<=num.length(); i++ ) {
int j = num.charAt(i);
if ((j >= 48 && j <= 57) || j==44 || j==47 ) {
numberFlag = false;
break;
}
}
if(numberFlag) {
// logic when a valid number is checked
} else {
// logic when an invalid number is checked
}
We can't say whether num is a valid number of not until we've checked every single character in the string.
And please be sure to check #ZouZou's answer, as this is what you should really be doing.
You could think about this in terms of Characters and implement the following:
if (Character.isDigit(num.charAt(i))) {
//do something
}

Putting 2 Boolean controllers in a do while expression?

newbie programmer here. I'm using Java to try and create a number guessing game. I want my do while loop to continue looping until the user inputs the correct number OR they run out of guesses. This is what I have and I can't figure out how to use 2 boolean controllers for the life of me.
do
{System.out.println("Enter guess #1");
userGuess = keyboard.nextInt();
} while ((userGuess != actualNumber) || (remainingGuesses = guesses; remainingGuesses >= 1; remainingGuesses--));
Any help is appreciated!
I think that you want something closer to this effect:
remainingGuess = guesses;
do {
System.out.println("Enter guess #1");
userGuess = keyboard.nextInt();
} while ( userGuess != actualNumber || remainingGuesses-- > 0 )
Line by line:
remainingGuesses = guesses;
assigns guesses to remainingGuesses once, if you were to do it every iteration of your loop, it would never end
userGuess != actualNumber || remainingGuesses-- > 0
Keep iterating while the user has guessed incorrectly OR remainingGuesses is more than 0.
remainingGuesses--
Evaluates to the current value of the variable remainingGuesses, then after the expression decrements it by 1.
Initialize remaining guesses before entering the loop. Only check the condition in the while paranthesis "()"
reaminingGuesses = guesses;
do
{System.out.println("Enter guess #1");
userGuess = keyboard.nextInt();
remainingGuess--;
} while ((userGuess != actualNumber) || (remainingGuesses >= 1));
If you want it as a do while I would make a few minor changes, and assuming you have constants defined for things like actualNumber and the total number of allowed guesses:
// break the calls into seperate methods, to make them easier to read in the long term and to
// seperate logical concerns into discrete elements.
do {
// get the user guess
guess = getGuess();
// if shouldStop returns true you would stop, if it returns false you should continue, thus the !..
} while (!shouldStop(guess)) {
// decrement the guesses.
--remainingGuesses;
}
/// define these methods somewhere..,
// get your guess
public int getGuess() {
System.out.println("Enter guess #1");
return keyboard.nextInt();
}
public boolean shouldStop(int guess) {
// condensed if statement syntax in java, very handy for this kind of thing
// do we have enough remaining guess to keep going? If so, compare the guess to the actual number
// otherwise return true (the stop signal
return remainingGuesses > 0 ? guess == actualNumber : true;
}
If you really wanted to follow the whole thing through you could break the guess==actual number into a method as well, but its probably not needed in this case since its a simple equality check.
The methos shouldStop could be defined a number of ways however...
Early on I think it's helpful to write these logical blocks out fully, and condense from there, for example:
public boolean shouldStop(int guess) {
if(remainingGuesses <=0) {
return true;
} else if(guess == actualNumber) {
return true;
} else {
return false;
}
}

Beginner looping issue- while ... do

What the program does: Reads two values from input, asks user whether to add, subtract, or find the product. If user enters one of the three options, it calculates, otherwise the program will loop back to the beginning. The program should STOP after calculation if the user enters one of the three options.
I'm not sure why it keeps on looping. How do I make the script loop only when the user types in a string other than "sum", "difference", or "product"? Also, how can I make the code simpler? Is there any way to loop the program without using do ... while?
import java.util.Scanner;
import java.util.Random;
public class simp_calculator
{
public static void main (String[] args)
{
Scanner scan = new Scanner (System.in);
double a, b;
String response;
boolean noresponse;
do
{
System.out.println ("Please enter first number.");
a = scan.nextDouble();
System.out.println ("Please enter second number.");
b = scan.nextDouble();
System.out.println ("Would you like to find the sum, difference, product?");
response = scan.next();
if (response.equalsIgnoreCase ("sum"))
{
System.out.println (a + b);
}
if (response.equalsIgnoreCase ("difference"))
{
System.out.println (a - b);
}
if (response.equalsIgnoreCase ("product"))
{
System.out.println (a * b);
}
else
{
noresponse = true;
System.out.println ("Starting again...");
}
}
while (noresponse = true);
}
}
You are using the assignment operator, =, so noresponse will always be true. The result of the assignment expression is thus true.
You want to check if it is true, so use the comparison operator ==:
while (noresponse == true);
or, because it's already a boolean:
while (noresponse);
Also, you may be getting a compiler error that noresponse may not have been initialized. You will need to make sure that it's initialized in all cases, and that something sets it to false so the loop will eventually end.
change while (noresponse = true); to while (noresponse == true);.
= is an assignment operation - where as == comparison.
Two errors:
The else applies only to the last if; so for any value, other that "product", noresponse becomes true and the loop goes on. Replace all your ifs from the second on with else ifs.
noresponse should be given the value false at the beginning of the loop.
There are 2 issues:
Currently you are looping while noreponse equals true. So to exit that loop, you need to setnoresponse to false when a particular condition is met :) I could give you the answer, but you should be able to figure it out with the info I've given you. (hint: at some point you need to set noresonse to false).
Also, you are setting noresponse to equal, rather than comparing it. You need to use == to compare.
So make while (noresponse = true); into while (noresponse == true);.
just change while (reponse = true) to while(reponse) and name the variable ..

Categories