Recursive java method to parse a string with condition? - java

Fairly new to java and programming.
Wrote this recursive method, with the objective of asking for a valid string that is both an integer and greater than 0:
private int getDimension(String tableElement){
Integer Input= 0;
System.out.println("Define table rows "+tableElement+"'s."
+"Enter an integer >= 1:");
if( !Reader.hasNextInt() || (Input=Input.parseInt(Reader.nextLine())) <= 0)
return getDimension(tableElement);
return Input;
}
I'd like to stick to using a short and recursive method. It seems to handle the >= 0 logic fine, but blows up when i pass it something other than an integer.
Can someone explain why does that happen to me please?

hasNextInt() doesn't actually consume your input, so you're stuck with the same non-int input on your next call.

Simply spoken, your code doesn't make much (any?) sense.
First of all, there is not really a point in using a recursive method that asks the user for input; and that does not at all do anything about the argument passed to it!
private int getDimension(String tableElement){
Integer Input= 0;
Bad: you keep up mixing int and `Integer. They are not the same. And - read about java coding style guides. Variable names start lower case!
if( !Reader.hasNextInt() || (Input=Input.parseInt(Reader.nextLine())) <= 0)
The first condition gives:
true: when there is NO int ...
false: when there is an int
true leads to: calling your method again without retrieving a value from the reader.
false leads to parsing an int; and checking its value for <= 0.
In one case, you are doing a recursive call; completely ignoring the input you got from the reader; in the other case, you returning 0; or that value in input.
Solution: do something like:
while (true) {
if (reader.hasNextInt()) {
input = reader.nextInt();
break;
}
// there is no number!
read.nextLine(); // consume & throw away non-number!
print "Enter a number"
}
instead.
But seriously: start with throwing away this code.
Final side note: you do Input.parseInt() ... but that is a static method on the Integer class. Just call that as Integer.parseInt() instead! But as said; throw away your code; and learn how to properly use that Scanner class; start reading here.

Because the user can enter anything, you must always read in the line, then compare it:
String num = Reader.nextLine();
return num.matches("[1-9][0-9]*") ? Integer.parseInt(num) : getDimension(tableElement);
Here I've use regex to figure out if it's a positive number; the expression means "a 1-9 char followed by 0 or more of 0-9 chars"

Related

Cannot invoke nextint() on the primitive type int

So I'm learning Java and maybe he didn't explain well enough how scanners work and their limits or maybe I'm looking over something silly... but I'm getting an error on answer = answer.nextInt(); I don't get this error for bomb but it's used pretty much the same way...
Code:
Scanner yesNo = new Scanner(System.in);
Scanner input = new Scanner(System.in);
//
//answer auto set to no. goes to first if, then asks for confirmation,
// then check answer again and go to if, else if or else.
//
int answer = 0;
while (answer != 1)
if (answer == 0) {
System.out.println("In how many seconds should we detonate?");
int bomb = input.nextInt();
//this number will be used later in else if (answer == 1)
System.out.println("Is " + bomb + " seconds correct? 1 for yes, 0 for no");
answer = answer.nextInt();
//error above "Cannot invoke nextint() on the primitive type int"
//Need this to grab a number from user to assign a new value to answer
What do? Thanks.
First of all, you have one Scanner instance with paramether System.in, so it will "record" your keyboard (I assume that yesNo scanner is not used). Then, you have a int variable called "answer" which you assign zero value. Finally you have another variable called "bomb" where you will get your requested value.
As I see in your answers' comments, you're wrong in one thing: "input.nextInt()" is an int value. When you use input.nextInt(), you're sending it a message that says "Hey bro, give me the first int that this stupid human have pressed", but you aren't doing anything more. "input" is only a scanner (as it class name says) that records keystrokes.
So in fact, when you do "input.nextInt()" you'll get an int value, and when you do "bomb = input.nextInt()" or "answer = input.nextInt()" the only thing that you're doing is giving "bomb" or "answer" that int value.
int is a primitive value. It is not an Object and it has no methods.
probably you want to do
answer = input.nextInt();
nextInt() is a function that is part of the object type Scanner. In order to call .nextInt() you must have an object of type Scanner.
So the line "int bomb = input.nextInt();" works fine, since "input" is an object of class Scanner. That function runs and it returns another object, an integer, from input, which is stored in int bomb.
The line "answer = answer.nextInt();" fails to compile because "answer" is an object of class integer. integer does NOT have a function called nextInt().
The appropriate line is "answer = input.nextInt();" using your Scanner object to return another integer to store in "answer".
int answer = 0;
answer = answer.nextInt();
You are calling nextInt() on an int. You need to call it on the scanner:
answer = input.nextInt();

While not (or equivalent) java

I'm making a program with Java that needs to involve some error checking. I can stop users from entering bad numerical inputs like this (assume the input scanner has already been created):
while (n == 0){
System.out.println("Can't use 0 as a denominator! Please enter a real, nonzero number");
n = input.nextInt();
}
But how do I stop users from entering an invalid string? I can't use !=, because strings can only be compared with the string.equals() method, right? So, is there a while not loop? ie:
while !(string.equals("y") || string.equals("n")){
//here have code
}
Or something of that nature?
While there is no such thing as a while-not loop, you can always invert the condition:
while (!(string.equals("y") || string.equals("n"))){
This is read, "while the string is not equal to "y" or "n"".
You could also apply DeMorgan's identity to rewrite this as:
while (!(string.equals("y")) && !(string.equals("n"))){
which is a bit clearer as "While the string isn't equal to "y" and isn't equal to "n"".
There isn't a while-not instruction, but you can simply negate the condition in a normal while loop. Try this:
while (!string.equals("y") && !string.equals("n"))
Or even better, to guard against the case where the string is null and/or it's in a different case:
while (!"y".equalsIgnoreCase(string) && !"n".equalsIgnoreCase(string))
You almost get it, just change where you position your !
like this:
while (!(string.equals("y") || string.equals("n")))
Why not try regex?
Scanner sc = new Scanner(System.in);
String string = sc.nextLine();
while (!string.matches("(?i)^(?:y|n|yes|no)$"))
{
System.out.println("Invalid input...");
string = sc.nextLine();
}
boolean answer = string.matches("(?i)^(?:y|yes)$");

How to accept strings or integers in the same user input

I want to accept user input as either an integer or a string in Java but I always get an error no matter what I do.
My code is very simple (I'm a beginner):
System.out.println(
"Enter the row number (or enter e to quit the application):"
);
Scanner rowInput = new Scanner(System.in);
int row1 = rowInput.nextInt();
I want the user also to be able to press "e" to exit.
I have tried several things:
1) To convert row1 to a String and and say:
if((String)(row1).equals("e"){
System.out.println("You have quit") }
2) To convert "e" to an integer and say:
if(row1 == Integer.ParseInt("e"){
System.out.println("You have quit") }
3) To do the switch statement but it said I had incompatible types (String and an int).
My errors usually say: Exception in thread "main" java.util.InputMismatchException
Is there somebody who could help me?
Many thanks in advance!
You can try something like this
Scanner rowInput = new Scanner(System.in);
String inputStr = rowInput.nextLine();
try{
int row1 = Integer.parseInt(inputStr);
} catch (NumberFormatException e) //If exception occurred it means user has entered 'e'
{
if ("e".equals(inputStr)){
System.out.println("quiting application");
}
}
you should read the input from your scanner as String type and the try to convert that String input into integer using Integer.parseInt().
If its successful in parsing, it means user has input an Integer.
And If it fails, it will throw an exception NumberFormatException which will tell you that its not an Integer. So you can go ahead and check it for e if it is, do whatever you want as per your requirement.
You can't use nextInt() if you aren't sure that you will have a number coming in. Also, you can't parse e as an integer, because it is not an integer, it's either char or string (I'll suggest string in this case).
That means, your code should look like:
System.out.println("Enter the row number (or enter e to quit the application):");
Scanner rowInput = new Scanner(System.in);
string row1 = rowInput.next();
Then you have the data in a string. You can simply check if the string is e:
if (row1.Equals("e")) ...
It is also a good idea to check if the input is actually an integer then. Good way to check it is described here:
How to check if a String is numeric in Java
1) you should say Integer.parseInt() instead of Integer.ParseInt()
2) if you pass "e" to Integer.parseInt() you'll get java.lang.NumberFormatException
3) get your input as a string this way (cause it's safer)*:
Scanner rowInput = new Scanner(System.in);
String row = rowInput.next();
if (row.equals("e")) {
//do whatever
}
else if(row.matches("\\d+$")) {
//do whatever
}
*In your approach if user enters a non-integer input you'll encounter java.util.InputMismatchException
I have tried several things ....
Attempting to solve this problem by "trying things" is the wrong approach.
The correct approach is to understand what is going on, and then modify your solution to take this into account.
The problem you have is that you have a line of input that could be either a number or the special value e which means quit. (And in fact, it could be a couple of other things too ... but I will come to that.)
When you attempt to either:
call Scanner.nextInt() when the next input is not an integer, OR
call Integer.parseInt(...) on a String that is not an integer
you will get an exception. So what do you do?
One way is to change what you are doing so that you don't make those calls in those situations. For example:
call Scanner.hasInt() to see if the next token is an integer before calling nextInt(), or
test for the "e" case before you attempt to convert the String to an integer.
Another way to deal with this is to catch the exception. For example, you could do something like this:
String s = ...
try {
number = Integer.parseInt(s);
} catch (NumberFormatException ex) {
if (s.equals("e")) {
...
}
}
Either way will work, but I'm going to leave you to work out the details.
But the real point I'm trying to make is that the right way to solve this is to understand what is happening in your original version / versions, and based on your understanding, modify what you were doing. If you just randomly "try" alternatives that you found with Google, you won't progress to the point of being a productive programmer.
I said there were other cases. They are:
The user types something that is neither a number of your special e character. It could be anything. An empty line, hi mum ...
The user types the "end of file" character; e.g. CTRL-D on Linux or CTRL-Z on windows.
If you want your program to be robust you need to deal with these cases too.
Try this:
public class Demo{
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
String choice = null;
System.out.println("Enter e to exit or some other key to stay:");
choice=s.next();
if(choice.equals("e"))
{
System.out.println("quits");
System.exit(0);
}
else
{
System.out.println("stays");
}
}
}
You can't convert a string into integer, use char ASCII codes instead.

Input validation without using try catch exception

Im writing a program that calculates the investment of a person after a number of years. I prompt the users to enter their name, amount they will be investing, interest rate, and number of years. I'm supposed to do a validation of the input with if...else statements. One of the checks is to see if the user has entered the correct data type. This is for an intro java class. We finished the chapter on methods a week ago, so this is beginner's stuff. I can seem to figure out how to do the data type check. I tried the hasNextInt for my int types but I get an exception which we haven't learned at all. I found some info online on the Pattern and Match classes but there's a lot of stuff in there that we haven't seen yet. Here's one of the methods I wrote to get the correct input.
//Define method for input validation, integer type
public static int getValidInt(String messagePrompt, String messagePrompt2, String messagePrompt3){
Scanner input = new Scanner(System.in);//Create scanner
int returnValue;
int j = 0;
do {//Start validation loop
System.out.printf(messagePrompt); //Print input request
returnValue = input.nextInt();
if (returnValue <= 0) { //Check if user entered a positive number
System.out.println(messagePrompt2);//Print error message
}
else if (!input.hasNextInt()) {
System.out.println(messagePrompt3);//Print error message
}
else {
j++;
}
} while (j == 0);//End validation loop
return returnValue;
}
Im not sure if I have the order of the checks right. Any help is welcome. Thank you.
If it's just 4 pre-defined input fields and you don't have to check for additional things then I don't see a reason to use a do while loop here. Though maybe I don't get what this method is supposed to do, are you returning some kind of integer that defines whether the input was valid or do you actually have to store the values? If the former, why not just return a Boolean or an Enumeration?
I also don't understand why you're simply calling nextInt the first time, but for the next one you are checking whether it has a nextInt.
Also you don't mention what kind of exception you're getting when calling hasNextInt, but apparently this can only be an IllegalStateException. I suggest taking a look at the Java docs at http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html, or reading your relevant course material.
The sequence nextInt() and hasNextInt() is invoked. First one is used to read the value from input, and second is used to see whether the value type is int. So you have to invoke hasNext[Type]() followed by next[Type].
Let's correct those two first as below.
if (scnr.hasNextInt()) {
int userChoice = scnr.nextInt();
} else {
// input is not an int
}
Now let's correct your code to get a valid int.
public static int getValidInt(String messagePrompt, String messagePrompt2, String messagePrompt3) {
Scanner input = new Scanner(System.in);// Create scanner
int returnValue = -1;
boolean incorrectInput = true;
while (incorrectInput) {
System.out.printf(messagePrompt); // Print input request
if (input.hasNextInt()) {
returnValue = input.nextInt();
if (returnValue <= 0) { // Check if user entered a positive number
System.out.println(messagePrompt2);// Print error message
} else {
incorrectInput = false;
}
} else {
input.next();
System.out.println(messagePrompt3);// Print error message
}
}
return returnValue;
}

Java - appending & passing values

I'm having trouble with passing a string and double to another class because it keeps on crashing at double cost = input.nextDouble();. Also, i was wondering if i am correct with the appending method used in public boolean addPARTDETAILS(String partDESCRIPTION, double partCOST).
For example. If the user enters the parts and cost, i want it to store that in a list and print it out with the cost appended.
Parts used:
brake pads ($50.00)
brake fluids ($25.00)
Note. Assuming that i have declared all variables and the array.
System.out.print("Enter registration number of vehicle");
String inputREGO = input.next();
boolean flag = false;
for(int i=0; i<6; i++){
if(inputREGO.equalsIgnoreCase(services[i].getregoNUMBER())){
System.out.print("Enter Part Description: ");
String parts = input.nextLine();
double cost = input.nextDouble();
services[i].addPARTDETAILS(parts, cost);
//System.out.println(services[i].getregoNUMBER());
flag = true;
}
}if(flag==false);
System.out.println("No registration number were found in the system.");
public boolean addPARTDETAILS(String partDESCRIPTION, double partCOST){
if(partDESCRIPTION == "" || partCOST <= 0){
System.out.println("Invalid input, please try again!");
return false;
}
else{
partCOST=0;
StringBuffer sb = new StringBuffer(40);
String[] parts = new String[50];
for (int i=0;i<parts.length;i++){
partDESCRIPTION = sb.append(partCOST).toString();
}
System.out.println(partDESCRIPTION);
totalPART+=partCOST;
return true;
}
}
it keeps on crashing at double cost = input.nextDouble();.
It is highly unlikely that your JVM is crashing. It is far more likely that you are getting an Exception which you are not reading carefully enough and have forgotten to include in your question.
It is far more likely your code is incorrect as you may have mis-understood how scanner works. And so when you attempt to read a double, there is not a double in the input. I suspect you want to call nextLine() after readDouble() to consume the rest of the the line.
I suggest you step through the code in your debugger to get a better understanding of what it is really doing.
Just to expand a bit on Joop Eggen's and Peter Lawrey's answers because I feel some may not understand.
nextLine doesn't play well with others:
nextDouble is likely throwing a NumberFormatException because:
next, nextInt, nextDouble, etc. won't read the following end-of-line character, so nextLine will read the rest of the line and nextDouble will read the wrong thing.
Example: (| indicates current position)
Start:
|abc
123
def
456
After nextLine:
abc
|123
def
456
After nextDouble:
abc
123|
def
456
After nextLine (which reads the rest of the line, which contains nothing):
abc
123
|def
456
Now nextDouble tries to read "def", which won't work.
If-statement issues:
if(flag==false);
or, rewritten:
if(flag==false)
;
is an if statement with an empty body. Thus the statement following will always execute. And no need to do == false, !flag means the same. What you want:
if (!flag)
System.out.println("No registration number were found in the system.");
String comparison with ==:
partDESCRIPTION == ""
should be:
partDESCRIPTION.equals("")
or better:
partDESCRIPTION.isEmpty()
because == check whether the strings actually point to the exact same object (which won't happen unless you assign the one to the other with = at some point, either directly or indirectly), not just whether the have the same text (which is what equals is for).
Data dependent error.
if(flag==false);
System.out.println("No registration number were found in the system.");
should be (because of the ;):
if (!flag) {
System.out.println("No registration number was found in the system.");
}
And
partDESCRIPTION == ""
should be:
partDESCRIPTION.isEmpty()

Categories

Resources