Thread overview
Re: Convert strings with different format to float
Sep 08, 2010
Jonathan M Davis
Sep 08, 2010
Stanislav Blinov
Sep 08, 2010
Tom Kazimiers
September 08, 2010
On Wednesday 08 September 2010 00:23:31 Tom Kazimiers wrote:
> Hi,
> 
> I try to read data in from a file. This data consist mainly of numbers and I have a hard time converting it to number type variables. Two data lines could look like this
> 
> v 0 0 0
> v 1.5 1.2 0
> 
> Now I want to parse those lines and call a method, the line in passed
> (as char[]) to it:
> 
> int index = indexOf(line, "v ");
> if(index != -1) {
>     vc++;
>     float x = 0.0, y = 0.0, z = 0.0;
>     char[][] vertexCoords = split( line[index+2 .. $] );
> 
>     if (vertexCoords.length > 0)
>         x = to!int(vertexCoords[0]);
>     if (vertexCoords.length > 1)
>         y = to!int(vertexCoords[1]);
>     if (vertexCoords.length > 2)
>         z = to!int(vertexCoords[2]);
> 
>     process_vertex(vc,x,y,z);
>     return;
> }
> 
> First I split the remaining characters (after "v ") into parts (here is
> probably dynamic copying included?). Then I want to convert each part to
> a float value.
> 
> The problem I have is that I obviously need to use "to!int" for numbers with out decimal point and "to!float" for numbers with. But since those can be mixed I would ask for every part if there is a decimal point, e.g:
> 
> if (vertexCoords.length > 0) {
> 	if (indexOf(vertexCoords[0], ".") != -1)
> 	        x = to!float(vertexCoords[0]);
> 	else
> 		x = to!int(vertexCoords[0]);
> }
> 
> Is there a more convient way to achieve that? I am coming from C++ and IIRC one could do there sth. like this:
> 
> int index = line.find("v ");
> if(index != std::string::npos) {
>     line.erase(0,index+1);
>     vc++;
>     float x,y,z = 0;
> 
>     std::istringstream ins;
>     ins.str(line);
>     ins >> x >> y >> z;
> 
>     process_vertex(vc,x,y,z);
>     return;
> }
> 
> That looks much cleaner to me (besides the ">>" operators). So I am looking for sth. similar in D :-). Maybe a to!float that can cope with numbers without decimal point.
> 
> Cheers,
> Tom

I would have thought that to!float() could handle a number without a decimal point. If it can't I would suggest creating a bug report for it. Now, since such a fix would not help you immediately in either case, I would suggest creating a wrapper function which took a string and then used to!int() for numbers without decimal points and to!float() for number with them, and then returned a float. That way, you wouldn't have to keep worrying about it. Also, you could try parse(). It might be more forgiving.

- Jonathan M Davis
September 08, 2010
Jonathan M Davis wrote:
> On Wednesday 08 September 2010 00:23:31 Tom Kazimiers wrote:
>> Hi,
>>
>> I try to read data in from a file. This data consist mainly of numbers
>> and I have a hard time converting it to number type variables. Two data
>> lines could look like this
>>
>> v 0 0 0
>> v 1.5 1.2 0
>>
>> Now I want to parse those lines and call a method, the line in passed
>> (as char[]) to it:
>>
>> int index = indexOf(line, "v ");
>> if(index != -1) {
>>     vc++;
>>     float x = 0.0, y = 0.0, z = 0.0;
>>     char[][] vertexCoords = split( line[index+2 .. $] );
>>
>>     if (vertexCoords.length > 0)
>>         x = to!int(vertexCoords[0]);
>>     if (vertexCoords.length > 1)
>>         y = to!int(vertexCoords[1]);
>>     if (vertexCoords.length > 2)
>>         z = to!int(vertexCoords[2]);
>>
>>     process_vertex(vc,x,y,z);
>>     return;
>> }
>>
>> First I split the remaining characters (after "v ") into parts (here is
>> probably dynamic copying included?). Then I want to convert each part to
>> a float value.
>>
>> The problem I have is that I obviously need to use "to!int" for numbers
>> with out decimal point and "to!float" for numbers with. But since those
>> can be mixed I would ask for every part if there is a decimal point, e.g:
>>
>> if (vertexCoords.length > 0) {
>> 	if (indexOf(vertexCoords[0], ".") != -1)
>> 	        x = to!float(vertexCoords[0]);
>> 	else
>> 		x = to!int(vertexCoords[0]);
>> }
>>
>> Is there a more convient way to achieve that? I am coming from C++ and
>> IIRC one could do there sth. like this:
>>
>> int index = line.find("v ");
>> if(index != std::string::npos) {
>>     line.erase(0,index+1);
>>     vc++;
>>     float x,y,z = 0;
>>
>>     std::istringstream ins;
>>     ins.str(line);
>>     ins >> x >> y >> z;
>>
>>     process_vertex(vc,x,y,z);
>>     return;
>> }
>>
>> That looks much cleaner to me (besides the ">>" operators). So I am
>> looking for sth. similar in D :-). Maybe a to!float that can cope with
>> numbers without decimal point.
>>
>> Cheers,
>> Tom
> 
> I would have thought that to!float() could handle a number without a decimal point. If it can't I would suggest creating a bug report for it. Now, since such a fix would not help you immediately in either case, I would suggest creating a wrapper function which took a string and then used to!int() for numbers without decimal points and to!float() for number with them, and then returned a float. That way, you wouldn't have to keep worrying about it. Also, you could try parse(). It might be more forgiving.
> 
> - Jonathan M Davis

No it wouldn't :)
It's indeed a bug, and it happens if string contains e.g. single 0 (other digits are parsed normally). It seems that parse for floating points tries to determine if the number is in hex format, thus eating first 0, but it does not reuse this 0 later while it tries to pop next characters (and that results in assertion in std.array).
September 08, 2010
Hi,

On 09/08/2010 10:02 AM, Stanislav Blinov wrote:
>> I would have thought that to!float() could handle a number without a decimal point. If it can't I would suggest creating a bug report for it. Now, since such a fix would not help you immediately in either case, I would suggest creating a wrapper function which took a string and then used to!int() for numbers without decimal points and to!float() for number with them, and then returned a float. That way, you wouldn't have to keep worrying about it. Also, you could try parse(). It might be more forgiving.
>>
>> - Jonathan M Davis
>
> No it wouldn't :)
> It's indeed a bug, and it happens if string contains e.g. single 0
> (other digits are parsed normally). It seems that parse for floating
> points tries to determine if the number is in hex format, thus eating
> first 0, but it does not reuse this 0 later while it tries to pop next
> characters (and that results in assertion in std.array).

thanks for your answers. Indeed, it is a bug. As Don states no bug report is needed, because it is fixed for a couple of weeks (in svn).

In the meantime (of waiting for upcoming release) I will, as Jonathan suggested, create a wrapper function.

Cheers,
Tom