digitalmars.D - toString(int) bug and two possible solutions
- Andrew Edwards (37/37) May 16 2004 There is a bug in the toString() function that prevents it from properly...
- Andy Friesen (9/19) May 16 2004 The problem is that you're treating a D string as though it were a C
- Andrew Edwards (12/37) May 16 2004 I'm afraid you're mistaken ma'boy! Your proposed solution results in:
- Andy Friesen (4/18) May 16 2004 ... gah. Right. You need printf("%.s", toString(i));
- Andrew Edwards (8/30) May 16 2004 Why should I need to do toStringz(toSring(i)) when toSring(i) already
- Andrew Edwards (5/31) May 16 2004 One more thing toStringz is intended to convert a D string to a null
- Ben Hinkle (8/58) May 16 2004 That's not a bug - it's a feature! I vaguely remember a recent thread wh...
- Derek Parnell (12/62) May 16 2004 Is it a bug?
- Derek Parnell (20/84) May 16 2004 This seems to work too, but its a bit limiting...
- Vathix (2/4) May 16 2004 A char* isn't necessarily a C string. When char[] converts to char* it j...
- Derek Parnell (21/26) May 16 2004 Technically you are correct. A C-string is a (char *) AND the set of
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: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, AndrewThere 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
Andrew Edwards wrote:Andy Friesen wrote:... gah. Right. You need printf("%.s", toString(i)); or printf(toStringz(toString(i)); (ew) -- andyThe 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)
May 16 2004
Andy Friesen wrote:Andrew Edwards wrote: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! AndrewAndy Friesen wrote:.... gah. Right. You need printf("%.s", toString(i)); or printf(toStringz(toString(i)); (ew)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)-- andy
May 16 2004
Andy Friesen wrote:Andrew Edwards wrote: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, AndrewThere 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
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, AndrewThat'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
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, AndrewIs 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 16 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: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 AMThere 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, AndrewIs 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.
May 16 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.
May 16 2004
On Mon, 17 May 2004 00:26:24 -0400, Vathix wrote:Technically you are correct. A C-string is a (char *) AND the set of characters pointed to is deemed terminated when a zero-value char is found. However a (char *) is also not a (char []) either. The first is a pointer to a char, and the second is structure whose first element is a 4-byte integer followed by zero or more char elements. I thought that when a D string (char []) is converted to a C string (char *) a new piece of RAM is allocated (length of D-string + 1) and the char elements are copied to the new RAM location and a zero-char is placed in the last RAM position. The new RAM location is returned (char *). I'd still like the compiler to tell us when its implicitly casting char[] to char* for us. Wouldn't it save many annoying buglets? Something like this should do the conversions too, IMO ... char *x; char[] y; . . . x = cast (char *)y; y = cast (char [])x; -- Derek 17/May/04 4:34:02 PMWhat 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.
May 16 2004