Console input and ENTER key with Java - java

I'm learning Java with the book: Java. A begginer's guide.
The book shows the following example:
// Guess the letter game, 4th version.
class Guess4 {
public static void main (String args[])
throws java.io.IOException {
char ch, ignore, answer = 'K';
do {
System.out.println ("I'm thinking of a letter between A and Z.");
System.out.print ("Can you guess it: ");
// read a character
ch = (char) System.in.read();
// discard any characters in the input buffer
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
if ( ch == answer) System.out.println ("** Right **");
else {
System.out.print ("...Sorry, you're ");
if (ch < answer) System.out.println ("too low");
else System.out.println ("too high");
System.out.println ("Try again!\n");
}
} while (answer != ch);
}
}
Here is a sample run:
I'm thinking of a letter between A and Z.
Can you guess it: a
...Sorry, you're too high
Try again!
I'm thinking of a letter between A and Z.
Can you guess it: europa
...Sorry, you're too high
Try again!
I'm thinking of a letter between A and Z.
Can you guess it: J
...Sorry, you're too low
Try again!
I'm thinking of a letter between A and Z.
Can you guess it:
I think the output of the program should be:
I'm thinking of a letter between A and Z.
Can you guess it: a...Sorry, you're too high
Try again!
Without a \n between 'a' and '...Sorry, you are too high'. I don't know why apears a new line. The do-while erases it.
Thank you.

ch = (char) System.in.read();
actually reads a single character.
if the input is - a\n only the first character is read and stored in ch. which is a in this case.
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
This is used to remove any unwanted characters.
Why did they use this?
We just need a single letter.
So if the user had given an input which is not a single character, like "example" and if your code didn't have the loop check.
First the ch becomes e, then x ....so on.
Even without the user entering a alphabet the previous input is considered to be entered.
what if only Enter(\n) was pressed
As even \n is considered a character it is also read. In the comparison the ASCII value of it is considered.
Have a look at this question. In which a user didn't check for the unnecessary characters and got an unexpected output.

Instead doing stuff char-by-char, you could easily utilize a Scanner:
replace
// read a character
ch = (char) System.in.read();
// discard any characters in the input buffer
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
with
Scanner in = new Scanner(System.in); //outside your loop
while(true) {
String input = in.nextLine();
if(!input.isEmpty()) {
ch = input.charAt(0);
break;
}
}

Related

How do I prevent an error message from repeating in Java?

I'm trying to write a program to calculate factorial but I can't figure out why the Error message displays twice if I enter a letter instead of an integer.
I feel like the issue has to do with Line 29 c = sc.next().charAt(0);, but am not sure how to fix it. Any help is appreciated.
My program:
public class Factorials {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char c = 'Y';
int num = 0;
do
{
System.out.print("Enter a number to calculate its factorial: ");
while (!sc.hasNextInt()) {
System.out.println("Invalid Entry - Enter only Integers! Try Again: ");
sc.nextLine();
}
int result = 1;
num = sc.nextInt();
for(int i = 1; i <= num; i++) {
result = result * i;
}
System.out.println("The factorial of " + num + " is: " + result);
System.out.println("Do you wish to continue? Y/N: ");
c = sc.next().charAt(0);
}while(c == 'y' || c == 'Y');
sc.close();
}
}
Simple fix: Change the sc.nextLine(); in your code to a sc.next() and you should be good to go. This error occurs because .nextLine() considers the enter/return key as a separate character, while .next() doesn't. (The enter key when you press it after entering either 'y' or 'n': if you try it, the error message doesn't print twice if you enter a letter the first time you run the program).
Side note: You probably want it to be a .print(/*invalid input sentence*/) instead of a .println() to go along with how you take in your other number values.
Otherwise, you're good!
Finds and returns the next complete token from this scanner.
A complete token is preceded and followed by input that matches
the delimiter pattern
As jdk doc shows, the 'sc.next' method will return when it reaches space, enter or return. So when you enter 'y' with enter, the enter character is still in buffer. You can assign sc.nextLine to a variable, like
String str = sc.nextLine();
System.out.println(str);
You can see the enter character and your input character.
Both #TheSj and #Lahiru Danushka answer could solve this problem.
add sc.nextLine(); after c = sc.next().charAt(0);

Java: how to exclude carriage return/ line feed from System.in.read

I am very new to this and working through a tutorial but wanted to fancy it up with a while loop so that the program repeats until "K" is entered by the user.
Unfortunately, this seems to read the carriage return and line feed when the incorrect char is entered. This means that "WRONG" is output three times instead of once.
Is there any way to exclude these so that only the Character is read? Thanks in advance
class Guess{
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(); //read a char from the keyboard
while (ch != answer) {
System.out.println("**WRONG**");
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(); //read a char from the keyboard
if (ch == answer) System.out.println("**Right**");
}
}
}
I would recommend using Scanner and read the line when user hits return as read considers return as another character, e.g.:
char answer ='K';
Scanner scanner = new Scanner(System.in);
System.out.println("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it:");
String ch = scanner.nextLine(); //read a char from the keyboard
while (ch.length() > 0 && ch.charAt(0) != answer) {
System.out.println("**WRONG**");
System.out.println ("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it:");
ch = scanner.nextLine();//read a char from the keyboard
}
System.out.println("**Right**");
scanner.close();
It's just the statments order.
Try this
public class Guess {
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(); //read a char from the keyboard
while (ch != answer) {
ch = (char) System.in.read(); //read a char from the keyboard
if (ch == answer) {
System.out.println("**Right**");
break;
}else{
System.out.println("**WRONG**");
}
System.out.println("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it:");
}
}
}

carriage return / line feed removal with do-while loop

Yo guys,
I used google and this website, but could not find an in depth explanation of a little part in the following code:
// Guess the letter game, 4th version.
class Guess4 {
public static void main(String args[])
throws java.io.IOException {
char ch, answer = 'K';
do {
System.out.println("I'm thinking of a letter between A and Z.");
System.out.print("Can you guess it: ");
// read a letter, but skip cr/lf
do {
ch = (char) System.in.read(); // get a char
} while(ch == '\n' | ch == '\r');
if(ch == answer) System.out.println("** Right **");
else {
System.out.print("...Sorry, you're ");
if(ch < answer) System.out.println("too low");
else System.out.println("too high");
System.out.println("Try again!\n");
}
} while(answer != ch);
}
}
So my question is about this part:
do {ch = (char) System.in.read();
} while(ch == '\n' | ch == '\r');
Can somebody explain in depth how this works? I know that it's reading a character from the keyboard first, because a do-while loop runs at least one time. The | means that both of them have to be false in order to let the do-while loop stops. In which order this works? So when i am pressing a letter, it first gets a carriage return and line feed, both true, so it runs the system.in.read again, but then it runs twice and it also has my letter already, so when system.in.read runs again because of the loop, it produces again a carriage return and line feed, or not? So in my mind it becomes an infinite loop, but it is not. I tried running the program without this and when i press a letter it prints the two questions, two times. Why? I am a little confused about how this loop and removal of this cr/nl works. Thanks for the help.
ch = (char)System.in.read(); reads a new char into ch in each iteration of the loop. The loop continues as long as the input character is either a new line (\n) or a line feed (\r). Any other input ends the loop.

Trouble with "do while"

this program expects a capital letter from user input. The input is saved in char variable c, after that converted to ascii, and then checked, if it really is a capital letter. When not, program should ask again. Problem ist, that command System.out.println("Write capital letter: ") is executed multiple times and it looks like that:
Write capital letter:
Write capital letter:
Write capital letter:
Write capital letter:
Write capital letter:
I want to have only one "Write capital letter: " on screen after every wrong input, and it needs to eb done with ascii table.
Thanks in advance.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int ascii;
char c;
do {
System.out.println("Write capital letter: ");
c = (char) System.in.read();
ascii = (int) c;
} while (ascii < 65 || ascii > 90 );
System.out.println("Write capital letter: ");
do {
c = (char) System.in.read();
// ascii = (int) c; // not needed if you are using the isUppercase() method
if(! Character.isUppercase(c)){
System.out.println("Write capital letter: ");
}
} while (! Character.isUppercase(c) );
As long as the condition is true, whatever is defined in the do block is executed. So, move the statements you want to execute only once out of the do block.
Why are you using System.in.read() when you have a BufferedReader variable set?
This will solve your issue. I am using your BufferedReader in variable.
while (true) {
System.out.println("Write capital letter: ");
int b = 0
while ((b = in.read()) != -1){
char c = (char) c;
if (Character.isUpperCase(c)) break;
}
//Carry on...
}

simple java program not working -- while-loop

So I'm fairly new to programming, and I'm working on a simple practice program that finds a letters order in the alphabet. This should have been pretty easy...but for some reason I get a StringIndexOutOfBoundsException when I add a while loop. So the program does do what it should the first time...but will not allow me to test again with out re-running the program. I tested the while loop with nothing but a simple print statement inside and it worked, so I'm confused as to why the while loop isn't working with my alphabet program.
Any help would be greatly appreciated
thanks!
import java.io.*;
public class test {
public static void main(String[] args) throws IOException
{
BufferedReader in;
in = new BufferedReader (new InputStreamReader (System.in));
boolean again=true;
String response;
while (again)
{
System.out.println("Enter a letter to find it's order in the alphabet");
char theLetter = (char) in.read();
System.out.println(theLetter + " is the " + convertLetter(theLetter) + "th letter of the alphabet");
System.out.println("want to play again?");
response = in.readLine();
if (response.charAt(0)=='n')
{
again=false;
}
}
System.out.println("end program");
}
public static int convertLetter(char TheLetter)
{
//number value 'a'=97
//number value 'b'=98
//number value 'c'=99
//subtracting 'a' from any other number will reveal how many places away that number is from the start
//thus finding it's chronological place in the alphabet
int NumberValue= (int)TheLetter;
int a = 'a';
int CalulateOrder = (NumberValue - a) + 1;
return CalulateOrder;
}
}
When you hit enter for the original char, that newline is still in the buffer since you only call read() and only get 1 character, leaving the newline in the buffer from hitting enter. So when you call readLine it simply hits that newline and returns an empty string.
You can test this by typing something with more than one character when it first asks you for a character, and it will go for a second loop since the readLine will return a non-empty string.
To fix this change your original read() to readLine() so that it gets the newline caused from you hitting enter, then just grab the first character from the string.
This should fix it:
import java.io.*;
public class test {
public static void main(String[] args) throws IOException {
BufferedReader in;
in = new BufferedReader (new InputStreamReader (System.in));
boolean again=true;
String response;
while (again) {
System.out.println("Enter a letter to find it's order in the alphabet");
response = in.readLine();
if (response.length() > 0) {
char theLetter = response.charAt(0);
System.out.println(theLetter + " is the " + convertLetter(theLetter) + "th letter of the alphabet");
System.out.println("want to play again?");
response = in.readLine();
if (response.length() > 0 && response.charAt(0)=='n') {
again=false;
}
}
}
System.out.println("end program");
}
public static int convertLetter(char TheLetter) {
return (TheLetter - 'a') + 1;
}
}
if (response.charAt(0)=='n')
If the String is empty "", there will be no character at position 0. Check for it before doing charAt()
is the length of response null or ""? if it is you will not be able to get the char at index 0
I bet the culprit is that you're hitting "enter" at the want to play again? prompt. The in.readLine(); returns the line without the trailing newline (see the javadocs), which means that if you only press "enter" it will return an empty string, thus the StringOutOfBoundException while checking the first char.
Check for the empty string before checking for the char:
if(response.length() > 0 && response.charAt(0) == 'n')
The only place you access a string index is at if (response.charAt(0) == 'n') so that is most likely your problem area.
if(response.length() > 0 && response.charAt(0) == 'n')
Should do the trick.
Edit:
As #TreySchroeder points out, there is another problem with your program, in that you don't read the full line at first. Put in.readLine(); after your initial theLetter = (char) in.read();, and use this fix for the other issue.
if (response.isEmpty() && response.charAt(0)=='n')
will avoid the exception.

Categories

Resources