digitalmars.D.learn - Help with Associative array problems.
- Spacen Jasset <spacenjasset yahoo.co.uk> Apr 02 2008
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Apr 02 2008
- Spacen Jasset <spacenjasset yahoo.co.uk> Apr 02 2008
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Apr 03 2008
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
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:~$
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
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:~$
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".
the best way or can I do something else?
Apr 02 2008
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








Frits van Bommel <fvbommel REMwOVExCAPSs.nl>