Taking input using bufferedreader - java

I want to take input in the format: -prize 45
This is my code
static double prize_input(String list[]) throws IOException{
boolean flag=false;
double p=0;
while(true){
if(list.length!=2 || ( list[0].compareTo("-prize")!=0 ) ){
System.out.println("usage: -prize <Itemprize>");
flag=true;
}
else
{
try{
p=Double.parseDouble(list[1]);
flag=false;
}
catch(Exception e){
flag=true;
}
}
if(!flag)
return p;
else
list=br.readLine().split(" ");
}
}
When I input: -prize abc where second argument is also a string it prompts me for another enter key from user instead of display the appropriate message. Please tell me what am I missing and how should I correct it.

usage: -prize <Itemprize> will be printed only if this condition will fail
if (list.length != 2 || (list[0].compareTo("-prize") != 0))
so only if
user didn't provided two elements,
and if first element is not -prize.
Since for -price aaa both conditions are fulfilled so user will not see this info, but flag representing correctness of data will be set to false while failed parsing second parameter, so in
else
list = br.readLine().split(" ");
program will be waiting for new data form
To improve user experience you should print usage info right before reading new data from user, so try moving line
System.out.println("usage: -prize <Itemprize>");
right before br.readLine()
else{
System.out.println("usage: -prize <Itemprize>");
list = br.readLine().split(" ");
}

your condition is worng as you are taking while(true) as a loop condition and also you are taking a input in which loop will go as forever and also buffer reader waits for the next line to be splited.

Related

Is it possible to check if the input is an integer without hasNextLine and exit loop if it's 0?

My method works perfectly,but I want to exit the loop if 0 is entered.I know I can use getArray.hasNextInt() and then if the input was an integer put into a new variable and then check again if it's 0,then leave the loop,but I think that'd be too long of a code and needs at least two other variables(an integer and a boolean) to be created.
I have written a method like so:
public static char[] play() { //Takes a string from the user,checks if the length is 5,and converts to character array.
boolean fiveChars =false;
System.out.println("Please enter your input: ");
Scanner getArray = new Scanner (System.in);
while(!fiveChars) {
String gotArray = getArray.nextLine();
if(gotArray.length()==5) {
myInput=gotArray.toCharArray();
break;}
else
{ if(gotArray.charAt(0)==0 && gotArray.length()==1) {
a++;
menu();
break;}
else
System.out.println("Please try again!Your input should consist of 5 characters!");
System.out.println("giving a new input doesn't count as one of your choices.");
}}
return myInput;
}
But it doesn't work.I want to know why
if(gotArray.charAt(0)==0 && gotArray.length()==1)
Blockquote
doesn't work here.Also,would you please tell me if there is a shorter way that works exists?Thanks.
Either
if(gotArray.charAt(0)=='0' && gotArray.length()==1)
OR
if(Integer.parseInt(gotArray.charAt(0))==0 && gotArray.length()==1)
should work.

Issue with catching my selection input

I am creating a program that is a simple mock-up of a banking account system. I have a simple method that when called asks the user to input a name (String) and a starting account balance (double) and creates a new Person object / Account object.
This method is called via a menu that uses 1-9 (int) options, and say '1' is pressed to create a new account. So the code (before accepting the string) has a default input.nextLine(); command to catch the int input before capturing the actual name input (customerName = input.nextLine();).
The issue I am having is that I am trying to add exception handling to this method to ensure that the name String input is only letters and spaces. When running the first time and someone puts an incorrect input, it would re-output the "Please input a name" but then they would have to enter the name twice since the input.nextLine(); was still in there (but not catching a menu input). So I added a if/else decision structure with a counter for the first time that the program runs if the (counter == 0) then it keeps the input.nextLine() and increments the counter, but if the (counter > 0) it gets rid of the input.nextLine() so that the program runs fine.
This causes another problem, that if the user tries to create multiple accounts, it will cause the program to stop printing the input.nextLine() the second time it is called and automatically assume the menu option input is what the name is supposed to be, and sends an error. Is there a better way to get this working the way I intended?
Sorry if the description isn't very clear, it's a hard problem to describe.
Here's the code:
public void menuOptionOne() {
do {
try {
if (counter == 0) { // counter is initially set to 0
System.out.println("Please input the customer's name: ");
input.nextLine(); // catches the menu input
customerName = input.nextLine();
matcher = pattern.matcher(customerName);
counter++; // increments the counter in case the user's input is invalid
if (!matcher.find()) { // if it has non-letter/space characters present, throws exception
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
} else if (counter > 0) { // asks the user to input name again, without the input.nextLine() which is intended to catch the menu int input
System.out.println("Please input the customer's name: ");
customerName = input.nextLine();
matcher = pattern.matcher(customerName); // checks the input to ensure it is only letters and/or spaces
if (!matcher.find()) {
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
}
continueInput = false;
} catch (Exception ex) {
System.out.println(ex.toString());
}
} while (continueInput);
So when this gets called twice in a row, it automatically goes to the second decision structure, without the input.nextLine(), and that catches the menu input (1) and throws the exception. How can I get it to work properly each time the method is called?
This is the output when it is called twice in a row (note: it saves the menu input as the new customer name, even though it is a number):
Please input the customer's name:
java.lang.Exception: Try again. (Incorrect input: name must contain only letters)
Please enter the new balance:
You want to do two things in the input retrieval:
allow a series of inputs by reusing this method.
check the content of the input and start again if not suitable.
The way you are using to "allow a series of inputs by reusing this method" is the source of your error.
In a general way you should favor the use of the most restricted scope when it is enough.
By declaring continueInput and counter as a field variable instead of a local variable you create a coupling between invocations of menuOptionOne().
Which explain your problem :
This causes another problem, that if the user tries to create multiple
accounts, it will cause the program to stop printing the
input.nextLine() the second time it is called and automatically assume
the menu option input is what the name is supposed to be, and sends an
error. Is there a better way to get this working the way I intended?
This code should be enough :
public void menuOptionOne() {
// change
int counter = 0;
boolean continueInput = true;
// end change
do {
try {
if (counter == 0) { // counter is initially set to 0
System.out.println("Please input the customer's name: ");
input.nextLine(); // catches the menu input
customerName = input.nextLine();
matcher = pattern.matcher(customerName);
counter++; // increments the counter in case the user's
// input is invalid
if (!matcher.find()) { // if it has non-letter/space
// characters present, throws
// exception
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
} else if (counter > 0) { // asks the user to input name again,
// without the input.nextLine()
// which is intended to catch the
// menu int input
System.out.println("Please input the customer's name: ");
customerName = input.nextLine();
matcher = pattern.matcher(customerName); // checks the input
// to ensure it
// is only
// letters
// and/or spaces
if (!matcher.find()) {
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
}
continueInput = false;
} catch (Exception ex) {
System.out.println(ex.toString());
}
} while (continueInput);
}
The way you are using to "check the content of the input and start again if not suitable", works but you could do much more simple and avoid repeat yourself.
Ah, I figured out my issue.
I set the variable counter = 0; at the top of my method and then at the bottom set continueInput = true; again
Now it works as intended.
So working code looks like:
public void menuOptionOne() {
counter = 0; // set counter to 0
do {
try {
if (counter == 0) {
System.out.println("Please input the customer's name: ");
input.nextLine();
customerName = input.nextLine();
matcher = pattern.matcher(customerName);
if (!matcher.find()) {
counter++;
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
} else if (counter > 0) {
System.out.println("Please input the customer's name: ");
customerName = input.nextLine();
matcher = pattern.matcher(customerName);
if (!matcher.find()) {
throw new Exception("Try again. (Incorrect input: name must contain only letters)");
}
}
continueInput = false;
} catch (Exception ex) {
System.out.println(ex.toString());
}
} while (continueInput);
continueInput = true; // reset the continue input value

Why does my while loop needs this line of code to run?

I just completed an application which prompts the user for a text File input IO but I have something to clarify as the final part, While loop I actually managed to refer it to a tutorial on google. In this loop, there is a if-else statement and for the else part I don't understand why is it necessary.
Here's my code:
import java.io.*;
import java.util.*;
class FileReadingExercise2 {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
Scanner fileInput = null;
do {
try {
System.out.println("Please enter the name of a file or type QUIT to finish");
String a = userInput.nextLine();
if (a.equals("QUIT")) { // if user inputs QUIT then stop application
System.exit(0);
}
fileInput = new Scanner(new File(a)); // the file contains text and integers
} catch (FileNotFoundException e) {
System.out.println("Error - File not found");
}
} while (fileInput == null);
int sum = 0;
while (fileInput.hasNext()) // continues loop as long as there is a next token
{
if (fileInput.hasNextInt()) // if there is an int on the next token
{
sum += fileInput.nextInt(); // then adds the int to the sum
} else {
fileInput.next(); // else go to the next token
}
}
System.out.println(sum);
fileInput.close();
}
}
As you can see, as long as the fileInput Scanner has a next token to look up to then operate the if else statement. If fileInput has a next Int then adds it up to the sum variable. So from what I think is that this will be sufficient. Once fileInput has no more token to read, it shall get out of the while loop isn't it? Why does it has still go onto the next token? I'm confused. Please advise thanks! ;)
Why does it has still go onto the next token?
That is because when nextInt() is executed it will consume the int number within the file but within it, it has a newLine character that needs to be consume and that is when next is executed to consume that newLine after the int number.
sample file content:
1
what actually in there is 1 character and newline \n character
In this loop, there is a if-else statement and for the else part I don't understand
why is it necessary.
fileInput.hasNexInt() method returns true if int value found and than it performs adding operation. if next value is not int type than else part will perform where fileInput.next() will return next value(pointer will points after that value), performs nothing means escaping next value(which can be any type except int-type). Again if condition will check for int.

java nextInt() try catch repeating output more than once

I am writing a program that accepts two ints within the program using nextInt(); and have it wrapped in a try catch block to stop bad inputs such as doubles or chars.
When multiple wrong inputs are entered the loop repeats that same number of times. I assume this is because my scan.next() has to loop around enough times to catch the bad inputs w/o error. Is there a way to know this number on the first run through to make a loop to run next in that many times?
In the output the
if(cont == 'N') System.out.print("\nPlease re-enter\n\t:"); will output and mirror the amount of times a mismatched input was written. That is, if I input 3 3.3 it will repeat one extra time, if input s 3.3 2.5 it will repeat three extra times.
I tried putting a loop around scan.next() to default it to ten times, but was overboard and I had to input an extra 8 characters before it started reading again. Maybe a while loop but what would its condition be, I tried while(scan.next() != null){} but that condition never stopped.
//input error checking
char cont = 'Y';
do{
if(cont == 'N')
System.out.print("\nPlease re-enter\n\t:");
cont = 'Y';
/* to stop the accidential typing of things other
* than integers from being accepted
*/
try{
n1 = scan.nextInt();
n2 = scan.nextInt();
}catch(Exception e){
cont = 'N'; //bad input repeat loop
scan.next();//stops infinite loop by requesting Scanner try again
}
} while(cont == 'N');//do loop while told N for continue
Not sure what you want your code to do. From reading what you have posted I assume you want the user to input 2 ints and if he/she doesn't you want to prompt him/her to re-enter something until he/she inputs 2 ints.
If this is the case I would just add
scan = new Scanner(br.readLine());
after this if statement:
if(cont == 'N')
{System.out.print("\nPlease re-enter\n\t:");}
This will solve your looping issue
First try :
change the line in the exception catch from
scan.next();
to
while(scan.hasNext()){
scan.next();
}
You can try to do the following in your catch block:
while(scan.hasNext())
scan.next();
make it a method and do it with that method.
sth like this:
// do it until getting two Integers
boolean isItInteger = false;
while (isItInteger == false) {
isItInteger = getInt();
}
.
.
.
// your method for getting two Integers
public static boolean getInt() {
try {
Scanner sc = new Scanner(System.in);
n1 = sc.nextInt();
n2 = sc.nextInt();
} catch (Exception e) {
System.out.println("Please re-enter");
return false;
}
return true;
}

How to classify input datatypes using buffered reader and exception handling?

Assume the user inputs several values and the program has used the stringTokenizer to break the values up. The program would then try to parse the token and throw an error right? the error catch would output the datatype;
This is a question given to a first year programming course so I'd rather not have a direct answer but more of a point in the right direction. The prof would like only two try...catch clauses, both of which were looking for NumberFormatException's.
Thanks in advance.
Original question:
"Using exceptions and testing to classify keyboard input into one of
the eight primitive data types, or String."
We will narrow down exactly what the input is in the order: boolean > char > double > float > long > int > short > byte
Discard the "or String" part of the question, all Strings can be
evaluated to a boolean value (see Boolean.parseBoolean(s)). So, your
starting answer is "the input is a boolean", and keep going.
Is the input exactly 1 character in length? If so, "the input is a
character". Keep going regardless.
Open a try block.
Double.parseDouble(s). If there is no exception, "the input is a
double", and keep going.
Try each parse the input in the order given above.
Open a catch block, catching NumberFormatException. The block will
actually be empty, since what you really want is the finally block.
Open a finally, in which you will return your answer.
Unless I'm missing somthing (entirely possible, since I've not writen the code), this gives you the "one" requirement, uses few exceptions, and takes advantage of exceptions to control flow.
Final answer thanks guys
import java.io.*;
import java.util.StringTokenizer;
/**
* Classifies input into primitive types or String
*
* #author Suavelizard
* #version Feb, 2012
*/
public class Classify
{
public static void main(String[] args) throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please enter some data (C-z or C-d to quit): ");
String str = in.readLine();
while (str != null)
{
StringTokenizer tokenizer = new StringTokenizer(str);
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
// your code goes here!
try{
long x = Long.parseLong(token);
if(x<= Byte.MAX_VALUE &&x>= Byte.MIN_VALUE){
System.out.println("Input is a Byte");}
else if (x<=Short.MAX_VALUE && x>=Short.MIN_VALUE){
System.out.println("Input is a Short");
}
else if(x<=Integer.MAX_VALUE && x>= Integer.MIN_VALUE){
System.out.println("Input is an Integer");
}
else{
System.out.println("Input is a Float");
}
}
catch(NumberFormatException a){
try{
double x = Double.parseDouble(token);
if (x<= Float.MAX_VALUE &&x>= Float.MIN_VALUE)
{
System.out.println("Input is a Float");
}
else if(x<= Double.MAX_VALUE &&x>= Double.MIN_VALUE)
{
System.out.println("Input is a Double");
}
}
catch(NumberFormatException b){
if (token.length() == 1){
System.out.println("Input is a Character"); }
else if(token.equalsIgnoreCase("true")|| token.equalsIgnoreCase("false")){
System.out.println("Input is a Boolean");
}
else{
System.out.println("Input is a String");
}
}
}
}
System.out.print("Please enter some data (C-z or C-d to quit): ");
str = in.readLine();
}
}
}

Categories

Resources