Smalltalk stdin nextLine for fixed number of lines of input

1.1k views Asked by At

I am currently trying to get 3 specific lines of input of the form:

XX.XX (float) XX (1-3 digit integer) XX (1-3 digit integer)

Below is the current code I have:

inputStringOne := stdin nextLine.
mealCost := inputStringOne.

Transcript show: inputStringOne; cr .

inputStringTwo := stdin nextLine.
tipPercent := inputStringTwo.

Transcript show: inputStringTwo; cr .

inputString := stdin nextLine.
taxPercent := inputString .

mealCost inspect .
tipPercent inspect .
taxPercent inspect .

I have been at this for a good 3-4 hours programming, scouring the Internet, etc. I am an uber-beginner teaching myself Smalltalk, so I am trying to see why the nextLine isn't reading the inputs correctly. Below are the sample inputs put into stdin, and the results of the Transcript show and inspect:

Sample Input on stdin:

10.25
17
5

Output on stdout:

10.25
.25
An instance of String
  contents: [
    [1]: $1
    [2]: $0
    [3]: $.
    [4]: $2
    [5]: $5
  ]
An instance of String
  contents: [
    [1]: $.
    [2]: $2
    [3]: $5
  ]
An instance of String
  contents: [
    [1]: $.
    [2]: $2
    [3]: $5
  ]
10.25

When I just do the following code, I see all 3 inputs separated by <10>, which I assume is the carriage-return or linefeed.

"just print all contents in stdin"
inputS := stdin contents.
inputS inspect .

Sample input (stdin):

10.25
17
5

Output (stdout):

An instance of String
  contents: [
    [1]: $1
    [2]: $0
    [3]: $.
    [4]: $2
    [5]: $5
    [6]: $<10>
    [7]: $1
    [8]: $7
    [9]: $<10>
    [10]: $5
  ]

So it seems that for some reason, the first line of the code is the only one gotten by stdin nextLine ., but the rest only get the last 3 characters (the decimal point and the 2 digits after the decimal point). I am not sure why this is the case.

I have tried nextAvailable, flush, commit, stdin close, and a handful of other methods, all to no avail. One idea I have is to go about this problem is to just get the whole stdin contents, split by <10>, then save each "part" to 3 different variables, but I want to learn more about how stdin nextLine works and to have a better understanding of how that relates to stdin contents as well. Is there no good way to just do stdin nextLine 3 times given we know that there are only 3 inputs?

3

There are 3 answers

2
Michael Kohl On

I can not reproduce this on macOS with GNU Smalltalk 3.2.5:

→ gst -f foo.st
12.23
12.23
12
12
7
An instance of String
  contents: [
    [1]: $1
    [2]: $2
    [3]: $.
    [4]: $2
    [5]: $3
  ]
An instance of String
  contents: [
    [1]: $1
    [2]: $2
  ]
An instance of String
  contents: [
    [1]: $7
  ]

As you can see every input is echoed back from your Transcript show: messages and the output of inspect looks correct too. Which OS and version of GNU Smalltalk are you using?

0
MERLIN On

using a very buggy version of smalltalk on another site. The best approach I could find builds on contents. Note: array in smalltalk starts at 1, not 0.

ins := stdin contents substrings '\n'.

loopMax := 3.
ix := 1.
[   line := ins at: ix.
    Transcript show: 'ins at ', ix printString;
        show: ' =', line; cr.
                
    ix := ix + 1.
    b := ix asNumber > loopMax.
] whileFalse: [ b ].
0
Gregory Schoenmakers On

This appears to be a bug in GNU smalltalk. If you type in the input directly from the keyboard then stdin nextLine works just fine. However, if you redirect the input from a file then stdin nextLine messes it up.

Significantly, I can't find a single answer in HackerRank that is written in smalltalk so this must be an old problem.