• Post Reply Bookmark Topic Watch Topic
  • New Topic

Scanner (System.in) question  RSS feed

 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
I'm participating in www.hackerrank.com 30 Days of Code challenge and I just completed Day 1 but I have a question.  The problem is https://www.hackerrank.com/challenges/30-data-types and I already passed it but I want to find out if my solution is truly correct.   The problem wants to concatenate and print out the two string variable on a new line with the s variable being printed first.

As instructed I created a String variable which I named "z".   In order to capture the entire input  of "is the best place to learn and practice coding!"  I  initialized my z variable as  .   Is this correct or was there a better way of handling this?

Thank you!
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:... was there a better way of handling this?

Don't think about the better ways yet, think if it is correct. No, it isn't.

Let's assume we are talking about the strings part.

Instructions wrote:When we concatenate HackerRank with is the best place to learn and practice coding!, we get HackerRank is the best place to learn and practice coding!

Further comment from instructions wrote:/* Concatenate and print the String variables on a new line;
        the 's' variable above should be printed first. */


So, in my understanding you need to concatenate what you have initialized already (in your case - s) with a user's input and place result in the variable you have declared.
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
HackerRank wrote:

And remember in the future not to follow such advice as it is suggested in the work template provided to you. I'm talking about the last line. If you close the Scanner which pointing to the System.in, you may never open it again.
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Liutauras Vilda wrote:So, in my understanding you need to concatenate what you have initialized already (in your case - s) with a user's input and place result in the variable you have declared.

The bolded part would be incorrect.

This is given:

The user's input is already saved in the second String variable. All you need to do after that is exactly what it says:

That says nothing about saving the concatenated values to a variable.
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, re-read once again what is given. I was wrong, my apologies. Please follow Junilu's advice.
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So I think my question isn't clear.   I appreciate the information already given to me but I don't think my actual question is answered.     Especially regarding not using .close(). 

My question applies to this line of code. 


For me to have captured the entire input  "is the best place to learn and practice coding! ".    I had to use both scan.next() and scan.nextLine().  Is this the correct way to have captured the entire line " is the best place to learn and practice coding! " in the variable " z " ?
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:So I think my question isn't clear.   I appreciate the information already given to me but I don't think my actual question is answered.     Especially regarding not using .close(). 

My question applies to this line of code. 


For me to have captured the entire input  "is the best place to learn and practice coding! ".    I had to use both scan.next() and scan.nextLine().  Is this the correct way to have captured the entire line " is the best place to learn and practice coding! " in the variable " z " ?


That was supposed to have been read as I appreciate the information about  not using .close().
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:Is this the correct way to have captured the entire line in the variable " z "

Is it what instructions ask you to do?
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Probably the exercises there asking you very precise things.

So it is mentioned there:
1. Declare second ... and String variables. (ok, that could be 'z' for instance)
2. Read and save ... String to your variables (so, that means need to be saved to 'z')
3. Concatenate and print the String variables on a new line the 's' variable above should be printed first.

Does that gives some insight?
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Liutauras Vilda wrote:
Lisa Austin wrote:Is this the correct way to have captured the entire line in the variable " z "

Is it what instructions ask you to do?


The instruction says
"Read  lines of input from stdin (according to the sequence given in the Input Format section below) and initialize your  variables."

So I used the .next() and .nextLine() which information regarding this is provided in the tutorial.  It works but the tutorial isn't specific regarding whether I would have to use both to capture an entire sentence or not.  I passed the assignment but I'm just trying to find out for my own understanding whether I should have used both to accomplish the task or if missed something. 
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:I passed the assignment

Since you have passed, I think I can let myself a bit more.

I'd think that supposed to be:
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And yet this sounds confusing now

/* Concatenate and print the String variables on a new line;
        the 's' variable above should be printed first. */


That sounds like need to print 2 String variables
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe then it just (instead of lines 5 and 6 above):
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Liutauras Vilda wrote:Probably the exercises there asking you very precise things.

So it is mentioned there:
1. Declare second ... and String variables. (ok, that could be 'z' for instance)
2. Read and save ... String to your variables (so, that means need to be saved to 'z')
3. Concatenate and print the String variables on a new line the 's' variable above should be printed first.

Does that gives some insight?


So maybe I'm not being clear.  I accomplished 1 - 3.  I understood #3 without issue prior to posting my question.       .   All I want help with is verifying that using .next() + .nextLine(); is the correct way to read and save String to your variable  (#2 ) .   Sorry if I am off in left field regarding your point here.     
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:All I want help with is verifying that using .next() + .nextLine(); is the correct way to read and save String to your variable  (#2 )

First have a cow

It seems you're talking about the oldest trick in the world. Yes, I think you're right, because after nextDouble() there will be something in buffer left, and you'll need to read it first in order to get next input string as expected.

Campbell knows very well about it Lets hope he sees this thread.
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Liutauras Vilda wrote:
Lisa Austin wrote:All I want help with is verifying that using .next() + .nextLine(); is the correct way to read and save String to your variable  (#2 )

First have a cow

It seems you're talking about the oldest trick in the world. Yes, I think you're right, because after nextDouble() there will be something in buffer left, and you'll need to read it first in order to get next input string as expected.

Campbell knows very well about it Lets hope he sees this thread.


Thank You and I apologize.  I looked over my OP and I understand where I led you guys off on the wrong direction. 
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lisa Austin wrote:
So maybe I'm not being clear.  I accomplished 1 - 3.  I understood #3 without issue prior to posting my question.       .   All I want help with is verifying that using .next() + .nextLine(); is the correct way to read and save String to your variable  (#2 ) .   Sorry if I am off in left field regarding your point here.


Scanner behavior can be pretty confusing to predict sometimes so it pays to experiment with it.  If you just have scan.next() you won't be able to capture the entire text of "is the best place to learn and practice coding!" because scan.next() will only give back the next word in the input stream, not the entire sentence.

If you just have scan.nextLine(), you will force the user to enter all the values at one go, like this:

1 5.0 is the best place to learn and practice coding!" (ENTER)

If the user hits ENTER after each value, like this:

1  (ENTER)
5.0 (ENTER)

They wouldn't even have a chance to enter the string value, which would end up being an empty string.

So, as far as I can tell from my experimentation, what you did with scan.next() + scan.nextLine() gives the user the most flexibility for entering the values that will be assigned to the variables.

That is, the user can choose to enter the values a few ways and you'd have the expected values properly assigned to the variables:

This works:
1 (ENTER)
5.0 (ENTER)
is the best place (ENTER)

This also works:
1 (ENTER)
5.0 is the best place (ENTER)

And this also works:
1 5.0 is the best place (ENTER)
 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Even this works:

1 (ENTER)
5.0 (ENTER)
(ENTER)
(ENTER)
(ENTER)
(... ENTER)
is the best place (ENTER)

Apparently, scan.next() will force the user to enter something other than whitespace(s).
 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:
Lisa Austin wrote:
So maybe I'm not being clear.  I accomplished 1 - 3.  I understood #3 without issue prior to posting my question.       .   All I want help with is verifying that using .next() + .nextLine(); is the correct way to read and save String to your variable  (#2 ) .   Sorry if I am off in left field regarding your point here.


Scanner behavior can be pretty confusing to predict sometimes so it pays to experiment with it.  If you just have scan.next() you won't be able to capture the entire text of "is the best place to learn and practice coding!" because scan.next() will only give back the next word in the input stream, not the entire sentence.

If you just have scan.nextLine(), you will force the user to enter all the values at one go, like this:

1 5.0 is the best place to learn and practice coding!" (ENTER)

If the user hits ENTER after each value, like this:

1  (ENTER)
5.0 (ENTER)

They wouldn't even have a chance to enter the string value, which would end up being an empty string.

So, as far as I can tell from my experimentation, what you did with scan.next() + scan.nextLine() gives the user the most flexibility for entering the values that will be assigned to the variables.

That is, the user can choose to enter the values a few ways and you'd have the expected values properly assigned to the variables:

This works:
1 (ENTER)
5.0 (ENTER)
is the best place (ENTER)

This also works:
1 (ENTER)
5.0 is the best place (ENTER)

And this also works:
1 5.0 is the best place (ENTER)


Thank you!  I tried on Eclipse to figure out if I needed a .next () or a .nextLine()  and only the two combined seemed to capture the entire sentence but I thought it was odd that I had to use both.    Now that I am playing around with it some more ( after what you said ) it seems that the .nextLine() works  if I enter only the sentence and not the other data first.  The way I was testing it on the website and in Eclipse was copy and paste the sample input


12
4.0
is the best place to learn and practice coding!


So the .nextLine() didn't work but both .next() + .nextLine() did.

But when I removed the int and double and left only the String and entered only


is the best place to learn and practice coding!


then .nextLine() worked.

 
Junilu Lacar
Sheriff
Posts: 11477
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The good thing with using next() first is that it skips all leading whitespaces.  That means that if you used only nextLine() and inadvertently (or purposely) entered:

(space)(space)(tab)is the best place (ENTER)

then your string variable would contain all that leading whitespace and you'd display "HackerRank (space)(space)(tab)is the best place".  By using next() + nextLine(), you practically guarantee that you'll get the output you'd expect, without any leading whitespaces that would mess the display up.

 
Lisa Austin
Ranch Hand
Posts: 178
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:The good thing with using next() first is that it skips all leading whitespaces.  That means that if you used only nextLine() and inadvertently (or purposely) entered:

(space)(space)(tab)is the best place (ENTER)

then your string variable would contain all that leading whitespace and you'd display "HackerRank (space)(space)(tab)is the best place".  By using next() + nextLine(), you practically guarantee that you'll get the output you'd expect, without any leading whitespaces that would mess the display up.


That makes complete sense.  Thank You very much   
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . 1 5.0 is the best place to learn and practice coding!" (ENTER) . . .
That shou‍ld read
1 5.0 Coderanch is the best place to learn and practise coding!" (ENTER)

Campbell knows nothing (or less) about this thread. I seem to have been busy, as often happens on a weekend.
I agree with Liutauras about HackerRank giving you dangerous advice about closing a Scanner pointing to System.in.

If you go through the documentation for Scanner, you find it uses a “delimiter”, which is defined as a regular expression. You can find out the default delimiter's regular expression simply by running this sort of code:-
System.out.println(new Scanner("Campbell is a right nuisance.").delimiter());
The documentation tells you about the “delimiter pattern, which by default matches whitespace.” It actually takes any number > 0 of whitespace characters as a delimiter, and that includes space, tab, hard space, return, line feed and several other characters. So if you tell your Scanner to look for anything except nextLine() or one of the two (beware: overloaded) findXXX methods (1 2), it will use the delimiter. Let us assume you have not changed the delimiter.

Now, as long as you use the default delimiter, the Scanner will ignore all whitespace between where you are now and where the next token begins. Whether you enter
123
or



123
or
    123
doesn't make any difference; the Scanner will ignore everything whitespace preceding the token 123. It will stop when it reaches the next whitespace character (including line ends). You can read 123 with next() or nextInt() or nextBigInteger() or nextDouble() or several other methods. If you read the details about those methods, you will find the same text causes different things to be returned.
Now, following a call to nextBigInteger() with nextAnythingWhichIsntNextLine() causes you to keep going until you find something not whitespace. But nextLine is different. I often quote this old post of mine. Have a look in your book and see what it says nextLine does. Many books get it wrong, saying it returns the next line. It doesn't. It returns whatever is between where you are at present (half a character after the 3 in 123) and the next time you have a line end character, which to all intents and purposes mean when you push the enter/return key.
If you write something after 123 before you push enter, that writing constitutes the nexLine(). If you write nothing after 123 before pushing enter, that nothing constitutes the nextLine(), and that is an empty String "" with no characters in. So writing
inScan.next() + inScan.nextLine():
will return exactly the same from an input of "Lisa↩" as would next()fullStop. Take ↩ to mean enter key. Similarly if you have a line like
StackOverflow is the best place to learn programming.
the next() call will return "StackOverflow" and the nextLine call will return the remainder of the line "is the best place to learn programming." but if you try to concatenate that with the + operator, your CPU will burn out.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you want to miss out whitespace, this is one way to do it:-Prasanna Rahman helped me develop that code by finding a major error in an earlier version.
 
Liutauras Vilda
Sheriff
Posts: 4916
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:So writing
inScan.next() + inScan.nextLine():
will return exactly the same from an input of "Lisa↩" as would next()fullStop.

And if our intention is to have a more universal method assuming we don't know if user's input was read before and if there were something left in a buffer from previuos read or not, wouldn't be a good practice to have a method looking like?
To me looks like this case works in both scenarios (and always): [1] when there were an input read before current input read [2] when there were no user input read before - always reads a full current line, which is what most users expects from this method call.

[edit] Didn't see one post above this one before I submitted mine.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have only looked at that briefly, but it looks a good alternative way to read the next non‑empty line. There is a subtle difference from my version. If I write
Liutauras is really helpful.
it will read the underlined w‍ord Liutauras as next(), then read the remainder as nextLine(). But what if I write this?
Liutauras is really helpful.               ↩
Where the ↩ represents pushing the enter key (again)? The output will include the trailing spaces. Just as it would if I write
             Liutauras is really helpful.              ↩
But then you will lose the leading spaces. My technique loses both leading and trailing spaces.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!