Jump to page: 1 2
Thread overview
toString(int) bug and two possible solutions
May 16, 2004
Andrew Edwards
May 16, 2004
Andy Friesen
May 16, 2004
Andrew Edwards
May 16, 2004
Andy Friesen
May 16, 2004
Andrew Edwards
May 16, 2004
Andrew Edwards
May 16, 2004
Ben Hinkle
May 17, 2004
Derek Parnell
May 17, 2004
Derek Parnell
May 17, 2004
Vathix
May 17, 2004
Derek Parnell
May 16, 2004
There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.

For example, the following program:

for(int i = 0; i <= 10; i++)
{
  printf(toString(i));
  printf(\n);
}

produces the output:

F:\>tostring
0123456789
123456789
23456789
3456789
456789
56789
6789
789
89
9
10

Obviously this is the incorrect result. The cause of this problem is located at line number 1501 .. 1503 of std.string.d

Which reads:

  if(u < 10)
    result = digits[u .. u+1];

Solution 1:

  if (u < 10)
    result ~= digits[u];

Solution 2:

  if(u < 10) {
    result.length = 1;
    result[0] = digits[u];
  }

Your choice really!

Regards,
Andrew
May 16, 2004
Andrew Edwards wrote:
> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
> 
> For example, the following program:
> 
> for(int i = 0; i <= 10; i++)
> {
>   printf(toString(i));
>   printf(\n);
> }

The problem is that you're treating a D string as though it were a C string.  Strings are not necessarily null terminated. (string literals seem to happen to have a zero following the last char, but I'm not sure whether that's part of the spec or not)

printf(toStringz(i)); should behave as expected.

What would be nice is a printf overload that accepts a D string as its first argument instead of a C string.

 -- andy
May 16, 2004
Andy Friesen wrote:

> Andrew Edwards wrote:
> 
>> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
>>
>> For example, the following program:
>>
>> for(int i = 0; i <= 10; i++)
>> {
>>   printf(toString(i));
>>   printf(\n);
>> }
> 
> 
> The problem is that you're treating a D string as though it were a C string.  Strings are not necessarily null terminated. (string literals seem to happen to have a zero following the last char, but I'm not sure whether that's part of the spec or not)
> 
> printf(toStringz(i)); should behave as expected.


I'm afraid you're mistaken ma'boy! Your proposed solution results in:

tostring.d(9): function toStringz (char[]string) does not match argument types (int)

The other problem is that I didn't treat D string as anything other than a D string. I merely pointed out a flaw in std.string.d and provided two solutions that remedies the problem. As currently implemented the conversion does not work and needs to be patched. You find a better way of doing it and I'd simply say congratulations! Either way it needs to be fixed.

Regards,
Andrew

> What would be nice is a printf overload that accepts a D string as its first argument instead of a C string.
> 
>  -- andy
May 16, 2004
Andy Friesen wrote:

> Andrew Edwards wrote:
> 
>> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
>>
>> For example, the following program:
>>
>> for(int i = 0; i <= 10; i++)
>> {
>>   printf(toString(i));
>>   printf(\n);
>> }
> 
> 
> The problem is that you're treating a D string as though it were a C string.  Strings are not necessarily null terminated. (string literals seem to happen to have a zero following the last char, but I'm not sure whether that's part of the spec or not)
> 
> printf(toStringz(i)); should behave as expected.

One more thing toStringz is intended to convert a D string to a null terminated C string; as such, it does not manipulate numbers.

Chao,
Andrew

> 
> What would be nice is a printf overload that accepts a D string as its first argument instead of a C string.
> 
>  -- andy
May 16, 2004
Andrew Edwards wrote:
> Andy Friesen wrote:
> 
>>
>> The problem is that you're treating a D string as though it were a C string.  Strings are not necessarily null terminated. (string literals seem to happen to have a zero following the last char, but I'm not sure whether that's part of the spec or not)
>>
>> printf(toStringz(i)); should behave as expected.
> 
> I'm afraid you're mistaken ma'boy! Your proposed solution results in:
> 
> tostring.d(9): function toStringz (char[]string) does not match argument types (int)

... gah.  Right.  You need printf("%.s", toString(i));
or printf(toStringz(toString(i)); (ew)

 -- andy
May 16, 2004
Andrew Edwards wrote:

> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
> 
> For example, the following program:
> 
> for(int i = 0; i <= 10; i++)
> {
>    printf(toString(i));
>    printf(\n);
> }
> 
> produces the output:
> 
> F:\>tostring
> 0123456789
> 123456789
> 23456789
> 3456789
> 456789
> 56789
> 6789
> 789
> 89
> 9
> 10
> 
> Obviously this is the incorrect result. The cause of this problem is located at line number 1501 .. 1503 of std.string.d
> 
> Which reads:
> 
>    if(u < 10)
>      result = digits[u .. u+1];
> 
> Solution 1:
> 
>    if (u < 10)
>      result ~= digits[u];
> 
> Solution 2:
> 
>    if(u < 10) {
>      result.length = 1;
>      result[0] = digits[u];
>    }
> 
> Your choice really!
> 
> Regards,
> Andrew

That's not a bug - it's a feature! I vaguely remember a recent thread where
it came up that toString on a digit will just return a slice of the digits
string - but I can't find the thread anymore. Anyway, to turn a D string
into a C string make sure it is null terminated:
 printf(toString(i) ~ "\0");
If you want you can change std.string to slice something like
"0\x001\x002\x003\x004\x005\x006\x007\x008\x009".
May 16, 2004
Andy Friesen wrote:
> Andrew Edwards wrote:
> 
>> Andy Friesen wrote:
>>
>>>
>>> The problem is that you're treating a D string as though it were a C string.  Strings are not necessarily null terminated. (string literals seem to happen to have a zero following the last char, but I'm not sure whether that's part of the spec or not)
>>>
>>> printf(toStringz(i)); should behave as expected.
>>
>>
>> I'm afraid you're mistaken ma'boy! Your proposed solution results in:
>>
>> tostring.d(9): function toStringz (char[]string) does not match argument types (int)
> 
> 
> .... gah.  Right.  You need printf("%.s", toString(i));
> or printf(toStringz(toString(i)); (ew)

Why should I need to do toStringz(toSring(i)) when toSring(i) already returns a D string?

OK... I see the problem, I'm treating printf() as a D function vice what it realy is: a C function.

Damn! We need a better IO facility.

My apologies!

Andrew

>  -- andy
May 17, 2004
On Sun, 16 May 2004 18:40:12 -0400, Andrew Edwards wrote:

> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
> 
> For example, the following program:
> 
> for(int i = 0; i <= 10; i++)
> {
>    printf(toString(i));
>    printf(\n);
> }
> 
> produces the output:
> 
> F:\>tostring
> 0123456789
> 123456789
> 23456789
> 3456789
> 456789
> 56789
> 6789
> 789
> 89
> 9
> 10
> 
> Obviously this is the incorrect result. The cause of this problem is located at line number 1501 .. 1503 of std.string.d
> 
> Which reads:
> 
>    if(u < 10)
>      result = digits[u .. u+1];
> 
> Solution 1:
> 
>    if (u < 10)
>      result ~= digits[u];
> 
> Solution 2:
> 
>    if(u < 10) {
>      result.length = 1;
>      result[0] = digits[u];
>    }
> 
> Your choice really!
> 
> Regards,
> Andrew

Is it a bug?
Doesn't printf() needs a C string as its first argument, and toString(int)
returns a D string?

What is annoying is the D compiler's failure to notice this as it does an implicit cast that does not actually convert the D string into a C string.

But explictly using printf( toStringz ( toString(i) ) ) will work instead.

I was hoping that printf( cast(char [])toString(i) ) might work, but that
doesn't do anything either.

-- 
Derek
17/May/04 11:13:05 AM
May 17, 2004
On Mon, 17 May 2004 11:24:19 +1000, Derek Parnell wrote:

> On Sun, 16 May 2004 18:40:12 -0400, Andrew Edwards wrote:
> 
>> There is a bug in the toString() function that prevents it from properly converting ints between '0' and '8' to their correct string value.
>> 
>> For example, the following program:
>> 
>> for(int i = 0; i <= 10; i++)
>> {
>>    printf(toString(i));
>>    printf(\n);
>> }
>> 
>> produces the output:
>> 
>> F:\>tostring
>> 0123456789
>> 123456789
>> 23456789
>> 3456789
>> 456789
>> 56789
>> 6789
>> 789
>> 89
>> 9
>> 10
>> 
>> Obviously this is the incorrect result. The cause of this problem is located at line number 1501 .. 1503 of std.string.d
>> 
>> Which reads:
>> 
>>    if(u < 10)
>>      result = digits[u .. u+1];
>> 
>> Solution 1:
>> 
>>    if (u < 10)
>>      result ~= digits[u];
>> 
>> Solution 2:
>> 
>>    if(u < 10) {
>>      result.length = 1;
>>      result[0] = digits[u];
>>    }
>> 
>> Your choice really!
>> 
>> Regards,
>> Andrew
> 
> Is it a bug?
> Doesn't printf() needs a C string as its first argument, and toString(int)
> returns a D string?
> 
> What is annoying is the D compiler's failure to notice this as it does an implicit cast that does not actually convert the D string into a C string.
> 
> But explictly using printf( toStringz ( toString(i) ) ) will work instead.
> 
> I was hoping that printf( cast(char [])toString(i) ) might work, but that
> doesn't do anything either.

This seems to work too, but its a bit limiting...

//-------------------
import std.string;

int printf(char []x)
{
    return std.string.printf( toStringz(x));
}

void main()
{
 for(int i = 0; i <= 10; i++)
 {
   printf( toString(i));
   printf(\n);
 };
}

//-------------------

-- 
Derek
17/May/04 11:47:22 AM
May 17, 2004
> What is annoying is the D compiler's failure to notice this as it does an implicit cast that does not actually convert the D string into a C string.

A char* isn't necessarily a C string. When char[] converts to char* it just drops the length, like it does from int[] to int* etc.


« First   ‹ Prev
1 2