Clearing unwanted input in Java - java

I am using a 'ConsoleSupport' class which handles the receiving and validation of input from the user. One problem I noticed was that if I asked for an integer (menu option) in my console UI first, then asked for a couple of Strings, the first String would be empty. The dreaded newline character strikes again! I used the following in my getType methods before returning the value to make it work:
if(in.hasNextLine())
in.nextLine();
Does anyone have an alternative, more 'elegant' solution to dealing with input that is not wanted?
The (abbreviated) class is below for reference
import java.util.Scanner;
/**
* This class will reliably and safely retrieve input from the user
* without crashing. It can collect an integer, String and a couple of other
* types which I have left out for brevity
*
* #author thelionroars1337
* #version 0.3 Tuesday 25 September 2012
*/
public class ConsoleSupport
{
private static Scanner in = new Scanner(System.in);
/**
* Prompts user for an integer, until it receives a valid entry
*
* #param prompt The String used to prompt the user for an int input
* #return The integer
*/
public static int getInteger(String prompt)
{
String input = null;
int integer = 0;
boolean validInput = false;
while(!validInput)
{
System.out.println(prompt);
input = in.next();
if(input.matches("(-?)(\\d+)"))
{
integer = Integer.parseInt(input);
validInput = true;
}
else
{
validInput = false;
System.out.println("Sorry, this input is incorrect! Please try again.");
}
}
if(in.hasNextLine())
in.nextLine(); // flush the Scanner
return integer;
}
/**
* Prompts the user to enter a string, and returns the input
*
* #param prompt The prompt to display
* #return The inputted string
*/
public static String getString(String prompt)
{
System.out.println(prompt);
return in.nextLine();
}
}

Input from System.in isn't available to be read until the user hits enter. Because of that, there's an extra newline in the Scanner's buffer after the integer. So when you call Scanner.nextInt() you read the integer, but the next time you call Scanner.nextLine(), you'll read up to the newline in the buffer and it would return a blank String.
One way to deal with it is to just always call nextLine() and use Integer.parseInt() like you're doing above. You could probably skip the regex match and instead just catch the NumberFormatException:
while(!validInput)
{
System.out.println(prompt);
input = in.nextLine();
try {
integer = Integer.parseInt(input.trim());
validInput = true;
}
catch(NumberFormatException nfe) {
validInput = false;
System.out.println("Sorry, this input is incorrect! Please try again.");
}
}
And you wouldn't need to check if there's an extra line at the end and flush the scanner.

Related

my loop goes to an endless loop. How can I solve it? I cannot not enter an input in second loop [duplicate]

This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 1 year ago.
import java.util.InputMismatchException;
import java.util.Scanner;
public class h {
/** Test Function.
* #param args Kommandozeilenparameter
*/
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
input = scan.nextInt();
check = true;
} catch (InputMismatchException e) {
System.out.println("Eingabe ist falsch");
}
} while (!check);
System.out.println("getout");
}
}
I am trying to check if the user gives an integer as input.
I am trying to catch it with the help of try catch and do while loop.
But it goes to an endless loop.
How can I solve it?
In second time I cannot write anything.
The first place you should always go when you have unexpected behavior is the documentation. scan.nextInt() only consumes the input if it can be translated to an integer. Otherwise it leaves it in the scanner's buffered data. So if the user enters a letter, that letter is never consumed, scan.nextInt() just keeps reading that same letter over and over and, because it's not an integer, it keeps looping. The fix is to simply read the input from the scanner as a string, whether it can be interpreted as an integer or not. Then you can check if it's an integer yourself, and the input is already consumed. Here's your example, modified:
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
// This retrieves the next line of input, without converting it to an integer:
String line = scan.nextLine();
// This tries to convert it to an integer,
// and throws a NumberFormatException if it can't:
input = Integer.parseInt(line);
check = true;
} catch (NumberFormatException e) {
System.out.println("Eingabe ist falsch");
}
} while (!check);
System.out.println("getout");
In order to try to help you visualize my explanation, I'm going to write out a sample input and then I'll show where the data is at each step. Let's say I enter abc into the console, using your original code. The program then enters into an infinite loop, and here's why:
I enter abc into the input stream:
System.in: abc
scan:
input:
scan reads abc from the input stream as it tries to find an integer:
System.in:
scan: abc
input:
scan can't translate abc into an integer, so it throws an exception. But note that scan held on to abc, it doesn't just go away:
System.in:
scan: abc
input:
The same thing happens again, it tries to convert abc to an integer, but it can't, so it throws an exception again. See the infinite loop happening?
System.in:
scan: abc
input:
Now lets try my code. I'll enter abc and then 123:
I enter abc into the input stream:
System.in: abc
scan:
line:
input:
scan reads abc from the input stream because I told it to read the next line:
System.in:
scan: abc
line:
input:
scan passes the data on to line, because it matches the criteria for a line of text:
System.in:
scan:
line: abc
input:
The code tries to parse abc into an integer, but it can't, so it goes to the next loop iteration. line is local to each iteration of the loop, so its old value gets thrown out:
System.in:
scan:
line:
input:
I enter 123 into the input stream:
System.in: 123
scan:
line:
input:
scan reads 123 from the input stream because I told it to read the next line:
System.in:
scan: 123
line:
input:
scan passes the data on to line, because it matches the criteria for a line of text:
System.in:
scan:
line: 123
input:
The code successfully parses 123 into an integer, and assigns it to input. No infinite loop, the program has completed.
System.in:
scan:
line:
input: 123
From javadoc:
Scans the next token of the input as an int. This method will throw
InputMismatchException if the next token cannot be translated into a
valid int value as described below. If the translation is successful,
the scanner advances past the input that matched.
This means that the input is only 'read' if it is of the correct type. Since your input is not correct, it will not be read and the next time the scanner will try to read that same sequence - resulting in an infinite loop.
To fix this issue, add scan.nextLine() (or other read methods) in your catch block. When I added nextLine(), it worked for me.
Your catch block:
catch (InputMismatchException e) {
System.out.println("Eingabe ist falsch");
scan.nextLine();
}
You just need to move the check = true assignment into the catch block.
import java.util.InputMismatchException;
import java.util.Scanner;
class h {
/** Test Funktion.
* #param args Kommandozeilenparameter
*/
public static void main(String[] args) {
//
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
input = scan.nextInt();
} catch (InputMismatchException e) {
System.out.println("Eingabe ist falsch");
check = true;
}
} while (!check);
System.out.println("getout");
}
}
The above code runs until the user inputs something other than an integer, for eg. a character or a decimal. If the user inputs a valid integer, the programs again asks for a number.
In your case, if user inputs a wrong integer, the flow goes to catch block and the statement is printed. No other logic happens to break or continue the loop. As for why the exception happens again and again; the reason is simply that the scanner is still trying to read the previous input and the cycle keeps on repeating.
If you wanted the program to ask for an integer again and again until a correct input is entered, the following code does the job.
import java.util.InputMismatchException;
import java.util.Scanner;
public class h {
/** Test Funktion.
* #param args Kommandozeilenparameter
*/
public static void main(String[] args) {
//
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
input = scan.nextInt();
check = true;
} catch (InputMismatchException e) {
System.out.println("Eingabe ist falsch");
scan.next();
}
} while (!check);
System.out.println("getout");
}
}
You can use Scanner::nextLine instead of Scanner::nextInt
public class h {
/**
* Test Funktion.
*
* #param args Kommandozeilenparameter
*/
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
input = Integer.parseInt(scan.nextLine());
check = true;
} catch (NumberFormatException e) {
System.out.println("Eingabe ist falsch");
}
} while (!check);
System.out.println("getout");
}
}

Java looped Scanner.hasNext() always evaluating to false after first evaluation is false

I'm looking to write a method that checks whether user input satisfies the prompt question. For example a prompt "Enter Y or N" could be answered by the user through entering y, Y, n, or N. If the input is satisfactory the method returns the character entered in uppercase. Otherwise another prompt "Invalid char" will be shown and the scanner checks the next input attempt.
I ran the program and the method checks the first input attempt correctly. However, the problem is that if the first input attempt is wrong and "Invalid char" is shown, ANY subsequent input attempts will be unsatisfactory, i.e. sc.hasNext() in the code below is now always false. As such the program gets stuck in the while loop.
The strange thing is, I ran this exact code a week ago and it worked as intended. If it helps, I'm using the Java N-IDE app for Android.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
verifyInputChar("Enter Y or N", "yn");
}
public static char verifyInputChar(String prompt, String acceptedChars){
Scanner sc = new Scanner(System.in);
System.out.println(prompt);
while(!sc.hasNext("^(?i)[" + acceptedChars.toUpperCase() + "]$")) {
System.out.println("Invalid char.");
sc.next();
}
char input = Character.toUpperCase(sc.next().charAt(0));
System.out.println(input);
sc.close();
return input;
}
}
I wouldn't use a regular expression to do this, you aren't reusing a Pattern so it doesn't even appear to be an optimization. Instead, I would suggest you simply read your input check if there's a match in acceptedChars like
public static char verifyInputChar(String prompt, String acceptedChars) {
Scanner sc = new Scanner(System.in);
System.out.println(prompt);
String input = sc.next().toUpperCase();
while (!acceptedChars.toUpperCase().contains(input)) {
System.out.println("Invalid char.");
input = sc.next().toUpperCase();
}
char ch = input.charAt(0);
System.out.println(ch);
return ch;
}

How to have check user input using scanner without having scanner prompt multiple times

So im writing a couple methods that require the user to input what hour(1-24) they want. I need however to check whether they enter in an int, and a number between 1-24. The problem is that the scanners are called multiple times if sent to the error statement. I don't know how to do this without having these issues.
public static int getHour(Scanner scan){
int hour=0;
System.out.println("Enter the hour for the showtime (1-24):");
do{
if((!scan.hasNextInt())||((hour=scan.nextInt())<1)||(hour>24)){
System.out.println("Enter a valid number");
scan.next();
} else{
return hour;
}
}while((!scan.hasNextInt())||(hour<1)||(hour>24));
return hour;
}
Ideally it only prompts one time when entering in a not valid input such as a string or int outside of 1-24. but it prompts twice or sometimes once depending on the order of what incorrect input you put in.
Any help would be appreciated, thanks
You're encountering this problem because .hasNextInt() does not advance past the input, and .nextInt() only advances if translation is successful. A combination of loops and if-statements can thus cause confusion as to whether or not the scanner will advance. Here's your method rewritten to have the scanner prompt only once for each bad input:
public int getHour(Scanner scan) {
System.out.printf("%nEnter the hour for the showtime (1-24): ");
while (true) {
input = scan.next();
entry = -1;
try {
entry = (int)Double.parseDouble(input);
} catch (NumberFormatException e) {
// Ensures error is printed for all bad inputs
}
if (entry >= 1 && entry <= 24) {
return entry;
}
System.out.printf("%nEnter a valid number: ");
}
}
I prefer to use an infinite loop in this case, but as that can be dangerous, receive it with caution. Hope this helps!

How do I read in a text file as a string and extract just a single character? "0"

How do I go about asking for a string input, then extracting the 0 character?
I was using "fstream.next()" and it would input whatever, not just a string.
I just need a character, which I can later use in a loop where the program only accepts char inputs of T, D, and E.
Then the program reads the double. Then the program calls the instance method with the parameters (char, double). The instance method later does it's thing and saves the inputs. The program later loops back and does it all over again.
Currently I am receiving an error "java.util.InputMismatchException". If you could offer suggestions, I'd greatly appreciate it! If clarification is needed, please let me know. Thank you in advance! :)
Here is my code:
/** holds answer of whether user has more inputs or not */
String answer;
/** holds the results when calling inLetter() */
char letter;
/** holds the results when checking for types/strings in txt file */
String inType = "";
/** holds double results when searching line by line the text file */
double inAmount = 0;
/** holds the results when calling inAmount() */
double amount;
/** initiates infile to null */
File infile = null;
/** count system for how many valid lines were read and used */
int count = 0;
/** calls description method */
description();
/** initiates new Object */
GironEventClass newInput = new GironEventClass();
try{
/** defines new variable linked to .dat file */
infile = new File("GironEvent.dat");
/** calls fstream scanner - for use on file */
Scanner fstream = new Scanner(infile);
/** calls while loop. As long as there is a line, the loop continues */
while(fstream.hasNext())
{
/** inputs first string in line of file to variable inType */
inType = fstream.nextLine();
char a_char = inType.charAt(0);
/** inputs first int in line of file to variable inAmount */
inAmount = fstream.nextDouble();
try{
/** calls instance method with two parameters */
newInput.donations(a_char, inAmount);
/** count ticket increases */
count+=1;
}
catch(IllegalArgumentException a){
/** prints out error if exception is caught*/
System.out.println("Just caught an illegal argument exception. ");
}
}
/** closes stream between program and fiel */
fstream.close();
/** outputs line count, and totals per type */
System.out.println("\n" + count + " number of valid lines were read!\n");
System.out.println("Total Sales: " + newInput.getSale());
System.out.println("Donations: " + newInput.getDonated());
System.out.println("Expenses: " + newInput.getExpenses());
}
catch (FileNotFoundException e){
/** Outputs error if file cannot be opened. */
System.out.println("\nGironEvent.dat could not be opened. ");
}
do{
/** loop asks user if there is more that needs to be added to the totals. N exits loop. */
System.out.print("\nAre there any more items to add that were not in the text file? (Type 'Y' or 'N'): ");
answer = keyboard.next();
if (("Y".equals(answer)) || ("y".equals(answer)))
{
letter = inLetter();
amount = inAmount();
newInput.donations(letter, amount);
}
}while (("Y".equals(answer)) || ("y".equals(answer)));
/** calls instance method to display totals in a fancy manner */
newInput.display();
}
/** inLetter - displays types to user. Asks user to input type. Converts input into uppercase letter.
*
* #return resultTwo - Uppercase form of result. Result is the type the user inputted.
*/
public static char inLetter(){
Scanner keyboard = new Scanner(System.in);
String result;
String resultTwo;
System.out.println("T = Tiket Sales");
System.out.println("D = Donations");
System.out.println("E = Expenses");
System.out.print("Please input an identifier ");
result = keyboard.nextLine();
resultTwo = result.toUpperCase();
return resultTwo;
}
/** inAmount - asks user for amount. Tests that amount isn't a negative number or a zero.
*
* #return result - the amount the user inputed. regardless if it was the first or tenth time.
*/
public static double inAmount(){
Scanner keyboard = new Scanner(System.in);
double result;
System.out.println("Please input an amount ");
result = keyboard.nextDouble();
if(result <= 0){
System.out.print("Please input a positive and non-zero amount ");
result = keyboard.nextDouble();
}
return result;
}
/** description - displays a description of what the program does
* void.
*/
public static void description(){
System.out.println("The program will ask you what amount is being spent on what.");
System.out.println(" ex: expenses, ticket sales, and profts.");
System.out.println("This program will help determine whether the event generated or lost money.");
}
I need assistance with the following block:
/** inputs first string in line of file to variable inType */
inType = fstream.nextLine();
char a_char = inType.charAt(0);
/** inputs first int in line of file to variable inAmount */
inAmount = fstream.nextDouble();
Your fstream is having a combination of String and Double.
So when you use fstream.nextDouble() it throws java.util.InputMismatchException
Reference: http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextDouble()
You can first check whether the next character is double or not with the method hasNextDouble()
Reference:
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextDouble()

System.out.print is printing two lines/questions at the same time. What am I doing wrong?

So i am working on an assignment for class and after i went through and fixed all of the errors the compiler found i get this when running the program:
J:\Java Class>java AddressDemo
What is your Street's name? Unknown RD
What is your zip code? 1234565
What is your State?
What is your house number?
It is asking both questions at the same time and waiting for input.
Here is my code:
import java.util.Scanner;
public class AddressDemo
{
public static void main(String[] args)
{
Address address = new Address();
Scanner input = new Scanner(System.in);
String Street;
int Zip;
String State;
String City;
int house;
// Get the student's input
System.out.println();
System.out.print("What is your Street's name?\t");
Street = input.nextLine();
System.out.println();
System.out.print("What is your zip code?\t");
Zip = input.nextInt();
System.out.println();
System.out.print("What is your State?\t");
State = input.nextLine();
System.out.println();
System.out.print("What is your house number?\t");
house = input.nextInt();
System.out.println();
System.out.print(" What is your city?\t");
City = input.nextLine();
// Processing
address.setStName(Street);
address.setZNum(Zip);
address.setSName(State);
address.setCName(City);
address.setHNum(house);
//Output isn't finished
System.out.println("\nYour address is:" + address.getHNum() + address.getStName() + address.getCName() +address.getSName()
+ address.getZNum() + " !");
}
}
and here is my code for the other file required:
public class Address
{
private int HNum;
private String StName;
private String CName;
private String SName;
private int ZNum;
private String LNum;
public boolean setHNum (int hn)
{
HNum = hn;
return true;
}
public String getHNum()
{
return String.format("%08d", HNum);
}
public boolean setStName(String str)
{
StName = str;
return true;
}
public String getStName()
{
return StName;
}
public boolean setCName(String City)
{
CName = City;
return true;
}
public String getCName()
{
return CName;
}
public boolean setSName(String st)
{
SName = st;
return true;
}
public String getSName()
{
return SName;
}
public boolean setZNum ( int zip)
{
ZNum = zip;
return true;
}
public String getZNum()
{
return String.format("%08d", ZNum);
}
public boolean setLNum (String l2)
{
LNum = l2;
return true;
}
public String getLNum()
{
return String.format("%08d", LNum);
}
}
When you use input.nextInt(), it does not consume the newline character that ends the input. The result is that when you prompt for the next input (the state), it immediately reads the leftover newline, assigns the empty string to State, and prompts for the house number. You should instead use input.nextLine() to read the zip code (and, later, the house number) and parse the line as an int. Alternatively, call nextLine() and ignore the return value after calling nextInt().
I'd like to suggest that the zip code should probably be just a string anyway so that you preserve leading zeros and can handle zip+4 addresses. Likewise the house number should be a string to handle addresses like 221b Baker Street. That will, of course, require changing your Address class definition as well as changing how you read the input.
You should use input.nextLine() after using input.nextInt() in order to consume the remaining newline character in the buffer. If you use input.nextLine() and try to parse it directly to int, you may get an exception if the line is not an integer, so you would need to catch an exception. You can do this instead:
System.out.println();
System.out.print("What is your zip code?\t");
Zip = input.nextInt();
input.nextLine();
When you type the zip code, let's say 12345, you also enter a carriage return. input.nextInt(); eats 12345, the following input.nextLine(); eats the carriage return, that's why your program jumps to the house number.
Here is the solution :
System.out.print("What is your zip code?\t");
Zip = input.nextInt();
input.next line();
System.out.println();
System.out.print("What is your State?\t");
State = input.nextLine();
System.out.println();
System.out.print("What is your house number?\t");
First:
in your Address class:
public boolean setStName(String str)
{
StName = str;
return true;
}
there no need for the boolean return, since you're not using that return value anywhere. So your functions should look like this instead: (void means there is no return value).
public void setStName(String str)
{
StName = str;
}
Second:
System.out.println() will print out what you give it, then add a line break at the end, while System.out.print() will just print what you give it... Consider this:
System.out.println("Hello1");
System.out.print("Hello2");
System.out.print("Hello3");
System.out.print("Hello4");
System.out.println("Hello5");
System.out.println("Hello6");
System.out.print("Hello7");
System.out.println("Hello8");
Will output:
Hello1
Hello2Hello3Hello4Hello5
Hello6
Hello7Hello8
--
Third:
And this is why I really hate the fact that Java is taught in this fashion to beginner programmers, is that reading input from the console isn't that simple, because Scanner.nextInt() isn't that simple.
Ok, so...
Scanner.nextLine() reads a string from the input console, until it hits a "new line" symbol (aka, you hitting the enter key), and it eats up that new line symbol in the process. But Scanner.nextInt() only tries to read a number, and stops when it encounters something that's not a number (like a "new line" character), and leaves it in the input buffer.
your Scanner.nextInt() call works, but your next nextLine() call never gets any input BECAUSE the nextInt() call took all the numbers from the System.in , but it didn't take out the new line. Your following nextLine() call only looks for the next new line character, and it finds it right away...
Here's the quick and super filthy solution:
After every Scanner.nextInt() add an extra Scanner.nextLine() to dump out the new line.
The less quick but slightly less dirty solution:
System.in consists of Strings of characters as text. so don't jump the gun, don't immediately assume the text you're receiving is a number... treat it as text first, then check to see if it's a number...
In your example:
System.out.println();
System.out.print("What is your house number?\t");
house = input.nextInt();
Let's do this:
System.out.println("What is your house number?");
String houseNumberString = input.nextLine();
house = Integer.parseInt(houseNumberString);
input.nextLine() will give you the keyboard input as a String up to when the user pressed Enter.
Integer.parseInt() will try to decipher the text String, and convert it into an integer.
bon courage :)

Categories

Resources