Switch statement within Do-While loop doesn't exit - java

The code doesn't exit after I type "stop" - for some reason. Why?
Step-by-step debugging shows that after I enter "stop" it's value consists of exactly 's','t','o','p' without any line breaks, etc. - however, the code still goesn't exit. Could anyone tell why, please?
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// asking username
System.out.print("Username: ");
String username = input.nextLine();
String inpText;
do {
System.out.print(username + "$: ");
inpText = input.nextLine();
System.out.print("\n");
// analyzing
switch (inpText) {
case "start":
System.out.println("> Machine started!");
break;
case "stop":
System.out.println("> Stopped!");
break;
default:
System.out.println("> Command not recognized");
}
} while (inpText != "stop");
System.out.println("Bye!..");
}
}

To compare Strings use .equals() and not ==, unless you really know what you are doing.
inpText != "stop" //Not recommended
!"stop".equals(inpText) //recommended
You cannot use a String in a switch unless you are using jdk 1.7+.
Cannot switch on a value of type String for source level below 1.7.
Only convertible int values or enum variables are permitted

You are comparing pointers not strings with this piece of code:
while (inpText != "stop");
Should be something like this:
while (!"stop".equals(inpText));

change while (inpText != "stop"); to while (!(inpText.equals("stop")));

If your JDK is 1.6 or lower you can't switch() on a String
P.S.
switching on a String is probably not the best solution Yeah in java 1.6 you can only switch int, boolean, double, long, and float I believe.

Related

Is there a way to use or operator || on char in java?

Im new in programming, so this is kind of basic but I cant find an answer here on why is this keep happenning. "The operator || is undefined for the argument type(s) char, char",can someone please help, its for our task. Thanks in advance.
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char choice = (scan.next().charAt(0));
switch (choice) {
case ('A'||'a'):
System.out.println("Wrong Answer");
break;
}
}
}
You can't logically OR together characters in Java. The closest thing to what you want to do in Java might be:
switch (choice) {
case 'A':
case 'a':
System.out.println("Wrong Answer");
break;
}
Here we are letting both cases of A to flow to the same case. Another option:
switch (Character.toUpperCase(choice)) {
case 'A':
System.out.println("Wrong Answer");
break;
}
This approach first uppercases the input character, and then we only need to check uppercase letters in the switch statement.
You could replace switch with regular if statement and use || operator:
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char choice = scan.next().charAt(0);
if (choice == 'A' || choice == 'a') {
System.out.println("Wrong Answer");
}
}
}
However, much better will be operating with String class. And next() from Scanner returns exactly String instance. With small modification it could be like:
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String firstLetter = scan.next().substring(0, 1);
if (StringUtils.equalsIgnoreCase(firstLetter, "A")) {
System.out.println("Wrong Answer");
}
}
}
Also, used equalsIgnoreCase() from StringUtils class. You have to add this dependency to the project with your build manager.
You can convert character to the lower or upper case:
switch (Character.toLowerCase(choice)) {
case 'a': System.out.println("Wrong Answer"); break;
}
As other answers have said, you can have only one value in each case statement. Other answers have suggested using two case statements. However, recent versions of Java (since version 13) have an enhanced switch statement which makes it much neater:
switch (choice) {
case 'A', 'a' -> System.out.println("Wrong Answer");
}
See how much neater it is? Not only do you not need two case statements, but you don't need a break statement either.
Other answers have suggested using Character.toLowerCase, but there are problems with that. Consider this:
switch (Character.toLowerCase(choice)) {
case 'i':
System.out.println("Correct answer");
break;
default:
System.out.println("Wrong answer");
break;
}
The problem is Character.toLowerCase is sensitive to the current locale. If a user in Turkey runs the above, and types I, they'll get "Wrong answer" instead of correct answer. This is because in Turkish, the lowercase equivalent of the letter I is not i, but ı (an i without a dot). Similar problems occur with toUpperCase and in some other languages. I wouldn't recommend using toLowerCase/toUpperCase for this reason.

What's a better or more standard way to perform this function?

I am a java beginner, and in this particular problem I practiced making a program that converts any given string to lowercase string. Is there a a better way to achieve this goal in java (in terms of design)?
Also, how does the "else" (after "else if") catches or waits for me to make an input. Somehow that part does not make sense to me, even though I achieved what I wanted. How is the value of "ans" from input transferred to the entire loop and used until the loop is closed?
After many attempts and failures, I used a separate method for the conversion part. My second question is a bit too complicated to be researched.
import static java.lang.System.out;
import java.util.Scanner;
public class MyClass {
public static Scanner s = new Scanner(System.in);
public static String ans;
public static void main(String args[]) {
Conversion();
do {
ans = new String(s.nextLine());
if (ans.equalsIgnoreCase("Y")) {
Conversion();
} else if (ans.equalsIgnoreCase("N")) {
out.println("Thank you for using this program!");
break;
} else {
out.println("Invalid entry!");
out.println("Would you like to convert another string?\n(Please type 'Y' for yes, or 'N' for no.)");
}
} while (ans != "N");
}//END MAIN
public static void Conversion() {
out.println("Please enter string to be converted to lowercase: ");
String str = new String(s.nextLine());
out.println("Your new string is: " + str.toLowerCase());
out.println("Would you like to convert another string? (Y/N)");
}
}
I notice a few issues; Conversion looks like a class-name (Java naming convention would be conversion) and ans != "N" is using == instead of .equals - and wouldn't ignore case (!ans.equalsIgnoreCase("N")). Globals (e.g. static) are bad (pass the Scanner to the methods that need it), and the static import just makes the code more difficult to reason about (in my opinion). Your current loop doesn't really follow a conventional form, I would extract the prompt and loop for "another" conversion to a new method and if you must print a thank you I'd do so after the "main loop". Something like,
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
do {
conversion(sc);
} while (another(sc));
System.out.println("Thank you for using this program!");
}
public static void conversion(Scanner s) {
System.out.println("Please enter string to be converted to lowercase: ");
System.out.printf("Your new string is: %s%n", s.nextLine().toLowerCase());
}
public static boolean another(Scanner s) {
while (true) {
System.out.println("Would you like to convert another string? (Y/N)");
String ans = s.nextLine();
if (ans.equalsIgnoreCase("Y")) {
return true;
} else if (ans.equalsIgnoreCase("N")) {
return false;
}
System.out.println("Invalid entry!");
System.out.println("(Please type 'Y' for yes, or 'N' for no.)");
}
}
Answering your first question:
There are many design patterns and practices so many people can argue what I would recommend you to do. It's basically the same for all programming languages. Let's take your function "Conversion". The name itself says that you use it to convert stuff. Not to display, not to prompt - to convert. In this case, the only actual thing it should do is to convert upperCase to lowercase. In fact, you might want to specify what type of conversion it has in the name of the function (convertToLowerCase?). In fact, in Java, we use lowerCamelCase for all function names and UpperCamelCase for classes.
If you accept my previous suggestion, you could break the Conversion function into multiple ones like promptUserForInput, WrongInputHandler and so forth.
If I understood your second question correctly, you wonder about the way the code executed and how the variable ans is transferred further into the loop. Let's take a look at your code and what variables do:
You initialize your variable in the class MyClass by making it accessible to all methods in the class;
You prompt the user for the input to assign to this variable inside the do..while loop with this line ans = new String(s.nextLine()); which saves the value of the variable and, again, which can be accessed inside the whole class so its value is changed.
It goes into the if..else if...else statement. The way it works, it goes line by line - if the first if-statement fails, it goes on until it finds a truthy statement and it doesn't go any further. In your case, if the ans is not equal to either y/Y/ it will go to else if statement and if it's not n/N, it will go to else (so basically whatever except y/Y/n/N) and will be executed. After that, it jumps into the while (ans!= "N"); line where it compares your class-member variable ans and if it's not equal to "N" it starts over the loop right after the do{ part until you type in the "N".
I hope that makes sense. Whenever the program is asking you for input, it does not execute code further but is stuck until you provide any input. The value from input itself isn't passed throughout the loop and the program. The reason why you can use it because you created a higher-scope variable ans where you saved the result of your input.
IMPORTANT: if you've declared the ans inside the do..while loop, you would've not been able to have accessed it in the while (ans...) because it will 'die' right before the curly brace between do { ...here} while(). If you want to learn more about the scope and variables in general, you can read this article.
Here is my code example:
public static void main(String args[]) {
//declare before entering the loop to have higher scope
String ans = "y";
do {
//we get the given string to convert from the user
String str = promptForString();
//we convert the string
str = converseStringToLowerCase(str);
//display the string (could use another function for that: easier to debug and locate problems and in bigger projects)
out.println("Your new string is: " + str);
//prompt user for respond to continue or not
ans = promptForContinue();
handleResponse(ans);
} while (!ans.equals("n"));
}//END MAIN
//prompts user for an input string
public static String promptForString() {
out.println("Please enter string to be converted to lowercase: ");
String str = new String(s.nextLine());
return str;
}
//converts any given string to lower case
public static String converseStringToLowerCase(String str) {
return str.toLowerCase();
}
//is used to prompt user for reply
public static String promptForContinue() {
out.println("Would you like to convert another string? (Y/N)");
String str = new String(s.nextLine());
//is good to make if...else statements easier - it will always be lower case (or upper if you prefer)
return str.toLowerCase();
}
//easier to locate other response scenarios
public static void handleResponse(String response) {
if (response.equals("n")) {
out.println("Thank you for using this program!");
//it's not a very good practice to innaturally break loops. Use input for that in while(..) statement
// break;
} else if (!response.equals("y")) {
out.println("Invalid entry!");
out.println("Would you like to convert another string?\n(Please type 'Y' for yes, or 'N' for no.)");
}
}

How to check for strictly formatted input?

I am doing a coding project for a basic non recursive, non GUI form of Minesweeper. One of the requirements is that input commands must be strictly formatted like so:
For marking commands (reveal, guess, mark):
["reveal"/"r"] [int] [int]
For help and quit:
just ["help"/"h"] or ["quit"/"q"]
Any inputs outside of these restrictions must be considered ill-formatted. My code for reveal looks something like this:
case "reveal":
case "r":
roundsCompleted ++;
if(input.hasNextInt()){
par1 = input.nextInt();
}
else{
commandIn = null;
}
if(input.hasNextInt()){
par2 = input.nextInt();
correctInput = true;
}
else{
commandIn = null;
}
if(correctInput && isInBounds(par1, par2)){
reveal(par1, par2);
where this is all inside a switch statement of course. The commandIn = null statements are designed to throw the default case which prints "command not recognized". I realize part of my issue here is that these are in two separate if-else statements. Another problem is that input.hasNextInt() doesn't seem to evaluating to false when there is not an int after the first one.
The essence of this problem is in completely restricting these commands to the formats I listed above. Can anyone give me some insight into this issue? Thanks.
I'd use regex to first see if something is either a good input or not just cause it'd be easier
String input = "r 3 4";
if (input.matches("^(help|h|quit|q|((r|reveal) \\d \\d))$"))
//switch case
System.out.println("match");
else
//null string
System.out.println("no match");
then after you've got a match you can use your switch case like what you're doing, if it's a "reveal" or "r", I would just use split() and turn it into an array to get the different x and y coordinates

User input for an if/else statement

its only my second program with java and im running into some issues.
I'm trying to get input from a user, either yes or no, then based on that go to an if else statemene. Heres what I have so far
String answer= UI.askString("Do you want to continue?");
if(answer=="yes"){
UI.println("Lets go");
}
else if(answer == "no"){
UI.println("Thank you. Goodbye");
}
else{
UI.println("Please enter yes or no");
}
Im thinking perhaps its better to use booleans for this?
Any help is gladly appreciated!
(also if you're wondering, its a custom import hence the weird syntax in some lines)
Cheers.
When you compare two Strings in Java with the == operator, they are compared to see if they are the same object, rather than whether they contain the same text. So, you could type "yes", and when you use if (answer == "yes") the comparison fails, because the object you got back from UI.askString is a different object, stored at a different place in memory, than the String the compiler generated from the literal "yes".
To compare the value of the two Strings you need to write answer.equals("yes"), or "yes".equals(answer). Either one will work, and will call the equals method of the String class, which will compare the actual text.
The latter syntax, "yes".equals(answer), is often recommended because it will not cause a NullPointerException, even if the variable answer is set to null. This is because the equals method handles null and simply returns false. If, on the other hand, you used the answer.equals("yes") form, and answer was null, you would be trying to invoke a method on null and an exception would be thrown.
what you are looking for is a dialog box. Here is oracle examples, with code. It is more than I can write here. There are ton of yes, no boxes and detection's of user input with them.
http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
Quick answer:
int dialogResult = JOptionPane.showConfirmDialog (null, "Would You Like to Save your Previous Note First?","Warning",dialogButton);
if(dialogResult == JOptionPane.YES_OPTION){ ... }
Other choices ...
YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION
For a command line program you need...
import java.util.Scanner;
The code will look like ...
Scanner in = new Scanner(System.in);
String line = in.nextLine();
//ask them to write yes, no, whatever
if(line.equal("yes"){ }
else if (line.eqals("no") {}
else {}
using MikeG010590's answer, you can try:
Scanner in = new Scanner(System.in);
String line;
System.out.println("you want to continue?");
Boolean exit = null;
do {
line = in.nextLine();
switch (line) {
case "yes":
exit = false;
break;
case "no":
exit = true;
break;
default:
System.out.println("Please enter yes or no");
break;
}
}
while (exit == null);
System.out.println(exit ? "Thank you. Goodbye" : "Lets go");

How to make a string compare non case sensitive?

I am trying to write a code for one of those programs that responds according to your answers. I want to make it so that some of the variables are not case sensitive. For example if my variable x is equal to "Me" I want it to also equal "me". Is that possible?
Here is my code so far:
import java.util.Scanner;
class Tutorial {
public static void main (String args[]){
System.out.println("Who goes there?");
Scanner N = new Scanner(System.in);
String name = N.next();
if (name.equals("me") || name.equals("Me")){
System.out.println("Well, good for you smartass.");
System.exit(1);
}else System.out.printf("Nice to meet you, %s.%n", name);
System.out.print("How are you doing?");
Scanner d1 = new Scanner(System.in);
String doing = d1.next();
switch(doing){
case "good": System.out.println("that is nice to hear.");
case "Well": System.out.println("that is nice to hear.");
case "bad" : System.out.println("That's ruff mate.");
case "Awesome" : System.out.println("Nice");
case "Terrible" : System.out.println("Sucks for you");
}
}
}
I don't want to have to make 2 cases for each answer where one is uppercase and the other is lower case.
Slightly off topic question. How do I close the resource leaks for the scanner?
Worth mentioning String#toLowerCase:
name.toLowerCase().equals("me");
Or simply use String#equalsIgnoreCase:
name.equalsIgnoreCase("me");
I think there is no way to do no case sensitive variable. From your code you want to threat answers in strings into a switch and do some action that depends on answer.
I think the best way is to take user input a use on that string upper method from string class.
YourString = YourString.toUpperCase();

Categories

Resources