Big Oversight with readln?

Nick Sabalausky (Abscissa) via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Feb 23 19:45:35 PST 2017


On 02/23/2017 09:43 PM, Jonathan Marler wrote:
> I can't figure out how to make use of the full capacity of buffers that
> are allocated by readln.  Take the example code from the documentation:
>
>      // Read lines from $(D stdin) and count words
>
>      void main()
>      {
>          char[] buf;
>          size_t words = 0;
>
>          while (!stdin.eof)
>          {
>              char[] line = buf;
>              stdin.readln(line);
>              if (line.length > buf.length)
>                  buf = line;
>
>              words += line.split.length;
>          }
>
>          writeln(words);
>      }
>
> When buf is not large enough to hold the line, readln will allocate a
> new buffer to accomodate and this example shows how you can save that
> new buffer to reuse the next time.  The problem is that the capacity of
> the new buffer is nowhere to be found. readln only returns the line that
> was read which is only a slice of the buffer that was allocated.  The
> next time that readln is called, it will not read past the slice even if
> the capacity of the buffer it allocated was larger.  This will cause a
> new allocation/copy every time you read a line that was larger than all
> the previous lines, even if a previous allocation was already large
> enough. This seems like a big oversight to me, I must be missing
> something right?

I don't think that problem is actually occurring:

Let's step through the code, and suppose you're reading the following 
four lines of text:

12345
123456789
123
1234567

Starting out, buf.length is 0. When reading the first line, the buffer 
isn't big enough for 5, so readln allocates returns new buffer of length 
5. That is more than buf.length (0), so the new buffer becomes the new buf.

Second line, again, buf (length 5) isn't big enough for 9, so readln 
allocates a new buffer length 9. That's more than the old one (5), so 
again your code sets buf to the larger new buffer (length 9).

Third line: buf (length 9) can definitely hold length 3, so readln does 
not allocate. The new slice returned (length 3) is NOT longer than buf 
(still length 9), so buf is NOT set to the slice returned by readln. So 
buf REMAINS length 9.

Fourth line: buf (still length 9) can definitely hold length 7, so 
readln does not allocate.



More information about the Digitalmars-d-learn mailing list