• Post Reply Bookmark Topic Watch Topic
  • New Topic

How do I get my scanner to print or end with a specific word, and how do I print a method via a part  RSS feed

 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm having trouble getting my if statement to work within the scanner portion of my code. What I'm trying to do is have the system ask the person if the baby is asleep after printing out the first few nursery rhymes, then if no, print another song, if yes, end the sequence. Then after the abc song, if the user types continue, I want the neverEnds song to print. If yes, I want the sequence to end. However, it does not seem to be working. Right now the scanner will let me type yes or no, but it has no impact on whether or not the code prints a new song, or loops the last song. It won't print or activate anything. What I really want is for the ABC song to print if the user puts no the first time, the sequence to end if the user puts yes, and after the abc is printed if the user did put no, for the neverending song to print indefinitely as long as the user types continue. However, the scanner should ultimately end when the user types yes. However, my search has been without any luck. Here code:

 
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First off, your code is confusing because you have a class named nurseryRhymes and you have a variable that has the same name. Furthermore, the variable named nurseryRhymes is a Scanner object. Your program is now kind of like that classic Abbott and Costello Who's on First comedy bit, except it's not that fun to read.

What's wrong with it is that you are using a Scanner object's equals method with a String argument. That's like comparing an apple with an elephant. A Scanner object will never be equal to a String object. This will always give a false result so your if statement will never succeed.

Choose better names for your variables so they reflect their purpose/function better. For Scanner objects, a name like input or console is more appropriate.

Also, the convention in Java is to capitalize class names so your nurseryRhymes class should be NurseryRhymes, with a capital N.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay so I changed my names up a little bit to make it easier to read, taking your suggestions. Now how do I get it so that yes and no create their corresponding outputs?

 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

Thank you for using the code button, but putting a whole verse onto a line makes them too long and the rest of the thread is illegible. I shall try to sort that out, so you can see the correct way to do it.
I shan't correct this thing, but you shou‍ld only use \n if you are asked for the LF character. I know a lot of books use \n, but it doesn't always work correctly. If you need line ends on the middle of a String try
frogs2 = String.format("little speckled frogs! %nRibbit, ribbit%n");
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Vach wrote:. . .
Who on earth told you that is a default constructor? You never see a default constructor because it only exists when you don't write a constructor yourself.
I am still finding it hard to work out how your Scanner tests whether the baby is asleep without waking him up.
:
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Already told you this before but I guess you need it one more time: if you compare a Scanner object with a String object using equals, you will ALWAYS get false. Look at line 91 carefully. Which object will be the String ”no” that you entered? (Hint: it's NOT input) Is that what you're checking on line 93? Same line of questioning for lines 99 and 101.

Maybe input is not a very good name after all since you still seem confused as to what it is.

Remember, console is a Scanner object so checking if it's equal to a String value will always give you false

In other words, String objects can only ever be equal to other String objects. A String object can never be equal to a Scanner object and vice versa.

Can you see what you're doing wrong yet?
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, when comparing Strings and you have one that's a literal, it's always better and safer to call the equals() method on the literal, like so:

String literals are full-fledged String objects, so you can call methods on them just like you can any other String object. The equals() method will always return false when passed null.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lastly, String.equals() is case sensitive so if the value passed does not match the case exactly, equals() will return false:
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . . . .
But the Scanner's next() or nextXXX() methods never return null; if they cannot find a next token they throw exceptions. The only Scanner methods which return null are those whose names begin find.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Junilu Lacar wrote:. . . . . .
But the Scanner's next() or nextXXX() methods never return null; if they cannot find a next token they throw exceptions. The only Scanner methods which return null are those whose names begin find.

That would mean you needed to look into the documentation and verify that it was so. When you're not sure or don't really care to dig into whether or not null is a possible value, calling the method on the string literal is generally safer and will succeed regardless of whether or not the value you are checking can actually be null. Just one less thing to worry about.

EDIT: and when I say "you needed to" I mean that in a general way, as in, "you, whoever is writing the code"
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good point.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, so taking you suggestions into account, and digging deeper into my research, I have solved my problem. Thank you for your guy's help. I just started my coding class two months ago so I am still quite new at this, although I am getting better everyday. This project combined concepts that baffled me somewhat, although now I feel more comfortable with them. In regards to my naming, I will continue to work on that, as I do see it is easier to read code when the names of variable, classes, methods and the like are different. Sorry if I didn't get it write away, I'm both new and sick right now and my sick brain likes to mess with me. Here is my final code if you are curious to see what I did/changed and once again thanks for your help. This site is much nicer to newbies like myself then the other forum I was previously using. Have a great day. (note, I also made the lyrics part of the code easier to read for this website. That's not what it looks like in my compiler.) Code:

 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Vach wrote:. . .
What are you iterating backwards there? What does the byeFrog number mean? Adding comments to explain those points might be helpful. Do you need both byeFrog and the loop index?
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What I was trying to do was, since in the song, it counts down 3 little frogs, then 2 then 1, I needed a loop for that. Then I realized that in the song, it says 3 little frogs, one jumped off, now there are 2 or something along those lines and I needed a second decreasing value in there. My teacher did say, "you are suppose to pass in int to the method so that you do not have to code it in main in order to print out expected output. Your design makes program complicated enough so that you have to struggle through it and it is not a good design to start with. #2 You need to use equalsIgnoreCase to compare user input. Otherwise, everything is fine." What did she mean by that. As far as I know, we haven't used equalsIgnoreCase in class yet.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh and byeFrog means the value when one frog has disappeared, that is the number that will show up.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Vach wrote:What I was trying to do was, since in the song, it counts down 3 little frogs, then 2 then 1, I needed a loop for that. Then I realized that in the song, it says 3 little frogs, one jumped off, now there are 2 or something along those lines and I needed a second decreasing value in there. My teacher did say, "you are suppose to pass in int to the method so that you do not have to code it in main in order to print out expected output. Your design makes program complicated enough so that you have to struggle through it and it is not a good design to start with. #2 You need to use equalsIgnoreCase to compare user input. Otherwise, everything is fine." What did she mean by that. As far as I know, we haven't used equalsIgnoreCase in class yet.


That's disappointing. I wonder how you're supposed to know the difference between "good" and "bad" design. Were you given any guidelines as to what would constitute a good design? Were there any examples discussed that contrasted two version of code as good design vs. bad design?

Google will turn up lots of examples for using Java String.equalsIgnoreCase - if your instructor said you should use it, you should go and learn how to use (it's not that hard) even if it hasn't been discussed in class.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, I don't know how we are supposed to either. She doesn't give any examples in class, only small ones from our homework. The examples she gives arn't in the grand scheme of good designs and bad designs, she just gives examples on small topics like while or do-while statements. For big projects like this, she just leaves us on our own to figure out what we don't know or don't get and to piece together the small concepts we've been taught. She has never given us any guidelines as to what constitutes a good design. Generally, after she mentions a topic, like equalIgnoreCase that I don't know, I will look up how to use it. And I plan to in this case. However, she never had told us to use that in the first place so I never knew about it. She marked everyone in our class off for it. Yet, she wonders why so many kids copy off of others in her class. I don't, however, thats why I go on forums for help, I feel like its trying to find an answer vs copying someone. She called out half the class for copying for this project, and this has happened the whole year. Although I like coding, and I really do, there is something so cool about figuring out how to accomplish a problem, and I might want to pursue it for a career in the future, she makes it almost unbearable in class to the point where I'm glancing up multiple times until the bell rings.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also any ideas why this was a bad design, so I might know for the future? Because I know everyone codes differently, and there are many ways to get to a solution.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you've watched "The Walking Dead" you may be familiar with the Hershel Greene character who liked to say "Everybody has a job to do."  This kind of implies a division of labor. Somebody stands guard, somebody takes care of the little kids, somebody goes and mends the fence, etc.

Well-designed programs also have a division of labor. Tasks are farmed out to different methods, with each method having its own little job to do.  Your program only has main() and it does EVERYTHING. That's not good. In fact, there's nothing but BAD when you do that. It complicates the logic, it ties everything together, it makes it difficult to read the code, it makes it hard to test, it makes it hard to extend, and so many more bad things.

(Shameless self-promotion follows) Read through this thread and see the code that OP shared and compare it with the examples of code snippets that I share. It should give you a sense of what's good and what's bad design. I also mention quite a few concepts that will help you write better programs even if you're just a beginner.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, thanks for the Walking Dead reference, that made my days. Second, I kind of get what your saying, although I will need to take more time tomorrow looking over his code. However, I'm not quite clear on how I would have to adjust my code in order to have multiple methods. Because the only task that my main method is doing is calling the lyrics to the nursery rhyme, right? Then in my other class, I am looping the tasks and implementing a scanner. I may have to look more closely tomorrow, however I'm not quite sure how I would adjust my code to create a better design.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, you asked for it.  I will post a series of incremental improvements to your code to show you that it can indeed be broken down into smaller tasks. Stay tuned.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First increment: Starting to make things a little bit more object-oriented (OO)

Objects are about behaviors and the data related to those behaviors. The code for "behaviors" in your program are all in the static method main() of your FullNurseryRhymes class. The related data, however, is all in the NurseryRhymes class. That's not object-oriented. Even in a general, non-OO sense, it's not well organized.  Data and commands that use that data should be kept closer together. So, we'll fix that a little bit.

Let's look at this section of your code:

This code (lines 11-18) is really interested in strings that are in the NurseryRhymes class. There is nothing in the FullNurseryRhymes class that it tries to access. In other words, this code has a stronger affinity to the NurseryRhymes class than it does to the FullNurseryRhymes class. So, let's move that code closer to the data that it wants to get at. We're going to copy it into a new method in the NurseryRhymes class.

Here, we just copy/paste the code directly from FullNurseryRhymes. We will get a couple of compile errors because of the rhymes references, so we delete them in the new method because they are no longer needed.

Finally, we delete the code that we're moving from FullNurseryRhymes and we replace it with a call to the new method in NurseryRhymes.

We just completed an Extract Method refactoring.  That's one small step towards objects, one big step giant leap for design. 

Now, do you think you can try to do that for other sections of your code in main() or do you need another example increment?
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's what you should be trying to get in the FullNurseryRhymes main() method:

Even with just three extractions, your main() code will already be noticeably smaller and cleaner.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Do you see how the analogy to Hershel's "Everybody has a job to do" thing applies to what I just did? 

The NurseryRhymes has just been given three little "jobs" that it will be responsible for doing.  Each job (method) can easily get to the information it needs because it's now closer to that information and there's no reaching across the ether into another class to do that. The FullNurseryRhymes class does not even need to know about the text of those rhymes because it just lets the NurseryRhymes class take care of managing that information. The only thing the FullNurseryRhymes class needs to "know" is what commands (methods) it can give (call) to make a NurseryRhymes object to do something. When asked to do something, a NurseryRhymes object will happily comply with that request.

Does that make sense?  Do you get a sense of why this is a better design?
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And because the FullNurseryRhymes class really has no need now to get to those Strings for the rhymes, you can delete some of the getXXX() methods in the NurseryRhymes class.  Preventing access to the String values in NurseryRhymes by other classes makes the class have better encapsulation.  Ultimately, you want to delete all of those getXXX() methods and only have methods that "tell" a NurseryRhymes object to display specific rhymes.

That's one step closer to a better design. It's still not going to be that good but it will at least be a LOT better than what you started out with.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's another aspect of design that's very important but is often overlooked by many programmers, even experienced ones.  Good names.  Goods names make your code easier to understand and they make your code sensical.  Poorly chosen names make your code difficult to read and understand. Bad names mislead the reader. They make your code lie to the reader and make them think the code does things that it doesn't do.

Now, if the code in the FullNurseryRhymes.main() method simply calls various rhyme methods of a NurseryRhymes object, does the name "FullNurseryRhymes" really fit what it does? Does the name match what is actually happening in the main() method code? I would say, "Definitely NOT."

What would be a better name for the class then? What name can best explain what happens in the main() method?  How about RhymesPlayer? RhymesJukebox? RhymesCarousel?  I don't know, you tell me what name you think will give the reader a better sense of what the class actually does.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Poor design choices in your code will often be common enough that they actually have names. We refer to them as "code smells." Martin Fowler's book Refactoring: Improving the Design of Existing Code catalogs about twenty or so code smells.

There is a similar list of code smells here: https://blog.codinghorror.com/code-smells/

If you go through that list, you will see that I addressed a Data Class code smell with that Extract Method refactoring. I also hinted at an Uncommunicative Name code smell when I asked about the appropriateness of the name of your class.

Read through the descriptions of smells on that page and see if you can recognize more of them in your code. Developing the ability to recognize code smells for what they are starts with knowing that they even exist in the first place and understanding how they manifest themselves in your code. That's about as good a set of design guidelines as you can find.

Another set of design guidelines that you should learn and follow diligently are the Four Rules of Simple Design
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Junilu Lacar. Your posts have really helped me in creating code with a better, less linear design in mind. I feel I am creating better code now that is more easily readable. If you are curious to see how I have improved, you ca either check some of my more recent posts or I can provide you an example of how I have improved here. I had almost forgotten to thank you for your help! It was really appreciated and is helping me further my interest in coding. Thank you.
 
David Vach
Ranch Hand
Posts: 105
3
Chrome Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And by more easily readable, I mean everything is not in the main method, and much of the parts of my code are in their won methods, to be called later.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!