Why does the string inside println method show twice? - java

In the following code why does the string inside println method shows twice.What should I do to show the message once per iteration
package practicejava;
public class Query {
public static void main(String[] args) throws java.io.IOException {
System.out.println("Guess a capital letter Character");
while ((char) System.in.read() != 'S') {
System.out.println("wrong.guess again to finish the program");
}
}
}

When a user writes in console characters, to confirm fact that his input is ready to be passed to application he presses enter key. But console doesn't pass only provided characters, it also adds to input stream (System.in) OS dependent line separator character(s) after it. Some OS use \r or \n (those are single characters, \x is just notation to represent them) others like Windows use \r\n (two characters) sequence as line separator.
Now those additional characters are also read by System.in.read() and since they are not equal to S System.out.println("wrong.guess again to finish the program"); is executed additional time.
To avoid such problems instead of working with raw data via System.in.read() consider using classes meant to make our life easier like java.util.Scanner
Scanner sc = new Scanner(System.in);
System.out.println("Guess a capital letter Character");
String response = sc.nextLine();
while(!response.equals("S")){
System.out.print("incorrect data, please try again: ");
response = sc.nextLine();
}

Its because the first char that you read is the letter you typed, and then there is a second loop where the character is the line return.
For example on my linux machine, if I input "E" and then press enter, the first loop processes the char 69 'E', and then there is a second loop to process the carriage return (char 10).

What you can do is use a Scanner to get the user's input:
package practicejava;
import java.util.Scanner;
public class Query {
public static void main(String[] args) throws java.io.IOException {
Scanner s = new Scanner(System.in);
char c;
do {
System.out.println("Guess a capital letter Character");
c = s.next().charAt(0);
if (c != 's') {
System.out.println("Wrong! Guess again to finish the program.");
}
} while(c != 's');
}
}
s.next() will get the input from the user as a string and s.next().charAt(0) will return the first character in that string.

Related

Why empty lines are being printed at the when I use BufferedReader to read characters from the console and print them?

Here is my program.
// Here we use a BufferredReader to read characters from console.
package fileIO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BRRead {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char ch;
System.out.println("Enter characters, 'q' to quit.");
do {
ch = (char)br.read();
System.out.println(ch);
} while(ch!='q');
}
}
Input 1: testq
Output:
t
e
s
t
q
Input 2: test
Output:
t
e
s
t
""
""
""
""
where "" means empty line.
My question is why 4 empty lines are printed for the case when the input characters doesn't contain letter 'q' but aren't printed when the input characters contain letter 'q'?
Complete-er answer at the bottom
Haven't run it at all to check, though it seems like it could have something to do with the use of a do-while loop instead of a while loop
This format will make sure that the character 'q' is not read before it attempts to output anything
while(ch!='q')
{
System.out.println(ch);
ch = (char)br.read();
}
And this format prints the read character before testing if it is valid
do {
ch = (char)br.read();
System.out.println(ch);
} while(ch!='q');
EDIT after some trial/error
With this version, I have used the Scanner class which is quite similar, and I am more familiar with it. It may go something like so:
Create Object(s) for reading the data BufferedReader,Scanner,etc.
Check if there is content present
Accept the data as a String and read the first character
Output if the String is is not q
Cycle the test-> read -> print -> loop, till q is entered
Scanner input = new Scanner(System.in);
System.out.println("Enter characters, 'q' to quit.");
String read = input.nextLine();
while(read.length() <= 1 && read.charAt(0) != 'q')
{
System.out.print(read);
read = input.nextLine();
}
The (almost) original method*
Eureaka!
name.read() Reads a single character --
However, this returns an int datatype which cannot be converted with the (char) mask.
name.readLine() Reads a line of text -- With this, you can simply take the character at index 0
https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html
do {
full = br.readLine();
System.out.print(full);
} while(full.length() <= 1) && full.charAt(0) != 'q');
Not sure what the best way to do it would be between a do-while and a while loop, and that may ultimately come down to use case and opinion. and you may want to make a boolean method too
// true if String matches 'q' or "quit"
public static boolean isQuit(input)
{
String lowercase = input.toLower();
char start = input.charAt(0);
return (lowercase.equals("quit")
|| (input.length() <= 1 && start == 'q'));
}

Printing a message if a char has more than one symbol(using char, not String)

Basically I need to write this message:
System.out.println("Invalid grade - must enter exactly one letter");
And I don't know how to write an (if,for,while loop) which will find if letterGrade is bigger than one character, it has to be only one character if > 1 character it should follow this message.
And problem is that I know how to do it with string.length() but this is char and it doesn't work.
I tried this:
while(String.valueOf(letterGrade).length() > 1)
{
System.out.println("Invalid grade - must enter exactly one letter");
System.out.print("Enter grade (one character): ");
letterGrade = in.next().charAt(0);
}
But it doesn't print me message that I want, is there some method that finds char greater than one character? Can charAt() help me ?
I would propose to use regular expression since you might want to only allow letters a-f/A-F.
The expression to use would be
[a-fA-F]
The Java code used to check this would be:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("Type");
Scanner reader = null;
try {
// Read from System.in
reader = new Scanner(System.in);
// Only work with first character
char c = reader.findInLine(".").charAt(0);
// ""+c creates a string since RegEx only works on strings
String testString = ""+c;
// Test string
if(!(""+c).matches("[a-fA-F]")) {
System.out.println("Invalid input");
return;
}
// c has a valid grade
System.out.println("Valid input");
}
catch(Exception ex) {
if(reader != null)
reader.close();
}
}
}
Test results:
a > Valid input
z > Invalid input
az > Valid input
za > Invalid input
You may use System.in.read(); if you want to read only one charactor.
So you should probably be a little more clear with your question and not in a paragraph form with the entire block of code including variable declaration and user inputlines.
In java, a char can only be one character (i am sure you know this) and so having multiple would mean that it is a string.
Assuming that you are working with letterGrade as an input from the user using Scanner, the way to check if the input is one character or not and do something in response will be
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
if(input.length==1)
{sysout("There is only 1 character in the input");
char value = input.indexOf(0);
}else
{sysout("Invalid grade");
}

The second do while loop in this code. I need somebody to explain what it is actually doing in more simple terms

The second do while loop in this code:
do {
ignore = (char) System.in.read();
} while(ignore != '\n');
I cannot comprehend what it actually does. All I understand is that when I take it out and run the program and guess an incorrect letter, program will print out 3 lines of the text "Guess letter now". Why does it do that 3 times without that code in place. What does that code even do? So I am confused and just cannot work it out.
public class GuessChar {
public static void main(String args[])
throws java.io.IOException {
char ch ,ignore, answer = 'k';
do {
System.out.println("Guess the letter now");
ch = (char) System.in.read();
do {
ignore = (char) System.in.read();
} while(ignore != '\n');
if(ch == answer) System.out.println("WELL DONE");
} while(ch != answer);
}
}
First look at the most confusing part:
char ignore;
do {
ignore = (char) System.in.read(); // (1)
} while (ignore != '\n'); // (2)
The do loop is entered unconditionally, so the line marked (1) is always executed. What it does is reading a single character from the standard input stream and assign the 16 least significant bits (thanks to the typecast) to the variable ignore. It is confusing letters in Java are actually of type int but as long as you are only dealing with simple-enough letters (eg symbols from the ASCII character set) they are the same.
The line marked (2) checks whether the just-read character is different from the newline character \n. If so, it will re-enter the loop and break it otherwise.
In combination, this discards any input up to and including the next newline character (ie the end of the current line).
Before that loop, you are also reading in a single character and store it away in the variable ch.
char ch = (char) System.in.read();
After the loop has discarded any remaining characters on the line, you test whether ch (that is, the first character that was on the line) is equal to answer and, if so, exit or otherwise start anew.
In conclusion, the program reads, line-by-line, input from the user (prompting for each line) until the user enters something that starts with the letter k.
Now we have clarified what the program does, let's see how we can improve it. It turns out that reading one character at a time is very inefficient and there are already methods in the standard library that will do a better job. Using them and more expressive variable names, the intent of the program becomes much clearer.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GuessChar {
public static void main(String[] args) throws IOException {
char expected = 'k';
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Guess the letter now.");
while (true) {
String line = stdin.readLine();
if (line == null) { // end of input
System.out.println("Giving up, eh?");
break;
} else if (line.isEmpty()) {
System.out.println("Sorry, that was no input at all.");
} else if (line.charAt(0) == expected) {
System.out.println("Well done!");
break;
} else {
System.out.println("Sorry, please try again.");
}
}
}
}
'\n' is a character for "new line", meaning it waits for a user to press "Enter". So second loop will exit as soon as user press Enter, and will check for correct answer afterwards. If answer is wrong, all start from the beginning.

Scanner nextLine() doesn't work after System.in.read()

I have following code and am facing a problem if I use System.in.read() before Scanner.
Then the cursor moves at the end by skipping nextLine() function.
import java.util.Scanner;
public class InvoiceTest{
public static void main(String [] args) throws java.io.IOException {
System.out.println("Enter a Charater: ");
char c = (char) System.in.read();
Scanner input = new Scanner(System.in);
System.out.println("Enter id No...");
String id_no = input.nextLine();
System.out.println("Charater You entered "+ c +" Id No Entered "+ id_no);
}
}
You are not consuming the newline character upon entering your character(System.in.read()) thus the input.nextLine() will consume it and skip it.
solution:
consume the new line character first before reading the input of for the id.
System.out.println("Enter a Charater: ");
char c = (char) System.in.read();
Scanner input = new Scanner(System.in);
System.out.println("Enter id No...");
input.nextLine(); //will consume the new line character spit by System.in.read()
String id_no = input.nextLine();
System.out.println("Charater You entered "+c+" Id No Entered "+id_no);
}
EJP comments thus:
Don't mix System.in.read() with new Scanner(System.in). Use one or the other.
Good advice!
So why is it a bad idea to mix reading from the stream and using Scanner?
Well, because Scanner operations will typically read ahead on the input stream, keeping unconsumed characters in an internal buffer. So if you do a Scanner operation followed by a call to read() on the stream, there is a good chance that the read() will (in effect) skip over characters. The behaviour is likely to be confusing and unpredictable ... and dependent on where the input characters are actually coming from.

some logical error in taking up character in java

This is my code...
class info{
public static void main (String[]args) throws IOException{
char gen;
while(true) { //problem occurs with this while
System.out.print("\nENTER YOUR GENDER (M/F) : ");
gen=(char)System.in.read();
if(gen=='M' || gen=='F' || gen=='m' || gen=='f'){
break;
}
}
System.out.println("\nGENDER = "+gen);
}
}
This is my output...
ENTER YOUR GENDER (M/F) : h
ENTER YOUR GENDER (M/F) :
ENTER YOUR GENDER (M/F) :
ENTER YOUR GENDER (M/F) : m
GENDER = m
Could someone please help me understand why it is asking for the gender so many times.
You are probably workin' on Windows. When you give an answer and hit enter it adds two extra characters '\r' and '\n'. From stdin you receive only one character but those extra two remain in the buffer. When you give an incorrect answer you loop and automatically read from the buffer those two characters. They don't match the gender so the loop continues. The best solution would be to analyze strings instead of characters:
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
String s = in.readLine();
Remember to use equals method instead of == in string comparison.
You pressed return after pressing h; you won't see the 'h' until you do so, but then you'll still see the return (and by the looks of it, that's coming out as two characters, possibly '\r' and '\n') before you see the next character.
You may want to read a line of text at a time, instead of a single character - you'll only see the input when the user presses return anyway, and it means you don't need to worry about this particular aspect.
You could use Scanner for this, or a BufferedReader wrapping System.in.
Use Scanner scan = new Scanner(System.in)
Here is the working version of your code....
public class Info{
public static void main (String[]args) throws IOException{
char gen;
Scanner scan = new Scanner(System.in); // Change made here
while(true) {
System.out.print("\nENTER YOUR GENDER (M/F) : ");
gen= scan.next().charAt(0); // Change made here
if(gen=='M' || gen=='F' || gen=='m' || gen=='f'){
break;
}
else{ // Change made here
System.out.println();
System.out.println("Your Option is not Available, pls try again");
continue;
}
}
System.out.println("\nGENDER = "+gen);
}
}

Categories

Resources