Using Java System.in as a press to continue - java

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

Related

In IntelliJ IDEA, while taking input in an array from console, character of enter key is accepted as an element

I was seeing an example of linear search in an array in Java, and I wrote this code:
import java.util.*;
public class LinearSearch
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
System.out.print("Enter no. of members: ");
int l=sc.nextInt();
String[] list=new String[l];
System.out.println("Enter the members: ");
for(int i=0;i<l;i++)
list[i]=sc.nextLine();
System.out.print("\nEnter the member you want to search for: ");
String ts=sc.nextLine();
for(int i=0;i<l;i++)
{
if(list[i].equalsIgnoreCase(ts))
{
System.out.println("The member is at index " + i);
break;
}
if(i==l-1)
System.out.println("There is no such member");
}
}
}
But while running this code, due to the System.out.println() at the 10th line, the carriage return (of the println() ) is taken as the element at index 0. Further, as I enter more elements, after each element I need to press Enter key to start the next iteration, but with that, the carriage return of the Enter key is taken as input too. This is the output:
Enter no. of members: 5
Enter the members:
a
b
c
Enter the member you want to search for: e
There is no such member
I did the following to prevent it:
System.out.println("Enter the members: ");
int j=0;
String in="";
while(list[l-1]==null)
{
in=sc.nextLine();
if(in.equals(String.valueOf((char)10))) //10 being the ASCII code of carriage return
continue;
else
{
list[j] = in;
j++;
}
}
But this doesn't work, it still takes carriage return as an element. Is there any way to fix this issue ?
You need to skip line after nextInt() call as in the answer mentioned by #user16320675 in the comment
But, there is another bug in Intellij IDEA console, refer answer which kind of skips alternative nextLine() input. Hence, your call ends even when you just enter 3 values in this case but your array size is 5.
Refer
Your program is still correct. Just test your code in other terminal instead of IDEA console

Character.isDigit parameters and line unavailable errors within the isDigit method (clarification)

I'm currently working on a small project for an introductory java class. We're supposed to make a program which can take in an integer from the user and output the number of odds, evens, and zeroes present within the code. This seemed pretty easy to me, and I managed to implement the code, but a class mate, after I criticized his code for incorrectly following the prompt, noted that my code would crash if anything but digits was input.
Out of spite I've tried to go beyond the prompt and have the program output an error message if it encounters characters aside from digits (instead of having my compiler return an error). However I'm returning multiple errors within the Eclipse compiler when using the isDigit method in the Character class.
I don't know exactly what's causing this, and I feel I must be missing something crucial, but my teacher quite frankly isn't qualified enough to understand what's causing the error, and none of my classmates can seem to figure it out either.
package ppCH5;
import java.util.Scanner;
public class PP5_3
{
public static void main(String[]args)
{
int even = 0;
int odd = 0;
int zero = 0;
int num = 0;
int count = 0;
boolean inputError = false;
System.out.println("please provide some integer");
Scanner scan = new Scanner(System.in);
String numbers = scan.next();
scan.close();
Scanner intSeperate = new Scanner(numbers);
intSeperate.useDelimiter("");
while(intSeperate.hasNext())
{
if(Character.isDigit(numbers.charAt(count)))
{
count++;
num = intSeperate.nextInt();
if((num % 2)==1)
odd++;
if((num % 2)==0)
if(num==0)
zero++;
else
even++;
}
else
{
count++;
inputError = true;
}
}
intSeperate.close();
if(!inputError)
{
System.out.println("There are " + even + " even digits.\n" + odd + " odd digits.\nAnd there are " + zero + " zeros in that integer.");
}
else
{
System.out.println("You have provided a disallowed input");
}
}
}
Any help would be appreciated, I'm currently at a loss.
When you enter a single non-digit character, say a, the else branch inside the while loop will get executed, incrementing count, right? And then the loop will start a new iteration, right?
In this new iteration, intSeparator.hasNext() still returns true. Why? Because the input a is never read by the scanner (unlike if you have entered a digit, intSeparator.nextInt would be called and would have consumed the input).
Now count is 1 and is an invalid index for the 1-character string. Therefore, numbers.charAt(count) throws an exception.
This can be avoided if you break; out of the loop immediately in the else block:
else
{
inputError = true;
break;
}
Also, don't close the scan scanner. scan is connected to the System.in stream. You didn't open that stream, so don't close it yourself.

Getting multiple inputs from user with char and integers Java

I'm trying to allow the user to put in multiple inputs from the user that contain a char and integers.
Something like this as input: A 26 16 34 9
and output each int added to an array.
I was thinking I could have the first input as a character and then read the rest as a string which then I separate and put into an array.
I'm not new to coding but new to java. I've been doing c++ so the syntax is a bit different.
This is what I have so far, I haven't set up my array yet for the integers.
import java.util.Scanner;
public class Program0 {
public static void main(String[] args) {
int firstNumber;
Scanner reader = new Scanner(System.in);
System.out.println("'A' to enter a number. 'Q' to quit");
int n = reader.nextInt();
if (n=='A') {
//if array is full System.out.println("The list is full!");
//else
System.out.println("Integer " + " " + "has been added to the list");
}
else if (n=='Q') {
System.out.println("List of integers: ");
System.out.println("Average of all integers in the list: ");
}
else{
System.out.println("Invalid Action");
}
reader.close();
}
}
Could you specify better how should your input be given? From your question, if I understand well, the user simply type "A" followed by a list of numbers separated by a space. So I would simply read the next line, split it in words (separated by a space) and check if the first word is the letter "A". Here it goes:
import java.util.Scanner;
public class Program0 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("'A' to enter a number. 'Q' to quit");
String line = reader.nextLine();
String[] words = line.split(" ");
if (words.length > 0 && words[0].equals("A")) {
//if array is full System.out.println("The list is full!");
// => I don't understand this part
//else
for(int i = 1; i<words.length; i++){
int integer = Integer.parseInt(words[i]);
System.out.println("Integer " + integer + " has been added to the list");
//do your stuff here
}
}
else if (words.length > 0 && words[0].equals("Q")) {
System.out.println("List of integers: ");
System.out.println("Average of all integers in the list: ");
}
else{
System.out.println("Invalid Action");
}
reader.close();
}
}
Note that in your solution, you read the next int from your scanner and then try to compare it with the character 'A'. This will not work because A is not an int. If you really want to get the first character from your scanner, you could do:
String line = reader.nextLine();
if(line.length() > 0){
char firstChar = line.charAt(0);
//do your stuff here
}
A character is not an int. You cannot read an int to expect something like 'A'. You can read a String and take its first character though. Scanner doesn't offer a convenient method to read the next String and expect it to be only one-character long. You'd need to handle that yourself.
But considering you don't know in advance how many numbers there will be to read, your solution to read the entire line and interpret it entirely, is the better one. That means you can't use nextInt() nor nextDouble() nor next() nor nextWhateverElse().
You need nextLine(), and it will give you the entire line as a String.
Then you can split() the result, and check if the first is one-char-long. Then you can parse all the others as int.
I don't immediately recall how to write this in Java – it's been a bit of a while – but what I'd do is to first separate the string by spaces, then attempt to do ParseInt on each piece.
If the string isn't a valid integer, this method will throw an exception, which you can catch. So:
If you make it to the next statement, an exception didn't happen, so the value is an integer.
If, instead, you find yourself in the exception-handler (having caught [only ...] the expected kind of exception, the value is a string.
Of course, don't "catch" any exception-type other than the NumberFormatException that you're expecting.
By the way, it is perfectly routine to use exceptions in this way. Let Java's runtime engine be the authority as to whether it's an integer or not.

Why terminal doesn't prompt another input for this JAVA code?

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.

Try Catch InputMismatchException not actually catching my Error

I have copied the exact same code from another program. Whenever inputting deliberate incorrect results the InputMismatchException still occurs and the program crashes.
import java.util.*;
public class Runner{
public static void main (String args[]){
Scanner sc = new Scanner(System.in);
sc.useDelimiter("\n");
Fixture f = new Fixture();
boolean inputValid = false;
int choice = 0;
do{
do {
System.out.println("\f\t\tFootball Database");
System.out.println("A utility to help make footballing events easier to manage.");
System.out.println("");
System.out.println("\t> Press 1 to manage players ");
System.out.println("\t> Press 2 to manage teams");
System.out.println("\t> Press 3 to manage coaches");
System.out.println("\t> Press 4 to manage fixtures");
System.out.println("\t> Press 5 to save database to file");
System.out.println("\t> Press 6 to load database from file");
System.out.println("\t> Press 7 to terminate program");
System.out.println("");
System.out.println("");
System.out.println("©Thomas Camilleri 2017");
try{
choice = sc.nextInt();
inputValid = true;
}catch(InputMismatchException e){
System.out.println("Invalid input");
inputValid = false;
sc.nextInt();
sc.nextInt();
}
}while(inputValid == false);
Here is the salient part of your code:
try {
choice = sc.nextInt(); // NOT HERE
inputValid = true;
} catch(InputMismatchException e){
System.out.println("Invalid input");
inputValid = false;
sc.nextInt(); // HERE
sc.nextInt();
}
If you look at the stacktrace that you got, and look at the line numbers, you will see that the line in your code where the exception happens is the one I have tagged with // HERE.
(Compile and run the original program and look at the stacktrace to see what I mean. Compare the line numbers in the stack trace with the source code.)
As you can see, that line is NOT in the try { ... } block. It is in the exception handler block.
What has happened is that you have caught the exception that was thrown at the line tagged // NOT HERE, and then you have called sc.nextInt() again (at // HERE). The second call has simply attempted to read the same input characters again.
The behavior of the nextInt method is as follows:
get characters sufficient to form a token
attempt to convert the entire token into an integer (using base-10 integer syntax)
if the conversion succeeds, return the converted integer
if the conversion fails, put all of the characters back and then throw an exception.
I strongly encourage you to carefully read the javadocs for the Scanner class so that you understand what the methods you are using actually do.
So ... as you see ... if you just call nextInt() after a failed nextInt() call, you just get the same failure repeated.
The reason that second exception is not caught is that it has not been thrown within the try { ... } block.
Solution: Instead of calling nextInt() in the handler, you should call a method that is going to just discard the rubbish. In this case, the most sensible thing to do is to throw away everything up to the next end-of-line.
Hint #1: the nextLine() gets everything up to the next end-of-line. Read the javadocs for that method too.
Hint #2: if you understand what I said, you will know where to put your modification.
Try like:
choice = Integer.parseInt(sc.nextLine());
and your program will like this:
try (Scanner sc = new Scanner(System.in)) {
sc.useDelimiter("\n");
// Fixture f = new Fixture();
boolean inputValid = false;
int choice = 0;
// removed outer do..while(); loop
do {
System.out.println("\f\t\tFootball Database");
System.out.println("A utility to help make footballing events easier to manage.");
System.out.println("");
System.out.println("\t> Press 1 to manage players ");
System.out.println("\t> Press 2 to manage teams");
System.out.println("\t> Press 3 to manage coaches");
System.out.println("\t> Press 4 to manage fixtures");
System.out.println("\t> Press 5 to save database to file");
System.out.println("\t> Press 6 to load database from file");
System.out.println("\t> Press 7 to terminate program");
System.out.println("");
System.out.print("Enter your choice : ");
try{
// Always use nextLine() if you mix String and basic Datatype
choice = Integer.parseInt(sc.nextLine());
inputValid = true;
}catch(NumberFormatException e){
System.out.println("Invalid input");
inputValid = false;
// Removed unnecessary two sc.nextInput() lines
}
}while(inputValid == false);
System.out.println("choice is : " + choice);
}

Categories