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;
}
Related
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
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.
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);
I don't think my switch statement is doing anything with my code, I'm new to java so I'm not sure how to use a switch statement in a while loop. I'm trying to take each grade/credit entered so I can find the GPA, but I added a System.out.print for the grades and it says it's worth 0 no matter what gets entered. Please help!
package exercises;
import java.text.DecimalFormat;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class GPA_Calculator {
public static void main(String[] args)
{
String greeting = "Hello, this program will calculate your GPA. You will be asked \n"+
"to enter your letter grade for each class, then you will be asked to enter \n"+
"the corresponding number of credits for that class. Once all the grades and credits\n"+
"have been entered, the program will display your GPA.";
JOptionPane.showMessageDialog(null,greeting,"Greeting - Introduction",1);
char gradeEntered;
String grade = "";
String creditEntered = "";
String inputGrade = "";
String inputCredit = "";
String enterGradePrompt = "Enter your letter grade (A, B, C, D, F)\n"+
"Enter Q to display your results\n\n";
String enterCreditPrompt = "Enter the credit hours for your course (0, 1, 2, 3, 4, 5, 6)\n"+
"Enter Q to display your results\n\n";
int points = 0, sum = 0, credits = 0, gradeCount = 0;
while(!inputGrade.toUpperCase().equals("Q"))
{
inputGrade = JOptionPane.showInputDialog(null,enterGradePrompt,"Enter grade",1);
gradeEntered = inputGrade.charAt(0);
grade += inputGrade.toUpperCase()+"\n";
inputCredit = JOptionPane.showInputDialog(null,enterCreditPrompt,"Enter grade",1);
creditEntered += inputCredit+"\n";
if(inputCredit.toUpperCase().equals("Q"))
continue;
credits = Integer.parseInt(inputCredit);
credits++;
switch (gradeEntered){
case 'A': points = 4;
break;
case 'B': points = 3;
break;
case 'C': points = 2;
break;
case 'D': points = 1;
break;
case 'F': points = 0;
break;
}
sum += gradeEntered;
gradeCount++;
}
// Prevents "Q" from being printed in results
grade = grade.substring(0,grade.length()-2);
creditEntered = creditEntered.substring(0,creditEntered.length()-2);
DecimalFormat df = new DecimalFormat("#.##");
double gpa = sum / gradeCount;
String results = "The courses you entered are:\n\n"+
"Grade "+"Hours \n"+
grade+" "+creditEntered+"\n"+
"Resulting in a GPA of "+df.format(gpa)+"\n\n"+
"This program will now terminate!";
JOptionPane.showMessageDialog(null, new JTextArea(results),
"results from the Invitation list generator",1);
}
}
The problem is that your switch statement is checking the value of grade, but your input is stored in inputGrade. The former is never reassigned from the empty string, so points never gets incremented.
EDIT: To expand on the comment below:
the conditional in either a while or do/while loop isn't being checked. You're checking it inside the loop and breaking out, which is fine, as you can just make an infinite loop and let the break terminate it. However, it shouldn't be duplicated in the loop conditional.
You should do check that condition early. There's no sense in performing anything inside the loop if the user enters 'q' (also, then, you don't have to have the part where you try to strip it afterwards).
Also, you should always try to keep your variables as locally as possible. There's no need to have anything but the aggregators (totalXxx and yyyEntered in this case) outside of the loop. It just makes it confusing for you in this case, as it's masking the source of your problem. When the switch statement hits the first time, it checks the empty string. The second time, it checks the first string. When you hit 'q', it breaks, and skips your last input. If these input variables were declared inside the loop, that would be immediately apparent.
Finally, while I'm here, you have an error in your gpa calculation. The points per score should take the weight of credits as a positive, not a negative. Something like:
sum(grade * credits) / sum(credits)
I can post fixed code if you want, but since I suspect this is an academic exercise, it would be more beneficial if you came to the solution yourself.
Your switch statement is using grade which seems to be never written to. It's always "".
You get inputGrade, but you don't write to grade itself.
As it is always "", you always get nothing from your switch
You are appending each grade to your gradeEntered
gradeEntered += inputGrade.toUpperCase()+"\n"; // at a point this is something like A\nB\nC\nD\nE.... so it will not match anyway
switch (gradeEntered) {
case "A": points = 4;
break;
case "B": points = 3;
break;
case "C": points = 2;
break;
case "D": points = 1;
break;
case "F": points = 0;
break;
}
so most of the times it will not match to any of your cases.
Either you have to have a separate char for grade and use it in the switch or first use switch and then append it to your variable
You are adding a newline ("\n") to your input, (inputGrade.toUpperCase()+"\n";) so none of your cases are valid.
That is, "A" does not equal "A\n"
I think you should not use "gradeEntered" and instead use:
switch (inputGrade.toUpperCase())
especially since after running the loop more than once, your "gradeEntered" string will start to look like this: "A\nB\nF\nQ\n", which is very far removed from all your cases.
Also, switching on strings is not good practice - it is a newish development in java, and won't be supported by computers running older versions fo java - though for your own use, if the compiler doesn't complain then it is fine. Still, better to get in the habit of switching on chars or ints, since most other programming languages won't let you switch on strings.
I am trying to store a value inside a variable depending on the input:
switch(pepperoni) {
case 'Y':
case 'y':
topping1 = 1;
break;
case 'N':
case 'n':
topping1 = 0;
break;
default:
{
System.out.print("This is not a valid response, please try again \n");
System.out.print("Do you want Pepperoni? (Y/N): ");
pepperoni = scan.next().charAt(0);
break;
}
I want the variable topping1 to store the value 1 if the input is 'Y' or 'y' and to store the value 0 if the input is 'N' or 'n'
If the input is neither 'Y', 'y', 'N' nor 'n' then I want it to repeat the question until a valid input is typed in.
The problem arises when I later in the program try to print the value 'because it might have not been initialized', which somewhat makes sense. (example below)
if(topping1 > 0)
System.out.println("Pepperoni");
// 243: error: variable topping1 might not have been initialized
I do realize there are other ways to do this, but as I am really wanting to learn Java I try to understand as much of the fundamentals as possible. Therefore would I be really happy if someone could tell me why this not work and if there is a way to do this with a switch statement or quick fixes.
The issue probably is that the switch statement does not guarantee a value set for topping1. If you received a response of 'L' you would neither set it to 1 or 0. You should set a default value when you initialize topping1 or set one in the default clause.
Java's compiler can't analyze your code to know that you won't let people out of the loop (that I presume this is in) until it's set. It can only tell that there's a path through the code which would allow it to not be set.
This works (same would be true for switch):
int a;
if (condition()) {
a=0;
} else {
a=1;
}
System.out.println(a);
And this works:
int a=1;
if (condition()) {
a=0;
}
System.out.println(a);
This does not:
int a;
if (condition()) {
a=0;
}
System.out.println(a); // compiler error!
because if condition() returns false, a is undefined. Local variables must be defined. Note that this is different than fields on classes which automatically are assigned default values of null, 0 or false.
If pepperoni is not Y, y, N, or n, you never assign a value to topping1, because the default case never assigns it a value. E.g., if pepperoni is not one of those four values, then the flow of control skips the other two cases and goes to default, which never gives topping1 a value, so later when you try to use it, it's possible topping1 has never received a value at all.
The "workaround" is to correct the logic so that you never try to use topping1 without having assigned it a value. How you do that depends on logic you haven't shown us. You might assign it a value other than 0 or 1 (the values you assign in the other branches of the switch), for instance.
You are getting the "might not have been initialized" error because there is a path through your switch statement in which you don't initialize topping1 and you reference the variable later.
What you can do: Initialize topping1 to an invalid value (say, -1). Then place your case statement in a while loop that checks if the value of topping1 is still equal to -1.
Then, once you are out of the while loop, you know that the following are true:
You have intialized topping1, so no compiler error should result.
You have a valid value for topping1.
This looks a little ugly, but writing the loop like this is one way to stop the compiler complaining:
for (;;) {
System.out.print("Do you want Pepperoni? (Y/N): ");
pepperoni = scan.next().charAt(0);
switch (pepperoni) {
case 'Y':
case 'y':
topping1 = 1;
break;
case 'N':
case 'n':
topping1 = 0;
break;
default:
System.out.println("This is not a valid response, please try again");
continue;
}
break;
}