dynamic array of strings

Denis Koroskin 2korden at gmail.com
Tue Dec 30 10:52:43 PST 2008


On Tue, 30 Dec 2008 20:34:00 +0300, Michael P. <baseball.mjp at gmail.com> wrote:

> Denis Koroskin Wrote:
>
>> On Tue, 30 Dec 2008 20:23:07 +0300, Michael P. <baseball.mjp at gmail.com>  
>> wrote:
>>
>> > Denis Koroskin Wrote:
>> >
>> >> On Tue, 30 Dec 2008 18:56:08 +0300, Michael P.  
>> <baseball.mjp at gmail.com>
>> >> wrote:
>> >>
>> >> > Jarrett Billingsley Wrote:
>> >> >
>> >> >> On Mon, Dec 29, 2008 at 10:36 PM, Michael P.  
>> <baseball.mjp at gmail.com>
>> >> >> wrote:
>> >> >> > import std.stdio;
>> >> >> > import std.cstream;
>> >> >> > void main()
>> >> >> > {
>> >> >> >  char[][] names;
>> >> >> >  char[] currentName;
>> >> >> >  while( true )
>> >> >> >  {
>> >> >> >    din.readf( "%s", &currentName );
>> >> >> >    if( currentName == "stop" )
>> >> >> >    {
>> >> >> >      break;
>> >> >> >    }
>> >> >> >    else
>> >> >> >    {
>> >> >> names ~= currentName;
>> >> >> >    }
>> >> >> >  }
>> >> >> >  foreach( name; names )
>> >> >> >  {
>> >> >> >    writefln( name );
>> >> >> >  }
>> >> >> > }
>> >> >>
>> >> >> ~= performs an append.  It adds the given item to the end of the
>> >> array.
>> >> >
>> >> > Under 1.036, this does not work.
>> >> >
>> >> > Input:
>> >> > michael
>> >> > is
>> >> > cool
>> >> > stop
>> >> >
>> >> > The output is:
>> >> > stopeal
>> >> > st
>> >> > stop
>> >> >
>> >> > What seems to be happening is that the letters of stop are added to
>> >> the
>> >> > word, and if the word is longer than stop, then the rest of the
>> >> letters
>> >> > of the word are added.
>> >> > So, I'm not sure if this is a bug or what...
>> >> > -Michael P.
>> >>
>> >> Now, it's not. What you do is overwrite the string again and again.
>> >> Try putting "currentName = null;" before doing din.readf().
>> >
>> > Thanks, that worked.
>> > -Michael P.
>>
>> Did you understand the difference? Can you explain the behavior (to  
>> yourself)?
>
> Not really... I really have no idea why it wouldn't work before.

Well, let's go through the code.

First of all, you should undestand that an array is nothing but a pair of pointer to first element and its length.

Since char[] == string in D1, let's use string instead to make code slightly more readable.

string[] names; // array of strings that will store our names
string currentName;
...
din.readf( "%s", &currentName ); // what does this line do?

din.readf tries to minimize allocations by accepting a buffer where the string will be stored. Buffer will be allocated on heap if provided one is too small to fit the whole string.

Initially, currentName is null, i.e. currentName.ptr is null and currentName.length == 0. If you type anything, the data won't fit into buffer and therefore a new one is created by readf. When you return from readf, currentName will point to "michael" and have length == 7.

When you call din.readf for second time, you pass your currentName as a buffer once again. This time it is large enough to fit "is" and therefore it is not reallocated. "is" is written on top of "michael" and becomes "ischael". currentName's length is updated to 2. Etc.

Here is names' contents step by step:

At Startup:
string[] names = []; // empty

Step 1:
string[] names = [ "michael" ];

Step 2:
string[] names = [ "ischael", "is" ];

Step 3:
string[] names = [ "coolael", "co", "cool" ];

Step 4:
string[] names = [ "stopael", "st", "stop", "stop" ];

When you reset buffer (by doing "currentName = null;"), a new one is allocated each step and each string gets its own memory. That's it.


More information about the Digitalmars-d-learn mailing list