splitting numbers from a test file
Craig Dillabaugh
cdillaba at cg.scs.carleton.ca
Tue Sep 18 20:36:36 PDT 2012
On Wednesday, 19 September 2012 at 03:12:21 UTC, Jonathan M Davis
wrote:
> On Wednesday, September 19, 2012 04:50:45 Craig Dillabaugh
> wrote:
>> Hello I am trying to read in a set of numbers from a text file.
>> The file in questions looks something like this:
>>
>> 35 2 0 1
>> 0 0.49463548699999998 0.88077994719999997 0
>> 1 0.60672109949999997 0.2254208717 0
>>
>>
>> After each line I want to check how many numbers were on the
>> line
>> I just read. My code to read this file looks like:
>>
>> 1 import std.stdio;
>> 2 import std.conv;
>> 3
>> 4 int main( string[] argv ) {
>> 5 real[] numbers_read;
>> 6 size_t line_count=1;
>> 7
>> 8 auto f = std.stdio.File("test.txt", "r");
>> 9 foreach( char[] s; f.byLine() ) {
>> 10 string line = std.string.strip( to!string(s) );
>> 11 auto parts = std.array.splitter( line );
>> 12 writeln("There are ", parts.length, " numbers in line ",
>> line_count++);
>> 13 foreach(string p; parts) {
>> 14 numbers_read ~= to!real(p);
>> 15 }
>> 16 }
>> 17 f.close();
>> 18 return 0;
>> 19 }
>>
>> When I try to compile this I get an error:
>> test.d(12): Error undefined identifier 'length;
>>
>> However, shouldn't splitter be returning an array (thats what
>> the
>> docs seem to show)? What is the type of 'parts'? (I tried using
>> std.traits to figure this out, but that just generated more
>> syntax errors for me).
>
> The docs do not show that splitter returns an array, because it
> doesn't. It
> returns a lazy range type which finds each successive element
> as you iterate
> over it. It doesn't have a length property, because it's length
> isn't known
> until you iterate over it. You have three options:
Thanks, a few others have pointed that out to me too. But as a D
newbie how would I have any clue what splitter returns since the
return type is auto?
The is an example in the docs.
auto a = " a bcd ef gh ";
assert(equal(splitter(a), ["", "a", "bcd", "ef", "gh"][]));
I guessed that since the return of splitter was equal to :
["", "a", "bcd", "ef", "gh"][]
it was returning some sort of 2D array!
When a function returns an 'auto' in the Phobos is this generally
indicative of the return value being a range?
>
> 1. Use std.array.split, which returns an array (so, it's eager
> and requires
> additional memory allocations to create the array, but you'll
> have its length
> without having to iterate over it multiple times).
>
> 2. Use std.range.walkLength to get the length of the range. If
> a range has a
> length property, then walkLength just returns that, otherwise
> it iterates over
> the whole range and counts its elements. So, you won't get
> extra memory
> allocations, but you'll have to iterate over the range twice.
>
> 3. Simply count up the number of elements as you iterate over
> them and _then_
> print out the length.
>
> Also, theres no need to convert s to a string like that. If you
> were saving
> the string or needed an actual string instead of char[], then
> that would make
> sense, but you're just splitting it and then converting it to a
> number. char[]
> will work just fine for that. So, something like this would
> probably be better
I think my problem was that I was trying to call strip on it first
to remove leading/trailing whitespace and I was getting syntax
errors
when I called strip() on the char[]. Just calling split works as
you
say.
>
> import std.conv;
> import std.stdio;
> import std.string;
>
> void main()
> {
> real[] numbers_read;
> size_t line_count = 0;
>
> auto f = std.stdio.File("test.txt", "r");
> foreach(line; f.byLine())
> {
> line = strip(line);
> auto parts = std.array.splitter(line);
> size_t length = 0;
>
> foreach(p; parts)
> {
> numbers_read ~= to!real(p);
> ++length;
> }
>
> writeln("There are ", length, " numbers in line ",
> ++line_count);
> }
> }
>
> If you aren't familiar with ranges, then read this
>
> http://ddili.org/ders/d.en/ranges.html
>
> But ranges are used quite heavily in Phobos, so you should be
> familiar with
> them if you intend to use D.
>
> - Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list