This week's book giveaway is in the Spring forum.
We're giving away four copies of Pro Spring MVC with WebFlux: Web Development in Spring Framework 5 and Spring Boot 2 and have Marten Deinum & Iuliana Cosmina on-line!
See this thread for details.
Win a copy of Pro Spring MVC with WebFlux: Web Development in Spring Framework 5 and Spring Boot 2 this week in the Spring forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Bear Bibeault
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh

no such element exception

 
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's my suggestion for how to fix this: use only scanner.nextLine(), and if you want a number, use Integer.parseInt() or Double.parseDouble().

Here's the problem: the Scanner class is designed to work with tokens, chunks of data, so to speak.  If you only use Scanner and tokens, you're fine.  The problem lies in that if you need to read in a String like "Fred Jones", you have two tokens, because the default separator for tokens is whitespace.  The standard solution is to use scanner.nextLine().  The problem arises when you mix scanner.nextInt() and scanner.nextLine().  nextInt() leaves a newline in the buffer and when nextLine() sees this, it thinks you've pressed the <Enter> key, so it assumes you've entered a empty String ("").  I used to counsel people to to do a scanner.nextLine() after each scanner.nextInt(), but I find this is not intuitive and it can become easy to lose track.  

So I just tell people now to use scanner.nextLine() for everything and parse out a number when you need that.  Also, you don't need the scanner.next() in the try/catch block.
 
Marshal
Posts: 72946
330
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
They are right on SO that many people have fallen into that pitfall; it is a poorly documented pitfall. I am surprised that you didn't fnd anything on your searches; search for Scanner nextLine in this forum and Java in General for user number 109202 (me). You will find various posts, but you may have to go back a long time. I have tried using nextLine() twice, but I now think the loop I showed you will work better. No, writing nextLine() twice will not cause you to read the same thing twice. The first time you will read the empty String at the end of the line, as I mentioned earlier. Make yourself a utility class; the hour or two spent writing it will be amply repaid by providing an input class you can use for ever.
I don't think you have presented us with good code, I am afraid. That method is far too long. It also has something I am dubious about, viz. catching unchecked exceptions. Input mismatch exception is a particularly bad exception to catch, since I have shown you how you can avoid it completely. Don't sue exception handling as an alternative to an if‑else, which is what you appear to be doing. Don't be scared about infinite loops; the code I showed you will not produce an infinite loop.
There is something else I am dubious about. Search my posts for how I would write else ifs. Note that I try to avoid <= and >= because < and > are less likely to cause confusion. You are using <= and >= and I am by no means dubious about them; I am quite definite about your if statements. Quite definite that they embody a logic error; I shall let you find it but I shall give you a hint: go hrough the different ages and work out how much a child will pay for each age. It shou‍ld be easy enough to go through the code with a pencil. You have confused yourself with <= and >= I am afraid.
Don't try file writing (line 56) inside your block like that. That is another thing that belongs in a method by itself. Don't try file writing without exception handling; don't declare that you throw the exception, but deal with it where you are writing. (You won't actually get an exception, but it is checked, so you must handle it somewhere.) Make sure you close readers and writers, otherwise there is a risk of having the file handle locked until you exit the JVM. And now that Java7 is here (so is Java9), you shou‍ld always use try‑with‑resources for closing readers and writers.
 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:Here's my suggestion for how to fix this: use only scanner.nextLine(), and if you want a number, use Integer.parseInt() or Double.parseDouble(). . . .

I disagree; correct use of nextLine() in a loop will work better. You are also losing the ability to test for the type of the input, or to use Scanner's ability to read multiple tokens per line.

Excessive use of myScanner.next() on the other hand, as you said, will cause tokens to be lost and incorrect matching of input to variables.
 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Adam Chalkley wrote:. . . trial and error . . .

Trial and error is a very bad way to write code; you need to put more thought into things like lines 7‑9. Can you work out what will go wrong if you enter “Adam Chalkley” as a single line? Or even better, if you enter your middle name as “Adam James Chalkley”?

At least if you enter the name all on one line, so you won't have problems with reading empty Strings.
 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:. . . if you need to read in a String like "Fred Jones", you have two tokens, because the default separator for tokens is whitespace.  The standard solution is to use scanner.nextLine().  The problem arises when you mix scanner.nextInt() and scanner.nextLine().  nextInt() leaves a newline in the buffer and when nextLine() sees this, it thinks you've pressed the <Enter> key, so it assumes you've entered a empty String ("").  I used to counsel people to to do a scanner.nextLine() after each scanner.nextInt(), but I find this is not intuitive and it can become easy to lose track. . . ..

Agree with that part. It can be easy to lose track of what has been read from the keyboard; even more so if the reading is in different methods. But my loop will ensure you really read the remainder of the current line, or the next line which isn't empty, from nextLine(). I think you shou‍ld reserve nextLine() for when you really want the whole line/whole remainder of the line.
 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Scanner isn't really designed for this sort of thing.
It seems to be designed for parsing structured input, for example rows in a file each of which have the same format (eg pipe separated or somesuch).

The problem arises when Scanner is used for UI input, which can take many forms and is often not structured in the same way, beyond the new line character.

I know it has lots of nice little things like the hasNextXXX and nextXXX methods, but with the number of times we see issues around it here I really do feel that people should be sticking to a good old BufferedReader and parsing the input based on what they expect it to be.
It would solve a hell of a lot of these problems.
 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Disagree; keyboard input is just as structured as input from a file with a predictable format. The problem is  that errors can slip in , e.g. writing 123456. instead of 123456 for an int. In the case of a file you would have to edit the file to correct such errors but you can repeat the entry easily enough at the keyboard. Text files will probably have been verified before storage, but keyboard input isn't verified.

The real problem with Scanner is what Winston said a long time ago: the documentation neither explains those problems nor how to correct for them; I haven't noticed recommendations for utility classes in books, only on this website. Also lots of books tell you that nextLine() does what it sounds like, i.e. returns the next line. It doesn't: it goes onto the next line and returns what is in between, and it would have been a lot easier to understand if it had been called remainderOfLine() or similar.
 
Dave Tolls
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But it's not.

Take the prior example that's currently causing the issue.

Having to adjust the input so that you understand that the first time round the loop you don't need to "absorb" a floating line end is not structured.
Not compared to the equivalent if it were a file:

Some Name|28
Another Name|42


That's the sort of thing that Scanner was built to handle.
 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think we are going to have to agree to differ.
 
Dave Tolls
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I think we are going to have to agree to differ.



I expect so.
 
Ranch Hand
Posts: 543
4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks guys much appreciated for all them =) I will get to them all,

but first to Knute I tried your suggestion but I didn't seem to work it still results in a line being skipped also now when I enter the number 2 to continue the program it throws a NumberFormatException

here is what I tried


 
Knute Snortum
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Adam Chalkley wrote:I tried your suggestion but I didn't seem to work it still results in a line being skipped also now when I enter the number 2 to continue the program it throws a NumberFormatException


Well, I would need more information to determine what's wrong.  "A line being skipped."  Which one?  "Throws a NumberFormatException."  What line?  Remember to TellTheDetails (that's a link).
 
Adam Chalkley
Ranch Hand
Posts: 543
4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ok so I found a better more compact way with less code to get what I wanted

anyway as you said Campbell trial and error is never a good thing so I'm going to ask with this code as an example whats going on,here is the code




thanks
 
Dave Tolls
Rancher
Posts: 4801
50
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I can see a scanner.nextLine() that doesn't seem to be associated with any input, on line 29, and then a scanner.next() left over in the catch block.

It's also probably an idea to re-prompt the user for the child name rather than silently sitting there expecting new input (line 19).

But as Knute says, you'd need to provide more information about your exception, including what was being input and the actual stack trace.
 
Adam Chalkley
Ranch Hand
Posts: 543
4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi Knute

it seemed to skip the input of the name of the child,on the first iteration it would work I could enter the full name but on further iterations it would skip it,

also with the code above it seemed to do the trick but yeah the Scanner class is pretty tricky still not 100% on it yet
 
Adam Chalkley
Ranch Hand
Posts: 543
4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi Dave

the scanner.next() is needed in the catch block or the program will be stuck in an infinite loop
 
Adam Chalkley
Ranch Hand
Posts: 543
4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Campbell

great advice =) I will do some more research on it and try look for them posts

also I agree the code is very sloppy it's kind of on top of one another the structure isn't great,I will try improve on this when I rewrite the program =)

thanks for the advice.

 
Campbell Ritchie
Marshal
Posts: 72946
330
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Adam Chalkley wrote:. . . the scanner.next() is needed in the catch block . . .

No, it isn't. I have already told you how you can avoid that exception. At least I think I did. The next() call goes inside the loop to consume and reject the unwanted input. You can find the loop here in a thread about how to write such an input class, or the link I gave you yesterday. You will notice there are slight differences of opinion about Scanner, but I like it as long as you understand what it is doing. Note the loop I showed there:-
  • 1: Can be relied on not to throw any exceptions unless you close the Scanner.
  • 2: Can have lines 5 and 6 in either order.
  • I am sure we have taught you that you mustn't close a Scanner reading from System.in already.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    wow thanks Campbell pretty nice block of code I can re use that quite a lot will bookmark it =)

    yes I don't think I closed the scanner object in my code which indeed did lead to a resource leak I used the System.exit() method when the program is about to terminate I am guessing that is bad practice?

    this was the video I followed to get he code to work but I will now go back and add the block of code you came up with

    https://www.youtube.com/watch?v=sWxiFBKe0-M

    this video does give a solution but it is poorly explained and don't really understand what he means

    thanks

     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    sorry I read that wrong the first time,did I close the scanner reading from System.in before the program was about to terminate?

    thanks
     
    Campbell Ritchie
    Marshal
    Posts: 72946
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    System.exit won't cause you any problems in a single‑threaded application as you have here, but it can cause nasty problems in a multi‑threaded program. Avoid it therefore; you are far better directing program flow back to the end of the main method, where the JVM will shut down gracefully.
    You need to take what Eclipse warns you about resource leaks with a pinch of salt, otherwise you will be closing Scanners reading from System.in. You must of course close files and similar.
    I haven't got the time to watch that video, but I suggest you beware of badly‑explained videos.
    If you have a utility class, you can write things like this:-and it will cope with all the following versions of input:-You do need to write the nextLine() method to discard empty lines.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    thanks Campbell I'll try implement that =)
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Campbell

    just getting back to the code you shared with me I just have a few questions,would be much appreciated if you could help me out with them =)



    I'm playing around with it,I'm not sure how exactly it works or how it works

    I know it does because I can see that in my program but not sure how it does

    the while loop is where I'm stuck at

    first I don't understand !scan.hasNextInt() this means while the scanner does not have an next int but what happens if it does for example if we enter 19 and 23 what will happen?

    we use scan.next to get the input? why don't we use scan.nextInt?

    thanks

     
    Knute Snortum
    Sheriff
    Posts: 7111
    184
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    we use scan.next to get the input?


    No, we use scan.next() to skip input when the input is not an int.

    why don't we use scan.nextInt?  


    We do, on line nine, but only after the Scanner has an int in its buffer.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    thanks Knute that makes sense,



    just a quick follow up how come in the first line of code i get an exception and in the second y gets ignored?

    thanks
     
    Knute Snortum
    Sheriff
    Posts: 7111
    184
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator


    Are you entering 5<space>y?  I don't get an exception when I do that.  What is the full text of the exception?
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    hey Knute

    yeah I think that was the problem I forgot to enter a space sorry

    anyway I want to post this code one more time you guys already helped me with the solution =) I just want to know why it skips the enter the childs name after the first iteration I will put in comments which I think is happening



    I followed the steps and I see no reason that input line gets skips each time I made sure I consumed the end of line character

    thanks
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    here in this example this code works how I would expect



    but in the code above this post it doesn't work how I would expect it to,even though I have pretty much used the code in the same way?

    thanks
     
    Campbell Ritchie
    Marshal
    Posts: 72946
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Adam Chalkley wrote:. . . when I enter 5 y I get an exception . . .

    You are entering 5 which is read as a valid int; the following token is y which the next line will try to interpret as an int too. Which is isn't.
    If you ask for age, then 5 is a valid input for 5 years, but you cannot include the y as the units. Had you used the loop which Rob taught me, you would have a “try again” message, and no exceptions.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    thanks Campbell,I'm still not too sure why the code two posts above wouldn't work but anyway I converted the program into a gui,I have to add more features and will do that some time soon I will post all the code here it's quite long because it consists of a lot of questions if you guys could tell me what I need to improve on that would be great and how I would go about doing it,this is quite long for coderanch standards but I'll post the whole program.


    I will admit that I have not mastered the OOP approach and in my opinion I'm pretty weak there but with time this may improve?

    anyway here is all the classes

    Child.java


    FormEvent.java


    SideBar.java


    SideBarListener.java




    TextListener




    TextPanel.java





    ToolBar.java


    Main.java



    thanks
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator



    I've run into a snag when I close the program(click x)

    this block of code runs




    but what happens is it creates a new instance(frame or window) of the gui and displays the message do you want to close,now I understand why this happens because I am passing  a new Gui() as an argument but how I do I pass the current Gui or JFrame

    I can't do it like this,



    because this will be referring to the anonymous class itself,I need a way to pass the gui that was created when main starts,


    thanks
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    one obvious fix would be to put the close operation in main but I DON'T want this handled by the main method

     
    Campbell Ritchie
    Marshal
    Posts: 72946
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Don't catch headless exception, which is unchecked and can be allowed to propagate if one is ever thrown. That means you have a computer without a nice screen.
    Don't declare your constructor as throwing IOException; handling that sort of exception shouldn't be done by the GUI. Any such exceptions need handling elsewhere.
    Don't use System.exit; you are now in a multi‑threaded context, so System.exit might harm something going on in another thread. I suggest you call dispose() on your JFrame object if the close option is chosen.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    thanks Campbell much appreciated =)

    I'm trying to create an admin mode and I have run into another little snag and from what I read it's possible if synchronised but I thought with a few simple gates or flags(booleans) I could simulate this process oh boy was I wrong,the logic looks right to me but it just gets stuck in an infinite loop which keeps printing "invalid choice"

    so the first question is it possible to even achieve this without synchronising the thread?

    and secondly if so,how can this be done,what in my code needs to be changed,

    thanks I'll post the code below of what I've come up with




    thanks
     
    Knute Snortum
    Sheriff
    Posts: 7111
    184
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I don't think this is doing what you want it to.  First, get rid of unnecessary parentheses: Next, check for null before using the object: Now that && in the middle has a higher precedence than ||, so you will effectively have which I bet you don't want.  So what do you want?  Probably "if name is null or empty or if the age is null or empty."  So do you really want an && in the middle?  Probably not.  And since all logical operators are now ||, you don't need parens:
     
    Saloon Keeper
    Posts: 8228
    71
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    You've got:
    and what you need is

     
    Knute Snortum
    Sheriff
    Posts: 7111
    184
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Reusing GUI fields for a purpose other than what they're labeled to do is a bad practice.  Better to have a "Is this an admin?" checkbox and a popup that prompts for a password.  Or something else like that.
     
    Carey Brown
    Saloon Keeper
    Posts: 8228
    71
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    You don't need to flush() after every call to write() and probably not at all.
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    thanks guys for all the help I changed the code =)

    but it still seems to be stuck in a infinite loop

    also I agree Knute that would be a much better idea,I'm going to try implement that but first I want to see if I can get my idea to work,which I have my doubts,

    do you think it's possible to accomplish what I'm trying to do with just booleans?

    thanks
     
    Adam Chalkley
    Ranch Hand
    Posts: 543
    4
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    here lies the problem



    I basically want this code to get run when we are in admin mode and click the button again BUT e.getSource already equals button so this code gets executed automatically,

    so how would I get a second click or second event,the first event when the button is clicked will make e.getSource = the btn after this button is clicked is there anyway to re assign e.getSource so I can get a second click?
     
    Tongue wrestling. It's not what you think. And here, take this tiny ad. You'll need it.
    Thread Boost feature
    https://coderanch.com/t/674455/Thread-Boost-feature
    reply
      Bookmark Topic Watch Topic
    • New Topic