Who knew that? (And why didn't you tell me before!?)

Who knew that? (And why didn't you tell me before!?)

Originally shared by Primož Gabrijelčič

Comments

  1. I'm surprised, too. :-) I've been using Copy(S, Index, Length(S)) when I wanted to copy until the end of the string.
    BTW, the third parameter is "count", not "position".
    docwiki.embarcadero.com - System.Copy - RAD Studio API Documentation

    ReplyDelete
  2. 2nd parameter is not needed either (when use on an array, string requires it though)

    FWIW the compiler passes High(Integer) as count parameter when you dont explicitly specify.

    ReplyDelete
  3. Didn't know that, simplifies code a bit

    ReplyDelete
  4. Didn't know either, I used MaxInt :)

    ReplyDelete
  5. Works in Delphi 2007 as well, for strings and arrays. Good to know.

    ReplyDelete
  6. works since Delphi 2010, also in FPC but I prefer being explicit.
    may be am being pessimistic. :)

    ReplyDelete
  7. ...and thanks for caring and sharing...

    ReplyDelete
  8. Sadly, in XE2 it does not work with dynarrays, only with strings...

    ReplyDelete
  9. 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?

    ReplyDelete
  10. Attila Kovacs Isn't that what RightStr is for?

    ReplyDelete
  11. Wow! All those (, , $ffff) i see. No more! Thx.

    ReplyDelete
  12. 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.

    ReplyDelete
  13. Stefan Glienke 64 bit compiler? Passes High(NativeInt) I hope.

    ReplyDelete
  14. Not really.

    Project60.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

    ReplyDelete
  15. 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.

    ReplyDelete
  16. 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.

    ReplyDelete
  17. Doesn't everyone use TStringHelper.Substring now? ;-) Here it is a documented feature that you can omit the length parameter.

    ReplyDelete
  18. Hans Lavdal Jakobsen .Substring works with 0-based indexes and so it cannot be used in a serious code.

    ReplyDelete
  19. Deadpan humor, man.

    Seriously, 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!

    ReplyDelete
  20. 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.

    ReplyDelete
  21. 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.

    ReplyDelete
  22. 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...

    ReplyDelete
  23. Hans Lavdal Jakobsen That's a sound plan. Mixing 0 based and 1 based is not a good idea.

    ReplyDelete
  24. Well, initial strings ( rebranded as short strings ) were 0-based and did not need SetLength function. Back in 1980-s it looked quite okay....

    ReplyDelete
  25. Arioch The actually, they were 1-based. Element 0 contained the length (and that's why it was limited to 255).

    ReplyDelete
  26. 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

    ReplyDelete
  27. No. The following code outputs 3 and 2 because byte 0 contains length and because indexing is 1-based.

    I 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.

    ReplyDelete
  28. 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?

    ReplyDelete
  29. Maarten de Vries I guess a proficient programmer that wants to know how a library function operates will read its documentation.

    It's the less proficient programmers, the ones writing shoddy code, that ignore the documentation and program by trial and error and guesswork.

    ReplyDelete
  30. 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.

    ReplyDelete
  31. 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

    ReplyDelete
  32. Maarten de Vries I read the What's New?, look through the Bugs Fixed list and compare the sources with the previous ones.

    ReplyDelete

Post a Comment