I am trying to get practice on loops and switch statements and trying to figure out the following issue.
The output depends on the integer day value.
For example if the user enters 8 then it will print the first 8 lines as follows:
On the 8th day of holidays, I did Eight jumping jacks,
....
...
On the 3rd day of holidays, I did Three pull downs,
...
..
On the 1st day of holidays, I did One downhill sprint.
So to solve this problem, I have used a switch statement in a for loop and then wanted to use another switch statement to put the appropriate suffix for the day number. Eg: 1st, 2nd etc
I have done the following but I am stuck badly and would really appreciate if they can help me out.
int day = in.nextInt();
for (int i = 0; i < day; i++) {
switch (day) {
// Also, do I add another switch statement here for suffix?
}
}
Loop is not required, you can do it as follows:
int day = in.nextInt();
switch(day){
case 10:
System.out.println("statement 10");
case 9:
System.out.println("statement 9");
case 8:
System.out.println("statement 8");
case 7:
System.out.println("statement 7");
case 6:
System.out.println("statement 6");
case 5:
System.out.println("statement 5");
case 4:
System.out.println("statement 4");
case 3:
System.out.println("statement 3");
case 2:
System.out.println("statement 2");
case 1:
System.out.println("statement 1");
}
So, when the input is 8, it will print your all statements starting from 8 to 1 as you require.
Use methods for each operation. Each method will have its own switch:
private String getDaySuffix(int day) {
switch(day) {
case 1: return "st";
// ...
}
}
private String getActivity(int day) {
switch(day) {
case 1: return "One downhill sprint";
// ...
}
}
for (int i = 0; i < day; i++) {
String s = "On the " + day + getDaySuffix(day) +
" day of holidays, I did " + getActivity(day);
}
That way, you improve cohesion: each method does what it is supposed to do, and nothing else.
Assume day has value entered by user.. then..
for(int i=day;i<=day && i!=0;i--)
{
switch(i)
{
case 8 :
On the 8th day of holidays, I did Eight jumping jacks,
break;
.
.
.
case 3 :
On the 3rd day of holidays, I did Three pull downs,
break;
.
.
case 1 :
On the 1st day of holidays, I did One downhill sprint.
break;
default :
break;
}
}
To get the right suffix you could use a switch:
private static String getSuffix(final int number) {
switch (number) {
case 0: throw new IllegalArgumentException();
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default:return "th";
}
}
To geht the word form of a number you could use an array:
final static String[] numbers = new String[] {
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine", "ten"
};
To use this, just append numbers[yourInt] to your string.
numbers[5] e.g. will be "five".
Putting everything together might look like this (It also appends an s to the activity if needed):
public class Main {
final static String[] numbers = new String[] {
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine", "ten"
};
final static String pattern = "On the %d%s day of holidays, I did %s %s%s\n";
final static Scanner in = new Scanner(System.in);
public static void main(String[] args) {
final int day = in.nextInt();
final String activity;
switch (day) {
case 1 : activity = "downhill sprint"; break;
// ...
case 3 : activity = "pull down"; break;
//...
case 8 : activity = "jumping jack"; break;
default : activity = "";
}
if (!activity.equals(""))
System.out.printf(pattern, day, getSuffix(day), numbers[day], activity, day > 1 ? "s" : "");
}
private static String getSuffix(final int number) {
switch (number) {
case 0: throw new IllegalArgumentException();
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default:return "th";
}
}
}
Converting the number to a word can be done with a switch statement, in the case where you are having a limited (and small) number. For example, only numbers one to 10.
It would be as follows:
String numberWord;
switch (day)
{
case 1:
suffix = "one";
break;
case 2:
suffix = "two";
break;
case 3:
suffix = "three";
break;
//ETC
default: break;
}
However, if you wish for a much larger range of numbers, I recommend you check out the following page:
http://www.rgagnon.com/javadetails/java-0426.html
It contains a method which converts a number to a word. It converts into the billions.
Regarding the suffix, a similar solution to that of above can be used. Watch out for 11, 12 and 13 though, because they have their unique suffixes.
String GetSuffix (int number)
{
int lastTwoDigits = number % 100;
if (lastTwoDigits == 11 || lastTwoDigits == 12 || lastTwoDigits == 13)
{
return "th";
}
switch (number % 10)
{
case 1:
suffix = "st";
break;
case 2:
suffix = "nd";
break;
case 3:
suffix = "rd";
break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0:
suffix = "th";
break;
default: break;
}
//This shouldn't happen
return "";
}
Here's an example of how to use this:
String result = "On the " + Integer.toString(day) + GetSuffix(day) + " day of holidays, I did " + EnglishNumberToWords(day) + " jumping jacks";
Related
is it considered bad practice to write a switch case statement with a comma such as this:
switch(name)
{
case 'a', 'A' :
break;
}
Rather than
switch(name)
{
case 'a':
case 'A':
break;
}
Just curious as my code seems to run fine either way but I want to get into the habit of using the proper/most accepted way.
It's not bad practice. In fact, it's considered concise and time-efficient.
Take a look at the following code that you have
switch(name){
case 'a', 'A' :
break;
}
The equivalent without using commas would be:
switch(name){
case 'a':
break;
case 'A':
break;
}
And the if-else equivalent would be:
if(name=='a'){
//Do something
}else if(name=='A'){
//Do something
}
Of these, the first example took a mere 36 characters to type. The latter took 49, and the last one took 37 characters.
Moral? Using the comma is definitely more concise and time-efficient that using two cases with a single result. Even the if statements would be more concise.
CheckStyle, the defacto standard for java style, has no check for this.
Do whatever is easiest to read.
I would say though use only one style or the other in any given switch statement.
From JavaDocs:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
class SwitchDemo2 {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1: case 3: case 5:
case 7: case 8: case 10:
case 12:
numDays = 31;
break;
case 4: case 6:
case 9: case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) &&
!(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = "
+ numDays);
}
}
So my main got deleted 2 days ago and my teacher helped me a bit with the switch code. I rebuilt the code yesterday and he was away yesterday and could not help me.
public static void main(String[] args) throws InterruptedException {
do {
try {
System.out.println("Enter your birthYear");
birthYear = Integer.parseInt(input.next());
int length = String.valueOf(birthYear).length();
System.out.println(length);
if (length != 4) {
lengthTest = false;
System.out.println("Invalid Choice");
} else {
lengthTest = true;
}
test = true;
} catch (Exception e) {
System.out.println("Invalid Choice");
}
} while (test == true ^ lengthTest != false);
do {
System.out.println("Please enter a number between 1-4 \n"
+ "1 = AreaOfTriangle \n" +
"----------------------------------\n" +
"2 = HoursToDaysAndHours Calculator \n" +
"---------------------------------- \n" +
"3 = CelciusToFahrenheit Calculator \n" +
"----------------------------------\n" +
"4 = BirthdayGame \r\n" +
"----------------------------------");
try {
choice = Integer.toString(input.nextInt()).charAt(0);
System.out.println(choice);
switch (choice) {
case 1:
aOT.areaOfTriangle();
break;
case 2:
hTDAH.hoursToDaysAndHours();
break;
case 3:
cTF.celciusToFahrenheit();
case 4:
System.out.println("Code not implemented");
break;
case 'e':
repeat = false;
break;
default:
System.out.println("");
break;
}
}catch (Exception e) {
System.out.println("Invalid Awnser");
}
} while (repeat == true);
}
My problem is in my switch case i want to be able to use int's and Char's at the same time. For example i want to use e to exit and and the 4 numbers
You can try to use String as an input paramenter, then any int value or char will be readed correctly without necessity to convert them:
try {
String choice = input.next();
System.out.println(choice);
switch (choice) {
case "1":
aOT.areaOfTriangle();
break;
case "2":
hTDAH.hoursToDaysAndHours();
break;
case "3":
cTF.celciusToFahrenheit();
case "4":
System.out.println("Code not implemented");
break;
case "e":
repeat = false;
break;
default:
System.out.println("");
break;
}
You can't use int and chars at the same time, as you can only use one variable and a variable has to have a type, but:
If you cast a char or Character to int you get values. For example ((int) 'e') evaluates to 101 if I am not mistaken. (Try System.out.println((int) 'e'));
So in your case, you can switch over int values and detect for 1,2,3,4 and 101.
Your default should also throw an exception and you are fine.
Happy Coding
You could just use the char representations of the digits 1-4:
char choice = input.next().charAt(0);
switch (choice) {
case '1':
aOT.areaOfTriangle();
break;
case '2':
hTDAH.hoursToDaysAndHours();
break;
case '3':
cTF.celciusToFahrenheit();
case '4':
System.out.println("Code not implemented");
break;
case 'e':
repeat = false;
break;
default:
System.out.println("");
break;
}
Basically I have this code, that with the input of 2 OR 3 letters/numbers combos like (AH, 10D, JS, and 7C) read back as value's of suits (Ace of Hearts, 10 of Diamonds, Jack of Spades, 7 of Clubs.)
Why, if I input "10D", does the code print nothing back? Why is it not register 10? How can I fix this?
ALSO: Please help me figure out how to shorten the case 2 - case 10 range into something more eloquent? I cannot use if-then-else statements.
System.out.print("Please enter a letter/integer of a playing card (A, J, Q, K, or 2 - 10),\nfollowed by card type (D, H, S, C):");
Scanner kbd = new Scanner(System.in);
String userInput = kbd.next().toUpperCase();
String valueofCard = userInput.substring(0, userInput.length() / 2); // gives first half of string
String suitofCard = userInput.substring(userInput.length() / 2); //give last half of string with + 1 if odd
StringBuilder result = new StringBuilder();
switch (valueofCard) {
case "A":
result.append("Ace of ");
break;
case "J":
result.append("Jack of ");
break;
case "Q":
result.append("Queen of ");
break;
case "K":
result.append("King of ");
break;
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "10":
result.append(valueofCard + " of ");
break;
}
switch (suitofCard) {
case "D":
result.append("Diamonds");
break;
case "H":
result.append("Hearts");
break;
case "S":
result.append("Spades");
break;
case "C":
result.append("Clubs");
break;
}
System.out.println(result.toString());
kbd.close();
If you use a regular expression, it will also reject bad input for you.
Regex: ([AJQK2-9]|10)([DHSC])
Sample code:
String card = "QS"; // Queen of Spades
Pattern cardPattern = Pattern.compile("([AJQK2-9]|10)([DHSC])");
Matcher m = cardPattern.matcher(card);
if (! m.matches()) {
System.out.println("Not a valid card: " + card);
} else {
String rank = m.group(1);
String suit = m.group(2);
// code here
}
It is simpler to code to the exceptional case(s)
Like
String valueofCard = userInput.substring(0, 1);
// unless starts with "10"
if (userInput.startWith ("10")) {
valueofCard = userInput.substring(0, 2);
}
I believe the problem is that, as an integer, 3 / 2 = 1 so when you input 10D, the substring reads the position counter as 1 instead of 2 which makes the string 1 instead of 10, which isn't handled by your cases.
I would recommend using either
if(userInput.length()>2)
{
String valueofCard = userInput.substring(0,2);
String suitofCard = userInput.substring(2);
}
else
{
String valueofCard = userInput.substring(0,1);
String suitofCard = userInput.substring(1);
}
Hello my program fails to run with ArrayIndexOutofBoundsExeption. I get this error when I run it:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -35
at RoulleteChecker.main(RoulleteChecker.java:134)
Here is my code:
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class RoulleteChecker {
public static void main( String args[] )
{
int a[] = new int[37];
for ( long roll = 1; roll <=99999999; roll++ ) {
a[0] = 1 + ( int ) ( Math.random() * 34);
switch ( a[0] ) {
case 0:
++a[1];
break;
case 1:
++a[2];
break;
case 2:
++a[3];
break;
case 3:
++a[4];
break;
case 4:
++a[5];
break;
case 5:
++a[6];
break;
case 6:
++a[7];
break;
case 7:
++a[8];
break;
case 8:
++a[9];
break;
case 9:
++a[10];
break;
case 10:
++a[11];
break;
case 11:
++a[12];
break;
case 12:
++a[13];
break;
case 13:
++a[14];
break;
case 14:
++a[15];
break;
case 15:
++a[16];
break;
case 16:
++a[17];
break;
case 17:
++a[18];
break;
case 18:
++a[19];
break;
case 19:
++a[20];
break;
case 20:
++a[21];
break;
case 21:
++a[22];
break;
case 22:
++a[23];
break;
case 23:
++a[24];
break;
case 24:
++a[25];
break;
case 25:
++a[26];
break;
case 26:
++a[27];
break;
case 27:
++a[28];
break;
case 28:
++a[29];
break;
case 29:
++a[30];
break;
case 30:
++a[31];
break;
case 31:
++a[32];
break;
case 32:
++a[33];
break;
case 33:
++a[34];
break;
case 34:
++a[35];
break;
}
}
JTextArea outputArea = new JTextArea();
outputArea.setText( "Lets see: " + a[0-35] );
JOptionPane.showMessageDialog( null, outputArea,
"Searching for the frequency: 99999999 times", JOptionPane.INFORMATION_MESSAGE );
System.exit( 1 );
}
}
Please my head is going to blow with this. I think that my error is on the a variable.
The error is from this line:
outputArea.setText( "Lets see: " + a[0-35] );
The - sign is the arithmetic minus operator. So, 0 - 35 is -35, which is, of course, not a valid index. I'm guessing you wanted to print the range of 0 to 35, which could be done with Arrays.toString:
outputArea.setText( "Lets see: " + Arrays.toString(a));
First, all that gigantic switch could be replaced by this:
++a[a[0] + 1];
Then, as other people already pointed out, a[0 - 35] do not means what you want, it will not magically grab the positions 0 to 35 of the array. It is just the math result of 0 subtracted to 35, which is -35. There is no position -35 on an array.
To represent the array as a String, we can use Java 8 Streams:
IntStream.of(a).limit(36).boxed().collect(Collectors.toList()).toString().replace(", ", "\n")
What this does:
This will convert the int[] to a IntStream (the IntStream.of(a) part).
Lets limit to get only the first 36 elements (since you wanted the elements from 0 to 35). This is what the .limit(36) does.
Then the IntStream will be converted to a Stream<Integer> (the .boxed()) part.
Then it will be converted to a List<Integer> (the .collect(Collectors.toList())) part.
Then it will be converted to a String (the .toString() part).
Since that String will be too long to be presented on a single line, it is a good idea to add some line breaks, this is what the .replace(", ", "\n") does.
Finally, you don't need the System.exit(1);, it has no purpose here.
With that, this is your resulting code:
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class RoulleteChecker {
public static void main(String args[]) {
int a[] = new int[37];
for (long roll = 1; roll <= 99999999; roll++) {
a[0] = 1 + (int) (Math.random() * 34);
++a[a[0] + 1];
}
JTextArea outputArea = new JTextArea();
outputArea.setText("Lets see: " + IntStream.of(a).limit(36).boxed().collect(Collectors.toList()).toString().replace(", ", "\n"));
JOptionPane.showMessageDialog(null, outputArea,
"Searching for the frequency: 99999999 times", JOptionPane.INFORMATION_MESSAGE);
}
}
New improved answer:
To show line numbers, I think that the Streams approach will not work or it would be overly complex. So lets use an specialized method instead:
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class RoulleteChecker {
private static final int TIMES = 99999999;
public static void main(String args[]) {
int a[] = new int[36];
for (long roll = 1; roll <= TIMES; roll++) {
int r = (int) (Math.random() * a.length);
++a[r];
}
JTextArea outputArea = new JTextArea();
outputArea.setText("Lets see:\n" + asString(a));
JOptionPane.showMessageDialog(null, outputArea,
"Searching for the frequency: " + TIMES + " times", JOptionPane.INFORMATION_MESSAGE);
}
private static String asString(int[] s) {
StringBuilder sb = new StringBuilder(8 * s.length);
for (int i = 0; i < s.length; i++) {
sb.append(i + 1).append(": ").append(s[i]).append("\n");
}
return sb.toString();
}
}
There is a few more differences here:
Since the 0th position of the array is just to temporarily hold the newly generated number, lets get it out of the array entirely. This is what the r variable is. And since I removed the 0th position of the array, so I removed the + 1 on the ++a[a[0] + 1] which became simply ++a[r].
I moved the number of times (99999999) to a constant. This makes it easier to make it changeable if needed.
Again, since I removed the 0th position of the array, I also removed the 1 + from the line that calculated a random number. Further, I made it grab the size of the array dynamically, so you don't need to track the array size both when creating it and when randomly accessing one of its positions.
The asString method should be pretty easy straightforward. The only gotcha is the i + 1, where the + 1 has the purpose to show the indexes starting at 1 instead of 0.
The parameter on the StringBuilder's constructor in the asString method is just a total String size estimative for performance, it is not an important thing.
This is Java:
a[0-35]
actually means:
a[-35]
What makes you think -35 is a valid index? You see --- all the information that you need to fix the bug is there - you just have to read the exception message carefully. It tells you the position of the error, and it tells you the invalid index!
And btw: consider your switch statement.
Do you really think you need to write down a switch that more or less does
case i:
i++;
?
I was doing some some Java homework with my friend. The instructor wants him to write a Java program to translate an integer input into a numeric grade. 100-90 = A and so on. The only catch is that he must use a switch statement. He must also:
Include a case in your switch statement that will display a polite
error message if the user enters any number less than 0 or greater
than 100."
Originally I thought of this...
import java.util.Scanner;
public class grade
{
public static void main(String[] args)
{
int ng;//number grade
String lg = "";//letter grade
System.out.println("enter grade");
Scanner in = new Scanner(System.in);
ng = in.nextInt();
switch (ng/10)
{
case 10:
case 9:
lg = "A";
break;
case 8:
lg = "B";
break;
case 7:
lg = "C";
break;
case 6:
lg = "D";
break;
default:
lg = "F";
break;
}
System.out.println("You got an " + lg);
}
}
This isn't perfect because it allows values over 100 and below 0, but I am trying to avoid typing out every integer from 100-0. This seems like a ridiculous use of a switch statement and I can't imagine why a college professor would teach it, other than to illustrate the DRY principle.
Is there a better way that still uses the switch statement, but doesn't type every int from 100-0?
You could always add some minor complexity to your switch expression to make the cases simpler; this will calculate 90-100 as 10, 80-89 as 9 and so on, 101 and above will become 11 and above, and every input below 0 will become 0 or negative so they'll fall under default;
switch ((ng-ng/100+10)/10)
{
case 10:
lg = "A";
break;
case 9:
lg = "B";
break;
case 8:
lg = "C";
break;
case 7:
lg = "D";
break;
case 6: case 5: case 4:
case 3: case 2: case 1:
lg = "F";
break;
default:
System.out.println("Polite Error");
lg = "";
}
Yeah, no way in hell you would want to actually use a switch statement for this lol. But the way you've suggested is about the best way I can think of to do it.
I would make the default be for the error scenario though, because that could any integer less than 0 or over 100. Between 0 and 100, at least you have a finite number of cases (though you'll have to repeat the "F" case several times).
Nice use of integer division ;)
Okay, well this code officially embarrasses me and makes me cry. But here, just using switch statements.
import java.util.Scanner;
public class grade
{
public static void main(String[] args)
{
int ng;//number grade
String lg = "";//letter grade
boolean error = false;
System.out.println("enter grade");
Scanner in = new Scanner(System.in);
ng = in.nextInt();
switch (ng/10)
{
case 10:
switch (ng)
{
case 100:
lg = "A";
break;
default:
error = false;
break;
}
break;
case 9:
lg = "A";
break;
case 8:
lg = "B";
break;
case 7:
lg = "C";
break;
case 6:
lg = "D";
break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0:
lg = "F";
break;
default:
error = true;
break;
}
if (error) {
System.out.println("Sorry, the grade must be between 0 and 100");
} else {
System.out.println("You got an " + lg);
}
}
}
Blech.
How about:
String lg = null;
switch (ng/10)
{
case 10:
if (ng > 100) {
// polite error
break;
}
case 9:
lg = "A"
break;
case 8:
lg = "B";
break;
case 7:
lg = "C";
break;
case 6:
lg = "D";
break;
default:
if (ng < 0) {
// polite error
break;
}
lg = "F";
break;
}
After the switch you'd have to check if a grade were set or not.
if (lg == null) {
System.out.println("The input score was > 100 or < 0");
} else {
System.out.println("You got an " + lg);
}