• Post Reply Bookmark Topic Watch Topic
  • New Topic

check for nonnumeric values entered via the java.util.scanner?  RSS feed

 
crystal smith
Greenhorn
Posts: 10
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i am creating a simple change calculating program and I need to have it check it for user errors (entering non numeric values, or entering more cash due than cash tendered) any help on this would be appreciated. Thanks! Crystal S.
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What have you done so far? Post your code and use code tags.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
crystal smith wrote:i am creating a simple change calculating program and I need to have it check it for user errors (entering non numeric values, or entering more cash due than cash tendered) any help on this would be appreciated.

Well, about the only thing I can suggest (without code) is that you have TWO problems here, not one.
1. User input.
2. Calculating "change".
And you should keep them completely separate. In fact, you might even consider writing two separate classes: Input and ChangeCalculator and simply putting them in the same package (changecalc?).

Winston
 
Greg Hatt
Greenhorn
Posts: 14
Java Linux Suse
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey there,

I'm fairly new to Java myself but I will certainly give my suggestion. As I understand if you want to check if a value entered is numeric and you want to calculate the change. The way to do this would be with two separate methods. The scanner class does have a method to see if the input is numeric but I find it simpler to work with the String value. So, your method to check if user input is numeric might look something like this:

Or you could use regular expressions to see if it matches a numeric format, like this:

As was mentioned above though, it'd be easier to give advice if the code was posted.

 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Plus one for using regular expressions (regex). Here's a few more notes in that vein.

"\\d+" will get you whole numbers, but what is needed is "change", so I'm assuming we needs two decimal places. That would be:

"\\d+.\\d\\d"

But then if we wanted to enter just "1" for $1.00, we couldn't. We could change the regex to:

"\\d+(.\\d\\d)?"

Then we could enter a whole number, or if we entered a decimal point (dot), then we have to enter two more numbers. Also, in this case, make sure you use matches() and not find(). matches() will match the entire string while find() will match any part of the string.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:We could change the regex to:

"\\d+(.\\d\\d)?"

Then we could enter a whole number, or if we entered a decimal point (dot), then we have to enter two more numbers. Also, in this case, make sure you use matches() and not find(). matches() will match the entire string while find() will match any part of the string.


Almost... there is an issue with this regex.

Hint: Try this regex on something like "123R45".

Henry
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is a simple way to do it with a Scanner. But what do you want? Do you want to check whether a number is an int (not integer)? Or do you want to ensure that the Scanner gives you an int and rejects non‑numeric input?
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:
Knute Snortum wrote:We could change the regex to:

"\\d+(.\\d\\d)?"

Then we could enter a whole number, or if we entered a decimal point (dot), then we have to enter two more numbers. Also, in this case, make sure you use matches() and not find(). matches() will match the entire string while find() will match any part of the string.


Almost... there is an issue with this regex.

Hint: Try this regex on something like "123R45".

Henry


Oops. Yes. "\\d+(\.\\d\\d)?" It needs a backslash in front of the dot or it will treat it like a metacharacter.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote:Plus one for using regular expressions (regex).

Actually, I'd say its a minus-one (and Greg, don't worry, I haven't done it because I know exactly why you suggested it ), because it's a procedural solution.

And why is that bad? Because Java is an Object-Oriented language.

Regexes, for all their power, are procedural, and therefore any result you get from them might form part of an object; but otherwise they're only good for other procedures. And that perpetuates the business of "do this...then do that...then do something else...".

What you want (ideally), is an input class/method that returns a number - and ONLY a number.

Unfortunately, Scanner (which is the only real "input" class we have), fails hugely on that mark. It allows you get an int, or a double, or whatever, but only on its terms. And those are that it acts like an Iterator - a fact not widely understood (despite the fact that it implements Iterator<String>), because the documentation spends far too much time telling you HOW it works.

I'm a client and I want someone to enter a number. Why is that so difficult? in a perfect OO world, I'd have a method like:
public Number getNumber(InputStream s)
(or a class that implemented it), and that method wouldn't return until my user DID enter a proper number.

@crystal: Unfortunately, we're not there yet, so you have to live with Java as it is. Scanner.nextInt() or Scanner.nextDouble() will probably do what you want, and the nice thing about them is that if your user makes a mistake, the program will throw an Exception. How you choose to handle them is up to you, but at this stage, my advice is: don't.

HIH

Winston
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Knute Snortum wrote:Plus one for using regular expressions (regex).

I'm a client and I want someone to enter a number. Why is that so difficult? in a perfect OO world, I'd have a method like:
public Number getNumber(InputStream s)
(or a class that implemented it), and that method wouldn't return until my user DID enter a proper number.


This statement was bothering me, so I wrote the following. I believe it does everything Winston asks for and it uses Scanner and Patterns.

 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are not going to believe this, Winston, but I am about to disagree.
I think you need to start by finding out how Scanner works. Everybody goes on about the nextXXX methods but nobody ever considers the hasNextXXX methods.
Well, that ain't quite true. A long time ago Rob Spoor showed me how you can get an int from the keyboard and never suffer an Exception. That sort of thing would never work for a file unless you want to edit it as you read it (‍) but it will work nicely for the keyboard where you have a real user who can repeat real input. It means you don't need to use Exceptions for flow control, but it would be awkward to verify that an input actually has two digits after the decimal point.Obviously myScanner needs to point to System.in and you mustn't close it.

Now it looks as if you are going to get hundreds of instances of Scanner and have to let them out of scope and get GC‑ed, but why? You only need 1 instance, so only get 1 instance. And there is one way to get 1 instance: make it a static field in one class and use that one class. That is a utility class. It has only static members, and a private constructor because you never need any instances.Now you can translate the earlier code into the contents of this method:- public static int getInt(String requestMessage)...You can consider overloading that method so it only accepts input in a certain range or uses a different error message, etc. etc., but life will become interesting if anybody calls it with min == 200, max == 100! I shall leave it to readers to work out how to do that overloading.

At this point I am keeping quiet about how to read a whole line, mainly because I am too tired to write much more.

As for the money input, let's see if we can get away without using any Exceptions. You can read a double from the keyboard with exactly the same technique as for an int. But you really want a BigDecimal for money. Well, you can read a Big Decimal from the keyboard by a very similar technique.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A short while ago, I wrote: . . . life will become interesting if anybody calls it with min == 200, max == 100 . . .
I think you have no choice but to throw Exceptions if somebody is daft enough to pass max ≤ min.I am 99.99% sure those methods are not thread‑safe and would require “synchronized” on each at least for thread‑safety.

As for the Big Decimal, what you are looking for is a scale not greater than 2. That would permit an input like 12345.67 or 12345 or 12345.00, whereas the regex from earlier would fail for the second input shown. Yes, you can overload the Big Decimal method. What about this?
The bit about Scanner which causes the most confusion is nextLine. I haven't got enough energy to write about nextLine now.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:You are not going to believe this, Winston, but I am about to disagree.

In the words of Victor Meldrew; "I don't believe it."

I think you need to start by finding out how Scanner works. Everybody goes on about the nextXXX methods but nobody ever considers the hasNextXXX methods.

I don't think I've said you can't do it; what I'm saying is: Why is it so damn complicated? Why should I have to write a whole new loop every single time I want a value that needs some sort of validation? I've already told you to "get me an integer" Scanner, so bl**dy well do it.

Winston
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You mean the nextInt method would keep going until it finds an int? That's almost as surprising as what somebody wrote to the newspaper many years ago under the heading
What Will They Think Of Next?
From a wallclock advert:

No mains lead, no battery, just wind it up.

For the first time, I think that I have understood what you have against Scanner.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:For the first time, I think that I have understood what you have against Scanner.

I think perhaps I ought to redress the balance somewhat. Scanner is, no doubt, a lot simpler than other input classes, and offers a lot of options (too many, IMO) for inputting specific kinds of value. However, I get the feeling that the designers saw it merely as a replacement for StringTokenizer, rather than what it's actually become (and been touted as in books and courses): a medium for non-GUI user (or keyboard) input.

And the mere fact that the great example you gave above for how to input an integer properly doesn't even appear in the docs would tend to bear me out.

It seems to me they could have made it a lot more comprehensive for precisely that kind of use by including an OutputStream (that defaults to System.out) for messages - ie, if they'd made it more like Console (which, unfortunately, has its own problems).

I also wonder why they concentrated so much on primitives, when the version it was introduced with also gave us autoboxing, which basically makes returning an int or long or double redundant. Returning objects might have allowed the option of creating typed Scanners tailored to specific needs.

I wouldn't even have minded if they'd added the "user input" side of things later on as a nested class (Scanner.Input?), but 10 years seems like a long time to force beginners to write fiddly and long-winded procedures to do something that's almost always required within the first week or two of learning the language, and the rest of us to roll our own utility classes to do something so basic.

My 2¢

Winston
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Worth a d*mn sight more than 2¢.

I think they intended it for keyboard input all along; the example of how to get an int from the keyboard has appeared at the top of the Scanner documentation for as long as I can remember.
The “great example” was given me a long time ago by Rob Spoor. And you are right; it would be good to have that sort of thing in the documentation or the Java Tutorials. The nice thing about writing a utility class, as I often suggest, is that you then have a class which does it all for you and you can use it for ever and there is never any need to write inputScanner.nextInt() again. When I started learning Java (1.4) we all wrote keyboard input classes because you had to use BufferedReader. Or we found out about JOptionPane.
 
Anindya Roy
Ranch Hand
Posts: 76
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Worth a d*mn sight more than 2¢.

Thank you kind sir.

I think they intended it for keyboard input all along; the example of how to get an int from the keyboard has appeared at the top of the Scanner documentation for as long as I can remember.

But it doesn't; that's my point. It shows you how to get an int if everything goes smoothly; and that wasn't how I was taught to program. Otherwise (and user input being what it is, it's highly likely to be), it'll throw an Exception.

What's "great" about your (or Rob's) example is that it works. Every time; and without having to faff about with Exceptions. It's a proper piece of business logic, not what some designer "allowed" you to do. But it took someone like Rob to "explain" it to the rest of us; and that suggests to me a poorly designed (or documented) class.

The nice thing about writing a utility class, as I often suggest, is that you then have a class which does it all for you and you can use it for ever and there is never any need to write inputScanner.nextInt() again.

Don't get me wrong; I'm not saying that we shouldn't write utility classes. But requiring newbs to take all that onboard while they're still learning the basics of the language, simply because they want to get a few things from the keyboard into their program, is naff.

Winston
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please tell us what poor style there is in that tutorial link.

You can use a Scanner to check whether a String is an int or not.That will probably return true for a String like “12345 Campbell”.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote: . . . Thank you kind sir.
You're welcome Well deserved.
. . . if everything goes smoothly; and that wasn't how I was taught to program. . .
Agree
But it took someone like Rob to "explain" it to the rest of us; and that suggests to me a poorly designed (or documented) class.
Poorly documented or poorly tutorial‑ed, rether than poorly designed.

. . . But requiring newbs to take all that onboard while they're still learning . . .
Winston
Agree.
 
Kat Rollo
Ranch Hand
Posts: 62
Eclipse IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
RegEx may not be a great way to go with beginners.

hasNextInt() is pretty clean for beginning exercises.
 
crystal smith
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

 
Kat Rollo
Ranch Hand
Posts: 62
Eclipse IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use [code] tags so members can easily review your work.

Did you solve your problem?
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It doesn't look like this is real code. Have you tried compiling it?
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would have thought by now you would know about the code button, but I'll edit it and doesn't it look better
What a long method! You have no end of repeated code in there, so you should divide that and make at least six methods out of it. It would be more object‑oriented if you had a Payment class with an amount, and maybe a Coin enum with DOLLAR QUARTER CENT etc instances. But let's see if you can't make several methods for a start.

And what's all this for (;;)..., then? Who wants infinite loops? There must be some elegant way to terminate the loop,
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Avoid >= if you can. It is mich easier to understand > than >= even when you have had lots of practice. I got >= wrong yesterday
Try > 0 rather than >= 1
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Avoid >= if you can.


Wow, really? I tend to like >= and <=. Otherwise I'm always adding one or subtracting one and then getting them mixed up. Also (and this is a picky point) x < 5 is equivalent to x <=4 only for integers.
 
crystal smith
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I guess Im confused about the whole more than one method thing... how do you combine them into one?
 
crystal smith
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

 
crystal smith
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
well it is supposed to loop over and over again. Also it is supposed to check for non numeric values and insufficient amounts entered. I noticed that with this working version it allows the input of numbers like 3.455 and it calculates negative amounts with parenthesis around a positive number. I need it to catch an exception when the amount entered is not a dollar and cents amount, and when the cash tendered is less than the amount due so that the program will not terminate but simply start over. I'm definitely confused with the try / catch statements.
 
sai rama krishna
Ranch Hand
Posts: 536
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wonder why the for loop is empty

for(;;)
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You still have an infinite loop. There is no way to terminate it. If you believe what you have programmed you will spend the rest of your life entering numbers into that loop. You ought to find some sort of condition to terminate your loop.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you worled out how to terminate your loop neatly yet? I mean, without pushing the power button on your computer, flinging it out of the window, getting a meteorite to hit it or pushing ctrl‑C.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote: . . . I tend to like >= and <=. . . .
I said, if you can. When you start sticking + 1 and − 1 in your code, then you can no longer avoid >=.
You should avoid using relational operators on floating‑point numbers as far as possible because they are error‑prone.

My little grandsons can count to 10In that instance changing < to <= makes no difference to the output.
 
Knute Snortum
Sheriff
Posts: 4279
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In another thread, Crystal asked what is wrong with this code:



I'm assuming she wants a critique of her code.

  • Infinite Loop

  • As has been stated before, this program needs a way to exit. Otherwise you have to type ^C or Del or whatever your system interrupt is. What about typing "quit"?

  • Uninitialized Variables

  • cash and due can all be uninitialized. This produced compiler errors for me. You have these variables defined correctly but not initialized because they are assigned in a try block, so it's possible they will remain unassigned.

  • Use hasNextXxxx() instead of try/catch

  • Most (all?) of time, you don't want to use try/catch for expected input. Some people will say, "Typing 'ksjdfh' isn't expected, " but really, you do expect the user to mistype thing now and then.

  • Resource Leak

  • Your Scanner is never closed. In fact, it is opened again and again.

  • Bad Invalid Logic

  • Follow the logic is valid is false.

  • Method Too Big

  • This has also been mentioned. Here's a way to look at it: write out what your method does.

    1) Gets amount due.
    2) Get amount tendered
    3) Calculates change
    4) Displays change

    Each of these can and should be their own methods. Notice that (1) and (2) share a lot of code. What can you do about that?
     
    Campbell Ritchie
    Marshal
    Posts: 56546
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Knute Snortum wrote: . . .
  • Resource Leak

  • Your Scanner is never closed. In fact, it is opened again and again.
    . . .
    You must not close a Scanner pointing to System.in. What you have there is multiple Scanners which will eventually need garbage collection. Chances are the user will get fed up and terminate the infinite loop (preferably by one of the more spectacular techniques I listed earlier ‍) before she actually runs out of heap space.

    Useful critique, however Merits a cow.
     
    Kat Rollo
    Ranch Hand
    Posts: 62
    Eclipse IDE Java MySQL Database
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    crystal smith wrote:I need it to catch an exception when the amount entered is not a dollar and cents amount, and when the cash tendered is less than the amount due so that the program will not terminate but simply start over. I'm definitely confused with the try / catch statements.

    Catching non-numeric values from user input and looping to ask again for the correct input is quite a tricky thing with try-catch.
    You have to to clear/discard in the catch-block if you want the loop to work.

    Below is a simple code that asks the user for an int and prints that number. However if it is not a number, the program will ask again.

    Using try-catch this way is generally not encouraged (hasNext methods are preferred), but this just shows how it can be done.
     
    Campbell Ritchie
    Marshal
    Posts: 56546
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Kat Rollo wrote: . . . Below is a simple code . . .
    That looks overly complicated to me.Now, that is simple code. Without the poor use of \n, without the use of System.out for error messages, and without your potentially dangerous mistake. And at least 7 lines shorter.
     
    Kat Rollo
    Ranch Hand
    Posts: 62
    Eclipse IDE Java MySQL Database
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    As you can see, I posted an example for hasNextInt() earlier.

    I was just showing him how it can be done with try-catch too (since OP is using try-catch).

    Also, I did say:
    Kat Rollo wrote:Using try-catch this way is generally not encouraged (hasNext methods are preferred), but this just shows how it can be done.
     
    Campbell Ritchie
    Marshal
    Posts: 56546
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Yes, you did. And did you notice the potentially dangerous error in it?
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!