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