While code, Method, Int to boolean understanding - java

I'm reviewing some code for a college assignment and we've been given examples to assist us.
I'm little confused on what the below is doing as it's using the assignment operator instead of the .equals or == method.
If I replace the code with the == (and create a local variable to compare it to) the code starts infinite looping and displaying out the default value.
int select = 0;
do {
switch (select) {
case 1:
Problem();
break;
default:
System.out.println("Invalid");
break;
}
} while ((select = getSelection()) !=3);
public static int getSelection () {
(Return function here with has.nextInt and scanner class to receive input)
}
From my limited understanding, the above assigns "Select" to the value from the "getSelection" method, it's also stating do not accept inputs that are 3 e.g. System.exit0 at this point.
Have I understood correctly?
(Further example as requested)
I would do something along the lines of:
int select = 0;
int select1 = 0;
do {
switch (select) {
case 1:
Problem();
break;
default:
System.out.println("Invalid");
break;
}
} while (select == select1);
I am attempting to think of a logical equivalent to the lecturers example but seem to be unable to do this without breaking the while loop.

In java, (and other "C like" languages) the result of an assignment is the value assigned, ie this code:
do {
// other code
} while ((select = getSelection()) !=3)
is the same as:
do {
// other code
select = getSelection();
} while (select != 3)
This style, known as in-line conditional, is generally considered a style to be avoided.
There is a checkstyle violation for it - see AvoidInlineConditionals

Related

How do I keep looping in a do-while loop as long as the default part of a switch triggers?

What I am trying to accomplish: when the user types in anything other than 1 or 2, there will be a prompt saying "I don't understand you" and it would ask the user to choose 1 or 2 again without having to run the program each time.
Something like this:
do {
String a = input.nextLine();
num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
break;
case 2:
System.out.println("goodbye");
break;
default:
System.out.println("I don't understand you");
}
} while (num == default);
I know typing this will give me an error, so how do I compare it?
First, you have a potential infinite loop because the value for num which controls the stoping condition is never updated inside the loop.
Second, you could introduce a local variable to track when the user input was understood and exit the loop on that condition:
boolean understood;
do {
understood = false;
String a = input.nextLine();
int num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
understood = true;
break;
case 2:
System.out.println("goodbye");
understood = true;
break;
default:
System.out.println("i dont understand u");
break;
}
} while (!understood);
What you asked is technically a while(true) since everything which is not 1 or 2 is default. Also you should probably put your scanning bit in the loop.
If you try to check if value is different from 1 and 2 to ask again for a valid option:
do
{
// stuff
}
while( num != 1 && num != 2)
Since "default" is a keyword you just can not compare it to anything. It's meaningless though, because in your condition you used all possible cases(case 1 and case 2), so your code will never end, printing either "hello" or "goodbye" forever.

I don't know how to leave this looping structure

Ok, so the code below loops wonderfully. It can loop as long as it wants to. The thing is though, I can never get out of the loop. I'm trying to build a text-adventure, by the way for those wondering, but I really need to get out of this loop.
System.out.println("\n\nWelcome, " + name + "! To proceed, enter your class of fighter.");
System.out.println();
boolean x = true;
while (x){
//information print statements
System.out.println("What will your class be? ");
String heroclass = scan.nextLine();
heroclass.toLowerCase();
String A;
switch (heroclass)
{
case "slayer": A = "You have selected the Slayer class.";
break;
case "blader": A = "You have selected the Blader class.";
break;
case "bandit": A = "You have selected the Bandit class.";
break;
case "wizard": A = "You have selected the Wizard class.";
break;
default: A = "Invalid entry.";
break;
}
String killloop = A;
if (killloop.charAt(0) == 'Y'){
x = false;
}
}
You need to assign heroclass.toLowerCase(); to the original value of heroclass:
heroclass = heroclass.toLowerCase();
If you do not do this, the lowercase version of heroclass is not saved.
heroclass is of String type. String is immutable type of object, so you can't update this string. heroclass.toLowerCase() just return another String object with lower cased characters, so you need to reassign this string result to this variable:
heroclass = heroclass.toLowerCase();
Put your loop in a labeled block:
myblock: {
while (true) {
//code
heroclass = heroclass.toLowerCase();
switch(heroclass)
{
case "slayer": A = "text";
break myblock;
//repeat with other cases
}
}
}
//goes to here when you say "break myblock;"
What you're doing is basically assigning the label myblock to the entire loop. When you say break myblock it breaks out of the entire section inside of the brackets.
NOTE: I would recommend this solution over the others because it doesn't depend on the magic value assigned by the switch; it works no matter what it is.
Also, I've added the part to make it case insensitive. Sorry about the confusion!
Although coding wombat is right, i'm not a big fan of the way you did things here. A loop around your whole program like this isn't good practice. It's super clunky and will lead to many problems, not to mention you're making things more complicated for yourself. Ideally you'd want to put this class selection part of the program inside a method. Then if the user's input is invalid, simply call back the method recursively until you get correct input.
Ex.
case A: do this...
case B: do this...
case C: System.out.println("Not a valid input);, classSelector();
Also, when you use OOP you have the benefit of storing all the player's attributes inside an object, as well as making methods that manipulates those attributes. It will make your code a lot cleaner and easier to work with.
Ex.
Player1.heal(10);

How can I avoid using more than a single "break" statement in a loop?

For code quality reason, I would like to refactor my code a little bit in order to use only one break statement in my loop. But I am not sure I can do this the way SonarQube is aking me...
Here's my code :
for (Integer integer: integerKey.keySet()) {
if (map.containsKey(integerKey.get(integer))) {
TypeValue value = map.get(integerKey.get(integer));
sb.append(integerKey.get(integer)).append(":");
sb.append(encodeValue(value));
sb.append("|");
if (integerKey.get(integer).equals(min)) {
break;
}
} else if (integerKey.get(integer) <= min){
TypeValue value = map.get(min);
sb.append(min).append(":");
sb.append(encodeValue(value));
sb.append("|");
break;
} else {
sb.append(integerKey.get(integer)).append(":");
sb.append("0");
sb.append("|");
}
}
I would like to do the same thing but using only one break but I am not sure I can write only one if condition in this case instead of if-elseif-else.
Any ideas ?
Thanks.
You could define a variable for the break-condition and include it into the for-loop condition:
boolean endLoop = false;
for (Iterator<Integer> keys = integerKey.keySet(); keys.hasNext() && !endLoop; ) {
Integer integer = keys.next();
if (map.containsKey(integerKey.get(integer))) {
...
if (integerKey.get(integer).equals(min)) {
endLoop = true;
}
} else if (integerKey.get(integer) <= min){
...
endLoop = true;
} else {
...
}
}
or declare a local variable in the loop which is set to true if the loop should left with a break:
for (Integer integer: integerKey.keySet()) {
boolean endLoop = false;
if (map.containsKey(integerKey.get(integer))) {
...
if (integerKey.get(integer).equals(min)) {
endLoop = true;
}
} else if (integerKey.get(integer) <= min){
...
endLoop = true;
} else {
...
}
if (endloop)
break;
}
If you want to use only one break, then you could set a boolean variable and test it at the end of the loop.
#hacks4life, the answer you selected is definitely the one you were asking for but it is not the one you should get from an "improve the quality of code" point of view (After all, you did add the SonarQube tag to your question which kind of implies you are interested in code quality).
Neither your code snippet nor the one from the selected answer are easy to read nor to maintain. And the main is reason is that several code logics are mixed into each other (aka. Spaghetti_code).
If you could split exit conditions from string concatenation logic, the question would be irrelevant and your code would be both easier to maintain and would have neither multiple break statement neither a mutable control flow variable (which both are code smells).

manipulating an arraylist of type String

I've got a problem here that's been giving me some real trouble and I really cant even get an idea of what to do. here's the assignment and my code so far.
Create a system using an ArrayList which stores and manipulates names.
Using standard input constantly prompt user for the following ..
Enter command or quit: (if they enter quit -- quit program)
Commands:
add <name>: add the String <name> to ArrayList;
change <name> <newName>: change all items in ArrayList which
have <name> to <newName>;
delete <name>: delete all items in Arraylist which are <name>;
print: print the ArrayList;
amount: display the amount of items in ArrayList.
System must work... and have proper error messages..
import java.util.*;
public class NameManipulation {
static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("enter a command, or quit!");
ArrayList<String> names = new ArrayList<String>();
String command = console.next();
int size = names.size();
for (String x = null; size; x++) {
if (command == "add") {
String assignment = console.next();
names.add(assignment);
}
if (command == "change") {
String newname = console.next();
names.set(names.size, newname);
}
if (command == "delete") {
String delete = console.next();
if (delete == names)
;
names.remove();
}
if (command == "print") {
System.out.println(names);
}
if (command == "amount") {
amount = (names.size - 1);
System.out.println(amount);
}
if (command == "quit") {
System.out.println("You just quit!");
break;
} else
System.out.println("command not found!");
System.out.println(names);
}
}
}
Don't use == (in Java that tests reference equality); you want to test for object value equality (and I suggest case-insensitivity) so you want to use String.equalsIgnoreCase and you should probably use else if for the other tests - for one example,
if(command.equalsIgnoreCase("add")) {
String assignment = console.next();
names.add(assignment);
} else if // ...
Also, this is just wrong;
for (String x = null; size; x++) // null++ is going to give you a bad time.
I think you wanted
for (int x = 0; x < size; x++)
Just looking at this it seems like it has a lot of problems...
In the for loop you're initializing a String to null and then trying to increment it (x++). I don't think that's legal syntax. Also, your for loop condition is set to size, which will initially be equal to 0. I'd have to test it, but the 0 may evaluate to false, which means the loop would never execute.
You don't want a for loop anyway, probably a do-while loop that runs until the command is equal to "quit" do{}while(!command.equals("quit"));
You should be using .equals() instead of '==' as was mentioned by Elliot Frisch. Also ignoring case is good, and you should be using else ifs.
In the change command you should be parsing out two parameters -- both the name to replace and the new name, and then perform the replacement. Right now you have the first parameter as names.size, which I think will be outside the bounds of the list (names.size() - 1 should be the last element). Instead you should get the index of the name you're replacing.
Depending on Java's toString implementation of ArrayList it may print out names nicely or it might be something like "#ArrayList Object" - I think Java has a nice ArrayList toString method though so that may work.
On the print amount, you should be using names.size() instead of names.size() - 1 (because names.size() - 1 will give you one less item than what is actually in the list)
you could try and use a switch block that could stream line your control statements. As stated above learn when to use == and when to use the .equals(). One compares a reference (==) the other compares the memory location, the important thing to take away from this, is that a String is an object and when you create a new String, it compares the address rather than a value (forgive me if i am wrong).
switch(command){
case "add": names.add(assignment);
break;
case "change": ..... etc.
}
If I were trying to accomplish this task I would use a List, not an ArrayList. I hope this method helps! This is C# code. I don't know the exact Java syntax but it seemed as if a lot of it was similar. I hope this methodology helps!
static void Main(string[] args)
{
string statement = "";
bool executed_command_properly;
while (statement != "quit")
{
executed_command_properly = false;
statement = Console.ReadLine();
string[] my_statement_elements = statement.Split(' ');
string command = my_statement_elements[0];
//could possibly use an array for inputs
string input1 = my_statement_elements[1];
string input2 = my_statement_elements[2];
switch(command)
{
case "add":
// do stuff
executed_command_properly = true;
break;
//other cases
}
if (executed_command_properly != true)
{
//error messages
}
}
}

Java switch (use values in a case calculated in another case)

I'm making a program that has menus and I'm using switch to navigate between the menus.
I have something like this:
switch (pick) {
case 1:
// Here the program ask the user to input some data related with students (lets say
// name and dob). Student is a class and the students data is stored in 1 array of
// students. If I do:
// for (Student item: students){
// if (item != null){
// System.out.println(item);
// }
// }
// It will print the name and dob of all the students inserted because I've created
// a toString() method that returns the name and dob of the students
case 2:
// On case 2 at some point I will need to print the array created on the case
// above. If I do again:
// for (Student item: students){
// if (item != null){
// System.out.println(item);
// }
// }
// It says that students variable might have not been initialized.
Question:
If a variable is created in one case it's values can't be used in another case?
What I was trying to do was first enter in case 1 and input the values and then, in case 2 be able to use some of the values defined in case 1.
If this can't be done, please point me in the right direction.
Please keep in mind that I've started to learn java only a few weeks.
favolas
Declare the variables before the switch and you'll be able to use them in all cases
int var1;
switch(number) {
case 1:
var1 = 2;
break;
case 2:
var2 += 3;
break;
...
Whenever there are curly brackets, you have what is known as a different scope.
If you create variables in there, they are lost when you leave that scope.
If you create the variable BEFORE, you can use it.
int subMenu = 0;
switch(...){
...
subMenu = 1;
}
if (subMenu == 1 ){
....
}
Will work even when you leave the switch.
If you try to declare (ie: int a = 2) a variable in case 1 and then use it also in case 2 you will get the error message: "Variable is already defined...". That explains why you can't do that, the compiler has to know you have declared a variable before you use it.
If you declare all the variables before the switch-statement you will be fine. An example:
int var;
swith(...){
case 1:
var ++;
break;
case 2:
var +=10;
break;
}

Categories