www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Help with Associative array problems.

reply Spacen Jasset <spacenjasset yahoo.co.uk> writes:
The program below does not print what it should, either using a File or 
the TArrayStream.

It prints this:

user vm-fruitbat:~$ dmd t.d
user vm-fruitbat:~$ ./t
Error: 4invalid UTF-8 sequence
Material user vm-fruitbat:~$



I can "fix" it by saying:

	m[words[1].dup] = 1

But why does the original 'go wrong'



import std.stdio;
import std.string;
import std.stream;

void main()
{
	//Stream file = new File("test.txt");
         TArrayStream!(char[]) file =
		new TArrayStream!(char[])("newmtl one\nnewmtl two");

	int [char[]]	m;
	foreach(ulong line_no, ref string line; file) {
		string words[] = line.split();
       		m[words[1]] = 1; 	
	}
         foreach (char[] k, ref int v; m) {
		writefln("Material %s", k);
	}
}
Apr 02 2008
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Spacen Jasset wrote:
 The program below does not print what it should, either using a File or 
 the TArrayStream.
 
 It prints this:
 
 user vm-fruitbat:~$ dmd t.d
 user vm-fruitbat:~$ ./t
 Error: 4invalid UTF-8 sequence
 Material user vm-fruitbat:~$
 
[snip]
     foreach(ulong line_no, ref string line; file) {
         string words[] = line.split();
               m[words[1]] = 1;    
     }
         foreach (char[] k, ref int v; m) {
         writefln("Material %s", k);
     }
 }
File.opApply (which is called by foreach), as implemented in superclass Stream, re-uses a (stack-allocated) buffer for each iteration. This is more efficient, but means the string put into the loop variable is only valid for that iteration; if you want to keep it beyond that you need to allocate a copy. This is mentioned in the documentation for InputStream[1]: "The string passed in line may be reused between calls to the delegate." [1] <http://www.digitalmars.com/d/1.0/phobos/std_stream.html>, search for "opApply".
Apr 02 2008
parent reply Spacen Jasset <spacenjasset yahoo.co.uk> writes:
Frits van Bommel wrote:
 Spacen Jasset wrote:
 The program below does not print what it should, either using a File 
 or the TArrayStream.

 It prints this:

 user vm-fruitbat:~$ dmd t.d
 user vm-fruitbat:~$ ./t
 Error: 4invalid UTF-8 sequence
 Material user vm-fruitbat:~$
[snip]
     foreach(ulong line_no, ref string line; file) {
         string words[] = line.split();
               m[words[1]] = 1;        }
         foreach (char[] k, ref int v; m) {
         writefln("Material %s", k);
     }
 }
File.opApply (which is called by foreach), as implemented in superclass Stream, re-uses a (stack-allocated) buffer for each iteration. This is more efficient, but means the string put into the loop variable is only valid for that iteration; if you want to keep it beyond that you need to allocate a copy. This is mentioned in the documentation for InputStream[1]: "The string passed in line may be reused between calls to the delegate." [1] <http://www.digitalmars.com/d/1.0/phobos/std_stream.html>, search for "opApply".
I see ok. This is all very subtle though. Is my solution adding a .dup the best way or can I do something else?
Apr 02 2008
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Spacen Jasset wrote:
 I see ok. This is all very subtle though. Is my solution adding a .dup 
 the best way or can I do something else?
If you need the string after the iteration of the loop in which it was bound, .dup is the best way to do so. (The original gets overwritten, so make a copy if you need it later -- not rocket science ;) ) Unless you're using D2-series compiler, in which case .idup may be better (especially for use as AA keys).
Apr 03 2008