Attila Kovacs Agree. It would make for a nice addition. Starting at -1 based index from the right I would think, perhaps with a negative copy Length also going right?
Attila Kovacs you can write one with ease. Personally i'd prefer some extra safety, that the function would not start copying reversed strings just because i made a off-by-one error. Fail Early.
String length is still Integer, because string size is limited to 2GB even on 64 bit. Taking into account the trailing NULL byte the maximum length cannot exceed $7FFFFFFF.
Primož Gabrijelčič If I were starting from scratch, I'd have everything 0-based. Having mistakenly taken the 1-based route for strings, it was insanity to introduce 0-based strings in the way they did.
Primož Gabrijelčič I agree that the zero based strings are messy. Like null terminated strings, I embrace the concept (and portability of code from other languages), but perhaps not a implementation that makes drastic changes to the language. $ifdefs required.
0-based strings make very good sense because dynamic arrays are 0-based too. When we went mobile, we converted the whole codebase at once with a global search for all "Pos", "Copy", etc functions and changed them to the 0-based string helper functions. Then no IFDEFs are needed, unless you need to compile with ancient compilers...
There WAS element #0, immediately available without pointer hacks and documented. What elements you put into an array is semantics, but the very char array was 0..255
In huge retrospect it perhaps better be -1..254, but before dynarrays and pointer maths Pascal was not zero-centric
I am nog surprised the copy works like that, since I am using it like that this for years. But I was surprised tot see it is not documented. But than again who is reading the documentation on the copy statement?
David Heffernan I don't think you are going to read all documentation again on every new release of Delphi. Especially on something as common as the copy statement which I was referring to.
David Heffernan that is very dependent upon a quality of the documentation. Completness, accuracy and ease to read too. In particular, Delphi docs after D7 are less than stellar
I'm surprised, too. :-) I've been using Copy(S, Index, Length(S)) when I wanted to copy until the end of the string.
ReplyDeleteBTW, the third parameter is "count", not "position".
docwiki.embarcadero.com - System.Copy - RAD Studio API Documentation
2nd parameter is not needed either (when use on an array, string requires it though)
ReplyDeleteFWIW the compiler passes High(Integer) as count parameter when you dont explicitly specify.
Didn't know that, simplifies code a bit
ReplyDeleteDidn't know either, I used MaxInt :)
ReplyDeleteWorks in Delphi 2007 as well, for strings and arrays. Good to know.
ReplyDeleteWorks in fpc, too...
ReplyDeleteOndrej Kelle Thanks, will fix.
ReplyDeleteWorks in D2007 but not in D6.
ReplyDeleteHas worked since Delphi 7 btw.
ReplyDeleteworks since Delphi 2010, also in FPC but I prefer being explicit.
ReplyDeletemay be am being pessimistic. :)
...and thanks for caring and sharing...
ReplyDeleteSadly, in XE2 it does not work with dynarrays, only with strings...
ReplyDeleteAttila Kovacs Agree. It would make for a nice addition. Starting at -1 based index from the right I would think, perhaps with a negative copy Length also going right?
ReplyDeleteAttila Kovacs Isn't that what RightStr is for?
ReplyDeleteWow! All those (, , $ffff) i see. No more! Thx.
ReplyDeleteAttila Kovacs you can write one with ease.
ReplyDeletePersonally i'd prefer some extra safety, that the function would not start copying reversed strings just because i made a off-by-one error. Fail Early.
Stefan Glienke 64 bit compiler? Passes High(NativeInt) I hope.
ReplyDeleteNot really.
ReplyDeleteProject60.dpr.15: s := Copy(s, 2);
00000000004258B3 488D0D963E0100 lea rcx,[rel $00013e96]
00000000004258BA 488B158F3E0100 mov rdx,[rel $00013e8f]
00000000004258C1 41C7C002000000 mov r8d,$00000002
00000000004258C8 41C7C1FFFFFF7F mov r9d,$7fffffff
00000000004258CF E83C4FFEFF call @UStrCopy
Primož Gabrijelčič Well that's fine for a string. They are always indexed by integer. I was thinking of arrays. They are indexed by NativeInt.
ReplyDeleteString length is still Integer, because string size is limited to 2GB even on 64 bit. Taking into account the trailing NULL byte the maximum length cannot exceed $7FFFFFFF.
ReplyDeleteDoesn't everyone use TStringHelper.Substring now? ;-) Here it is a documented feature that you can omit the length parameter.
ReplyDeleteHans Lavdal Jakobsen .Substring works with 0-based indexes and so it cannot be used in a serious code.
ReplyDeletePrimož Gabrijelčič Why not?
ReplyDeleteDeadpan humor, man.
ReplyDeleteSeriously, I'm so used to 1-based strings that I always leave a comment in when working with 0-based functions.
The whole thing is a mess. Damn whoever is responsible for it!
Primož Gabrijelčič If I were starting from scratch, I'd have everything 0-based. Having mistakenly taken the 1-based route for strings, it was insanity to introduce 0-based strings in the way they did.
ReplyDeletePrimož Gabrijelčič I agree that the zero based strings are messy. Like null terminated strings, I embrace the concept (and portability of code from other languages), but perhaps not a implementation that makes drastic changes to the language. $ifdefs required.
ReplyDelete0-based strings make very good sense because dynamic arrays are 0-based too. When we went mobile, we converted the whole codebase at once with a global search for all "Pos", "Copy", etc functions and changed them to the 0-based string helper functions. Then no IFDEFs are needed, unless you need to compile with ancient compilers...
ReplyDeleteHans Lavdal Jakobsen That's a sound plan. Mixing 0 based and 1 based is not a good idea.
ReplyDeleteWell, initial strings ( rebranded as short strings ) were 0-based and did not need SetLength function. Back in 1980-s it looked quite okay....
ReplyDeleteArioch The actually, they were 1-based. Element 0 contained the length (and that's why it was limited to 255).
ReplyDeleteThere WAS element #0, immediately available without pointer hacks and documented. What elements you put into an array is semantics, but the very char array was 0..255
ReplyDeleteIn huge retrospect it perhaps better be -1..254, but before dynarrays and pointer maths Pascal was not zero-centric
No. The following code outputs 3 and 2 because byte 0 contains length and because indexing is 1-based.
ReplyDeleteI would know. We are still using shortstrings in the code. >:-(
program Project147;
{$APPTYPE CONSOLE}
{$R *.res}
var
s: shortstring;
begin
s := '123';
Writeln(byte(s[0]));
Writeln(Pos('2', s));
Readln;
end.
I am nog surprised the copy works like that, since I am using it like that this for years. But I was surprised tot see it is not documented. But than again who is reading the documentation on the copy statement?
ReplyDeleteMaarten de Vries I guess a proficient programmer that wants to know how a library function operates will read its documentation.
ReplyDeleteIt's the less proficient programmers, the ones writing shoddy code, that ignore the documentation and program by trial and error and guesswork.
David Heffernan I don't think you are going to read all documentation again on every new release of Delphi. Especially on something as common as the copy statement which I was referring to.
ReplyDeleteDavid Heffernan that is very dependent upon a quality of the documentation. Completness, accuracy and ease to read too. In particular, Delphi docs after D7 are less than stellar
ReplyDeleteMaarten de Vries I didn't say that.
ReplyDeleteMaarten de Vries I read the What's New?, look through the Bugs Fixed list and compare the sources with the previous ones.
ReplyDelete