www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Array with char-keys

reply Charma <Motoko_Kusanagi web.de> writes:
thanks to all..
i have tested it...
seems to work as long as i am writing into the string, but it somehow looks
like it is always overriding the same entry...

i got my class:
class VFIentry
{
	byte VFSfile;
	uint pos;
	uint size;
	byte flags;
}

and later in some code i do this:

VFIentry[char[]] VFIndex; // this is the array


byte VFSt;
char[] namet;
while(!index.eof())
{
	index.readExact(&VFSt, 1);
	index.readExact(&t, 1);
	namet.length = t;
	index.readExact(namet.ptr, t);
	VFIndex[namet] = new VFIentry; // **
	VFIndex[namet].VFSfile = VFSt;	
	index.readExact(&VFIndex[namet].flags, 1);
	index.readExact(&VFIndex[namet].pos, 4);
	index.readExact(&VFIndex[namet].size, 4);
	writefln("file: ", namet, " in VFS-File: ", VFIndex[namet].VFSfile, " pos: ",
VFIndex[namet].pos, " size: ", VFIndex[namet].size);			
}
up to this point it seems to work correctly... i hope it isn't too hard to
understans... i am reading a file that has informations about in which vfs
(virtual file system) the files are and then the name-length, the name, and
other informations...
i want to read them all into the array VFIndex so that i can later get the
informations with VFIndex["file1.dat"] and VFIndex["file2.dat"] and so on...
i think my mistake is at the **-marked line but i am not sure..
anyone any idea?!?
May 25 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Charma wrote:
 thanks to all..
 i have tested it...
 seems to work as long as i am writing into the string, but it somehow looks
like it is always overriding the same entry...
 
 i got my class:
 class VFIentry
 {
 	byte VFSfile;
 	uint pos;
 	uint size;
 	byte flags;
 }
 
 and later in some code i do this:
 
 VFIentry[char[]] VFIndex; // this is the array
 
 
 byte VFSt;
 char[] namet;
 while(!index.eof())
 {
 	index.readExact(&VFSt, 1);
 	index.readExact(&t, 1);

From here...
 	namet.length = t;
 	index.readExact(namet.ptr, t);
 	VFIndex[namet] = new VFIentry; // **
 	VFIndex[namet].VFSfile = VFSt;

...to here is, I think, your problem. Strings in D are arrays, and arrays are reference types. So what's happening here is that you're reading in the file's name, storing it away... and then *overwriting it* on the next file. What you need to do is copy the buffer if you plan on re-using it, or simply create a new buffer in the first place. Since you're actively using namet in several places, I'd replace: namet.length = t; with: namet = new char[t]; And it should work from there.
 	index.readExact(&VFIndex[namet].flags, 1);
 	index.readExact(&VFIndex[namet].pos, 4);
 	index.readExact(&VFIndex[namet].size, 4);
 	writefln("file: ", namet, " in VFS-File: ", VFIndex[namet].VFSfile, " pos: ",
VFIndex[namet].pos, " size: ", VFIndex[namet].size);			
 }
 up to this point it seems to work correctly... i hope it isn't too hard to
understans... i am reading a file that has informations about in which vfs
(virtual file system) the files are and then the name-length, the name, and
other informations...
 i want to read them all into the array VFIndex so that i can later get the
informations with VFIndex["file1.dat"] and VFIndex["file2.dat"] and so on...
 i think my mistake is at the **-marked line but i am not sure..
 anyone any idea?!?

Out of interest, what language(s) are you coming from? -- Daniel P.S. Full disclosure: changing .length *can* give you a new string, but only if the new length doesn't fit into the previously allocated storage. So files with the same length or shorter won't get new storage. Ones that are larger *might*. -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 25 2007
parent reply Charma <Motoko_Kusanagi web.de> writes:
Daniel Keep Wrote:

 
 
 Charma wrote:
 thanks to all..
 i have tested it...
 seems to work as long as i am writing into the string, but it somehow looks
like it is always overriding the same entry...
 
 i got my class:
 class VFIentry
 {
 	byte VFSfile;
 	uint pos;
 	uint size;
 	byte flags;
 }
 
 and later in some code i do this:
 
 VFIentry[char[]] VFIndex; // this is the array
 
 
 byte VFSt;
 char[] namet;
 while(!index.eof())
 {
 	index.readExact(&VFSt, 1);
 	index.readExact(&t, 1);

From here...
 	namet.length = t;
 	index.readExact(namet.ptr, t);
 	VFIndex[namet] = new VFIentry; // **
 	VFIndex[namet].VFSfile = VFSt;

...to here is, I think, your problem. Strings in D are arrays, and arrays are reference types. So what's happening here is that you're reading in the file's name, storing it away... and then *overwriting it* on the next file. What you need to do is copy the buffer if you plan on re-using it, or simply create a new buffer in the first place. Since you're actively using namet in several places, I'd replace: namet.length = t; with: namet = new char[t]; And it should work from there.
 	index.readExact(&VFIndex[namet].flags, 1);
 	index.readExact(&VFIndex[namet].pos, 4);
 	index.readExact(&VFIndex[namet].size, 4);
 	writefln("file: ", namet, " in VFS-File: ", VFIndex[namet].VFSfile, " pos: ",
VFIndex[namet].pos, " size: ", VFIndex[namet].size);			
 }
 up to this point it seems to work correctly... i hope it isn't too hard to
understans... i am reading a file that has informations about in which vfs
(virtual file system) the files are and then the name-length, the name, and
other informations...
 i want to read them all into the array VFIndex so that i can later get the
informations with VFIndex["file1.dat"] and VFIndex["file2.dat"] and so on...
 i think my mistake is at the **-marked line but i am not sure..
 anyone any idea?!?

Out of interest, what language(s) are you coming from? -- Daniel P.S. Full disclosure: changing .length *can* give you a new string, but only if the new length doesn't fit into the previously allocated storage. So files with the same length or shorter won't get new storage. Ones that are larger *might*. -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/

thanks a lot! my problem is solved, but to be honest i am not 100% sure why... maybe you could explain that again?!? (sorry about that... english isn't my native language) What I don't understand is why i still need the old name?! once i have saved it in VFIndex, i can override it, right? it is not needed anymore since it is saved in VFIndex, isn't it? About language.. i think you want to know what i used before: C++, acoutally i still use C++ sometimes... I started using D 3 days ago and only because my friend is using it and we are on a project together...
May 25 2007
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Charma wrote:
 Daniel Keep Wrote:
 
 Charma wrote:
 thanks to all..
 i have tested it...
 seems to work as long as i am writing into the string, but it somehow looks
like it is always overriding the same entry...

 i got my class:
 class VFIentry
 {
 	byte VFSfile;
 	uint pos;
 	uint size;
 	byte flags;
 }

 and later in some code i do this:

 VFIentry[char[]] VFIndex; // this is the array


 byte VFSt;
 char[] namet;
 while(!index.eof())
 {
 	index.readExact(&VFSt, 1);
 	index.readExact(&t, 1);

 	namet.length = t;
 	index.readExact(namet.ptr, t);
 	VFIndex[namet] = new VFIentry; // **
 	VFIndex[namet].VFSfile = VFSt;

Strings in D are arrays, and arrays are reference types. So what's happening here is that you're reading in the file's name, storing it away... and then *overwriting it* on the next file. What you need to do is copy the buffer if you plan on re-using it, or simply create a new buffer in the first place. Since you're actively using namet in several places, I'd replace: namet.length = t; with: namet = new char[t]; And it should work from there.


 
 thanks a lot! my problem is solved, but to be honest i am not 100% sure why... 
 maybe you could explain that again?!? (sorry about that... english isn't my
native language)

A dynamic array (let's say T[]) in D is best thought of as a struct { size_t length; T* ptr; }. When you make a copy of it (which happens when you use it as an AA key, for example) this struct is copied, not the data the "ptr" member points to. What you were doing was changing the data it points to while it was still being used as an AA key...
 What I don't understand is why i still need the old name?!

Because the data is still referenced by the AA key.
 once i have saved it in VFIndex, i can override it, right?

You shouldn't overwrite[1] array data once the array reference is "saved" into an AA key. [1] (You can't override it ;) )
 it is not needed anymore since it is saved in VFIndex, isn't it?

It *is* needed since only the _reference_ is "saved" into the AA.
May 25 2007