class test {
public static void main(String args[])
throws java.io.IOException {
char ch, answer = 'K';
System.out.println("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it: ");
ch = (char) System.in.read();
if(ch == answer) {
System.out.println(" *** YOU ARE RIGHT *** ");
else System.out.println("Please try again: ");
ch = (char) System.in.read();
}
}
}
I'm using command line to run this java program and I want the user to continuously be able to input something instead of having to run the program manually every time they guess it wrongly. Tried many ways but the second System.in.read() doesn't show a prompt instead the code just ends in terminal having to manually run the program again to play. I'm a beginner so I have trouble understanding.
For one, as #GhostCat mentioned, you should put brackets around your if and else cases, otherwise the second read will happen regardless of the if statement
if (ch == answer) {
// your if code here
else {
// your else code here
}
Second, if you want it run indefinitely until they give a right answer, you need some kind of loop. In this case, you probably want a while loop. This would replace the if statement
while (ch != answer) {
// ask for retry
}
// They were right!
The code after the closing bracket will only run once the condition of the while loop is false (in this case, when ch is equal to answer). Meaning, at this point you can handle the correct answer case. Meanwhile, if they input the wrong answer, the program will loop and they will be prompted to try again.
EDIT: As to why the original code wasn't waiting for a second input and just stopping, inputting the first character in the command line actually adds an extra carriage return/new line character to the end of input, so the second read immediately consumes this new line character and proceeds (which in the initial code there's nothing else to do, so it quits).
This will work:
import java.util.Scanner;
class test {
public static void main(String args[]) throws java.io.IOException {
char ch, answer = 'K';
Scanner s = new Scanner(System.in);
System.out.println("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it: ");
ch = s.next().charAt(0);
if(ch == answer){
System.out.println(" *** YOU ARE RIGHT *** ");
} else{
System.out.println("Please try again: ");
ch = s.next().charAt(0);
}
}
}
if(ch == answer)
System.out.println(" *** YOU ARE RIGHT *** ");
else System.out.println("Please try again: ");
ch = (char) System.in.read();
is the equivalent of
if(ch == answer) {}
System.out.println(" *** YOU ARE RIGHT *** ");
} else {
System.out.println("Please try again: ");
}
ch = (char) System.in.read();
Indentation has no effect semantically nor syntactically. It's just a convention but it has no effect on your program (in contrast to python).
You should loop the program:
while(ch != answer) {
ch = (char) System.in.read();
....
}
However, this lacks EOF handling. It's better to use something like this:
while(true) {
int ch = System.in.read();
if(ch < 0) {
System.out.println("Bye!");
}
if((char)ch == answer) {
System.out.println("YOU ARE RIGHT");
break;
}
System.out.println("Please try again: ");
}
Also, bear in mind that read() reads only one byte which depending on how you input the data can be confusing because terminals usually buffer input until you press enter... not all terminals do this but most do it. You might be better of with using System.console which provides a readLine method. However, System.console won't work if no console is attached to stdin (such as when piping input to stdin, but for your case that's not a problem because I don't think your program is intended to be used through pipes). You can use System.console.readLine() and then strip away unwanted characters using the trim method of String.
Related
I fail to understand why For loop keeps executing, if condition meet and break statement applied.
Code:
class ProgramControlStatements {
public static void main(String[] args) throws java.io.IOException {
System.out.println("Menu: ");
System.out.println("Choice: ");
System.out.println("1: If/Else");
System.out.println("2: Switch");
for(int i = 0; i < 5; i++) {
chooseOption();
};
};
static void chooseOption() throws java.io.IOException{
char choice = (char) System.in.read();
switch(choice){
case 'a':
System.out.println("Computer control statement: If/Else");
break;
case 'b':
System.out.println("Computer control statement: Switch");
break;
default:
System.out.println("No valid option");
};
}
}
Expected result:
If char a chosen, print "If/Else" and expect next input until i<5
Computer control statement: If/Else
Actual result:
First Input -> a
Computer control statement: If/Else
No valid option
Second input -> b
Computer control statement: Switch
No valid option
Third input -> a
Computer control statement: If/Else
Program ends.
I expect default statement to be skipped since break statement is applied.
Is this happening as System.in.read() returns a new line?
I think same behaviour is to be expected from while; do-while loops?
It's not as easy as #Arvind Kumar Avinash says, depending on your OS you may encounter either a \r (carriage return), \n (new line) or both \r\n after every line.
So just adding another System.in.read() line is a workaround that may not always work.
I suggest using Scanner instead, as suggested here: Take a char input from the Scanner.
LE: As an answer to a request in the comment, I would like to specify that I always try to use Scanner when I want to parse my input and don't mind the performance. When I mind performance, I use BufferedReader. Never System.in directly. You can read more in the answers provided here https://stackoverflow.com/a/21698084/2477456.
I believe the answer is a combination between the 2 answers offered so far.
For a quick fix, #Arvind Kumar Avinash is very good.
Looking more in to the problem as #Valdrinium specifies alternatives might be considered.
I am sceptical on choosing #Arvind Kumar Avinash as definitive, although it solve the problem in this instance.
Can an admin help?
It's happening because of the dangling line break character. Just add System.in.read(); once again as shown below to consume dangling line break character e.g. (char) System.in.read() consumes just a but not the Enter character that you press after a.
public class Main {
public static void main(String[] args) throws java.io.IOException {
System.out.println("Menu: ");
System.out.println("Choice: ");
System.out.println("1: If/Else");
System.out.println("2: Switch");
for (int i = 0; i < 5; i++) {
chooseOption();
}
}
static void chooseOption() throws java.io.IOException {
char choice = (char) System.in.read();
System.in.read();// Add this line
switch (choice) {
case 'a':
System.out.println("Computer control statement: If/Else");
break;
case 'b':
System.out.println("Computer control statement: Switch");
break;
default:
System.out.println("No valid option");
}
}
}
A sample run:
Menu:
Choice:
1: If/Else
2: Switch
a
Computer control statement: If/Else
b
Computer control statement: Switch
a
Computer control statement: If/Else
b
Computer control statement: Switch
a
Computer control statement: If/Else
For example, like this.
while ((input = kb.nextInt()) != 0) {
if (input % 2 == 0) {
System.out.println("even");
} else {
System.out.println("odd");
}
instead of only checking the value of the input variable inside the condition and getting the number from Scanner inside the loop, like so:
while (input != 0) {
input = kb.nextInt();
...code here...
Just wondering if the first one is bad practice or anything like that.
Using nextInt() as part of a loop condition, while perfectly legal, can be problematic from the standpoint of dealing with errors arising from bad input. Actual humans sitting in front of a keyboard entering data (which the Scanner variable name kb seems to suggest is exactly what you're dealing with here) are notoriously unreliable in terms of their data entry quality, so bad input is something you should be prepared for.
nextInt() will throw an InputMismatchException exception if the next available input is not a valid representation of an integer. In order to catch and handle this exception, the nextInt() call must be executed inside of a try block. However, with the nextInt() being part of the control condition of the while loop, the only way to do that is to enclose the entire loop in the try block:
try {
while ((input = kb.nextInt()) != 0){
...
}
} catch (InputMismatchException ime){
...
}
Unfortunately, this means that any exception raised by nextInt() will kill the while loop. If you wanted to keep processing user inputs after an input error, you'd have to provide a means of starting the while loop over again, and keep starting it over until the "real" user-signaled end-of-input condition had been reached. You might be able to do it with a clunky workaround like this one:
boolean keepGoing = true;
while (keepGoing){
try {
while ((input = kb.nextInt()) != 0) {
...
}
keepGoing = false;
} catch (InputMismatchException ime) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
}
}
But depending on what the ... code inside the loop was doing, this relatively simple workaround might be inadequate; you might need something even more complicated and unreadable.
But by moving the nextInt() call out of the control logic of the loop and into the loop body, you gain considerable flexibility in terms of your options for recovery from bad input. With nextInt() inside the loop body, you can now catch and handle any exception entirely within one iteration of the loop, without having to terminate the loop itself:
do {
try {
input = kb.next();
if (input != 0) {
...
}
} catch (InputMismatchedException ime) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
}
} while (input != 0);
You'd also have the option of avoiding an exception altogether by using hasNextInt() to ensure that a valid input is present before trying to read it with nextInt():
for(;;) {
if (!kb.hasNextInt()) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
} else {
input = kb.nextInt();
if (input == 0) {
break;
else {
...
}
}
}
The second one doesn't have the input defined for testing the condition input!=0 hence the first one is right but if you're going to use the second format I'd suggest to change the while loop to do-while loop.
Your two code samples are not equivalent and do different things (the second version probably doing not what you want it to do).
You would need another if (input != 0) inside the loop and assignment of input before the loop for the second version. Moving the assignment to the end and duplicating it before the loop is also a viable option:
input = kb.nextInt();
while (input != 0) {
if (input % 2 == 0) {
System.out.println("even");
} else {
System.out.println("odd");
}
input = kb.nextInt();
}
And the duplicated first and last line in this version is very likely the reason for the somewhat complicated code. This type of loop loop ((x = input()) != 0) can be seen in a lot of C code but is sometimes "required" in Java too when you want to reduce code-duplication when processing input. This is caused by the fact that nextInt returns a value and mutates the underlying state.
I am just polishing my java skills and I wrote out this code to play around with keyboard input and do while loops.
package Chapter3;
import java.io.IOException;
public class convertCase {
public static void main(String args[]) throws IOException {
char ch = 'a';
do {
System.out.println("please type in a value: ");
ch = (char) System.in.read();
if((int) ch < 96) {
ch += 32;
int newCh = (int) ch;
System.out.println("The lowercase version is: " + (char)newCh);
}
else if((int) ch >96) {
System.out.println("You have typed in" + ch);
ch -= 32;
int newCh = (int) ch;
System.out.println("the uppercase version is: " + (char)newCh);
}
} while(ch!='.');
}
}
Problem is that when I test it the 'while loop' runs twice before asking for input instead of just the once:
please type in a value:
a
You have typed ina
the uppercase version is: A
please type in a value:
The lowercase version is: *
please type in a value:
L
The lowercase version is: l
please type in a value:
The lowercase version is: *
please type in a value:
Can someone bring clarity to this situation??
That's because
System.in.read();
takes in every key pressed. that is, in your case, the 'a' key, and the 'return' key.
If you want your functionality then use the following:
Scanner scanner = new Scanner(System.in);
And then use:
String line =(char)scanner.nextLine();
and then parse the value.
It is looping twice because it is processing the newline that follows each character.
You are processing the newline character as if it is legitimate input. You should either read the entire line (including the newline, perhaps using a Scanner) and then process the first character of the line or simply add a test to skip newlines in your loop logic.
P.S. Converting case by adding or subtracting 32 is a really awful approach. It won't work with anything but a-z and A-Z (in the English alphabet). It won't work for most characters outside the Basic Latin block and shouldn't be used at all for characters that have no alternate case (such as newline). You should be using Character.toUpperCase() and Character.toLowerCase() instead.
Answer taken from Book "Java: A Beginner's Guide"
The answers mentioned above are right as well. Just for more clarification, I will post this.
do {
System.out.print("Pres a key followed by Enter: ");
//get a char
ch = (char) System.in.read();
//REFERRING TO THIS PART
do{
ignoreNewLineENTER = (char) System.in.read();
}
while (ignoreNewLineENTER != '\n');
} while (ch != 'q');
console input is line buffered—you have to press ENTER before characters are sent. Pressing ENTER causes a carriage return and a line feed (newline) sequence to be generated. These characters are left pending in the input buffer. Also, if you typed more than one key before pressing ENTER, they too would still be in the input buffer. This loop discards those characters by continuing to read input until the end of the line is reached. If they were not discarded, then those characters would also be sent to the program as guesses, which is not what is wanted. (To see the effect of this, you might try removing the inner do-while loop.) In Chapter 10, after you have learned more about Java, some other, higher-level ways of handling console input are described. However, the use of read( ) here gives you insight into how the foundation of Java's I/O system operates. It also shows another example of Java's loops in action.
first sorry if the title isn't clear enough but English isn't my main language so it's a bit hard to explain myself.
I made a simple program that requires you to press Enter so it continues with the code, in my case count to 60 second then wait for another Enter, the problem is that sometimes it bugs and continues as if you had pressed Enter when you didn't (might be because accidentally there is another character pressed before Enter key).
Here is the fragment of code, I used System.in.read() because I read here that it was a good option for what I was looking to do, but I was more experienced with Scanner.
public static void cuentaSeries(int n) throws Exception {
System.out.println("------------------------------");
int aux = 1;
while(aux<=n) {
System.out.print("Serie Nº" +aux +" []");
System.in.read();
System.out.println("Serie Nº" +aux +" [X]");
cuenta();
aux++;
}
System.out.println("------------------------------");
}
public static void cuenta() throws Exception {
int contador = 0;
System.out.print("0 ");
while(contador<60) {
Thread.sleep(1000);
contador++;
if(contador%5==0) System.out.print(contador +" ");
if(contador==60) System.out.println("");
}
}
Thanks.
The problem comes from the line:
System.in.read();
See the documentation that says:
Reads the next byte of data from the input stream. The value byte is
returned as an int in the range 0 to 255.
You are not checking for the enter key but for any single character. Consider if you got the input 'hello'. The System.in.read() will first read 'h', then 'l', etc. To solve this you need to switch to using nextLine().
Try this:
Scanner scan = new Scanner(System.in);
int aux = 1;
while(aux<=n) {
System.out.print("Serie Nº" +aux +" []");
scan.nextLine();
System.out.println("Serie Nº" +aux +" [X]");
cuenta();
aux++;
}
with
import java.util.Scanner
Sorry if the title made no sense but I did not know how to word it.
The problem:
I'm making a multiple choice quiz game that gets either a, b, c or d from the user. This is no problem if they do as they are told, however if they don't type anything and just hit enter I get a StringIndexOutOfBoundsException. I understand why this is happening, but I'm new to Java and can't think of a way to fix it.
What I have so far:
System.out.println("Enter the Answer.");
response = input.nextLine().charAt(0);
if(response == 'a')
{
System.out.println("Correct");
}
else if(response == 'b' || response == 'c' || response == 'd')
{
System.out.println("Wrong");
}
else
{
System.out.println("Invalid");
}
Of course the program will never make it past the second line of code if the user types nothing, because you can't take the charAt(0) value of an empty String. What I'm looking for is something that will check if the response is null, and if so ask go back and ask the question to the user again.
Thanks in advance for any answers.
You can use a do-while loop. Just replace
response = input.nextLine().charAt(0);
with
String line;
do {
line = input.nextLine();
} while (line.length() < 1);
response = line.charAt(0);
This will continue to call input.nextLine() as many times as the user enters a blank line, but as soon as they enter a non-blank line it will continue and set response equal to the first character of that non-blank line. If you want to re-prompt the user for the answer, then you could add the prompt to the inside of the loop. If you want to check that the user entered a letter a–d you could also add that logic to the loop condition.
Either handle the exception(StringIndexOutOfBoundsException) or break this statement
response = input.nextLine().charAt(0);
as
String line = input.nextLine();
if(line.length()>0){
response = line.charAt(0);
}
Exception Handling:
try{
response = input.nextLine().charAt(0);
}catch(StringIndexOutOfBoundsException siobe){
System.out.println("invalid input");
}
Simple:
Get the input initially as a String, and put it into a temporary String variable.
Then check the String's length.
then if > 0 extract the first char and use it.
In addition #HovercraftFullOfEels' (perfectly valid) answer, I'd like to point out that you can "catch" these exceptions. For example:
try {
response = input.nextLine().charAt(0);
} catch (StringIndexOutOfBoundsException e) {
System.out.println("You didn't enter a valid input!");
// or do anything else to hander invalid input
}
i.e. if a StringIndexOutOfBoundsException is encountered when executing the try-block, the code in the catch-block will be executed. You can read more about catching and handling exceptions here.
StringIndexOutofBoundException will occur in the following situation also.
Searching a string which is not available
Match with the string which is not available
for ex:
List ans=new ArrayList();
temp="and";
String arr[]={"android","jellybean","kitkat","ax"};
for(int index=0;index < arr.length;index++ )
if(temp.length()<=arr[index].length())
if(temp.equlsIgnoreCase((String)arr[``index].subSequence(0,temp.length())));
ans.add(arr[index]);
the following code is required to avoid indexoutofboundexception
if(temp.length()<=arr[index].length())
because here we are cheking the length of src string is equal or greater than temp .
if the src string length is less than it will through "arrayindexoutof boundexception"