fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC:

Comparison of (Ansi) strings 26 Feb 2020 17:43 #13474

  • ArneOrtlinghaus's Avatar

  • ArneOrtlinghaus

  • Topic Author


  • Posts: 188
  • How can I influence the sorting of strings?
    The following code does not give the same order as in VO. In VO I would have the same order as the input array (ordered similar to the internal ASCII value, in X# I have something like chr(1), chr(2), ..., chr(6), chr(149), chr (7), ..., chr(15), chr(164), chr(16), ..., chr(19), chr(182), chr(20), chr(167). chr(21), ..., chr(33), chr(147), chr(148), chr(168), chr(34), ...

    a :={}
    for i := 1 upto 255
    c := chr(i) + "_" +ntrim(i)
    aadd(a, c)
    next

    ASort(a)
    msginfo(array2string(a, crlf))

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 26 Feb 2020 20:12 #13483

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Arne,

    Is this real text that you are trying to sort, or is it binary data? Due to string in .Net being unicode, Chr() for values 128...255 will not give a char with that unicode value, it will instead return the equivalent unicode char, so you cannot directly compare this routines in VO and .X#.

    If it's binary data that you are working with (it does look like it), then I think the best way to deal with it is to create your own sorting and/or use standard .Net functions like String.Compare()
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 26 Feb 2020 20:18 #13485

  • Terry's Avatar

  • Terry


  • Posts: 184
  • Arne

    Don't know why things are different in VO.

    But format the composite string (c in this case) in the order you want.

    for example c:=ntrim(i) + chr(i).

    Convert i to a string and pad it left before adding it to the array.

    This should work for any string complexity. Others may know a better way.

    Terry.

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Feb 2020 09:07 #13491

  • ArneOrtlinghaus's Avatar

  • ArneOrtlinghaus

  • Topic Author


  • Posts: 188
  • Hi Chris and Terry,

    In VO we use this possibility to order records by several columns composing it to one unique sort string which is used by a Quicksort procedure. In case of descending the ANSI characters are substituted by chr(255)-chr(xxx). Probably we have other places where we use some sortings related to the ANSI values.

    Now I am searching for something similar. I have looked into the DLL Xsharp.core and tried to understand working of ASC and CHR. There a helper class stringhelpers is used. This class contains a method CompareWindows, which seems to be what I could need. Is it possible to use this method?

    Arne

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Feb 2020 09:25 #13493

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Arne,

    Chr(255) - Chr(xxx) will not work in .Net, unless you only use standard Latin chars (< 128 ascii), so no umlauts etc. Why don't you just sort in reverse order?
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Feb 2020 09:39 #13497

  • ArneOrtlinghaus's Avatar

  • ArneOrtlinghaus

  • Topic Author


  • Posts: 188
  • Hi Chris,
    some columns are sorted in ascending order and some in descending order, just as the user selects it. For the first column I can use reverse ordering in case of descending. But if the other columns differ from the selection of the first column, I have to "reverse" the character sequence of that part. Until now this worked also quite well for the west european characters above 128 ascii.

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Feb 2020 10:55 #13501

  • Terry's Avatar

  • Terry


  • Posts: 184
  • Hi Arne

    >> There a helper class stringhelpers is used. This class contains a method CompareWindows, which seems to be what I could need. Is it possible to use this method?

    Sorry I can't answer that - I just don't know.

    But the way I suggested will work, and with suitable conditional extractions you'll be able to sort things in whatever way or ways you like.

    You are only sorting through 256 characters, it's not much so the following won't apply; but it is worth bearing in mind should you ever want to do the same thing over thousands, then strings are immutable and some forced garbage collection may improve performance.

    It may be the "CompareWidows" method includes something like that.

    Terry

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Feb 2020 11:00 #13502

  • ArneOrtlinghaus's Avatar

  • ArneOrtlinghaus

  • Topic Author


  • Posts: 188
  • A workaround now works when transforming the single bytes to hex strings. Indeed it is more a binary comparison than a real string comparison. I have found some other places which I have to look at.
    There are places we have used chr(255) assuming that it is a placeholder for the last possible character. Looking at my Tests in X#, chr(255) = ÿ comes to position 225 and is located for example before Ö chr(214) and
    Ü chr(220) which are used in German.

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 28 Feb 2020 17:36 #13527

  • ArneOrtlinghaus's Avatar

  • ArneOrtlinghaus

  • Topic Author


  • Posts: 188
  • Looking again at the code I have found some switches that influence string comparisons:
    - The compilerswitch /VO13 Compatible string comparisons
    - If set, the Setexact() and the Setcollation() settings. In our case /VO13 is set, SetExact is false. Testing the collation modes SetCollation(#clipper), SetCollation(#ORDINAL), SetCollation(#windows), SetCollation(#UNICODE) changed the behavior of sorting, but did not reproduce the same result as in VO.

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 28 Feb 2020 18:07 #13528

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Arne,

    Yes, for compatibility with VO you need to use /vo13, same with almost every other vo compatibility option. Also note that #ORDINAL and #UNICODE did not exist as collation settings in VO, so you need to use either #CLIPPER or #WINDOWS

    Also please remember the fundamental difference between VO and X#, VO has 8-bit strings, while X# (.Net) has unicode ones. String comparison in X# was designed in such a way to give correct (compatible with VO) results when "real" text is used (so it makes the necessary ansi<->unicode conversions), not with binary data. And using Char(255)-Chr(realchar) effectively changes the text into binary data.

    Have you seen any difference of the behavior of X# to the one of VO with text data? If you have, can you please post a sample so we can look into it?
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Jul 2020 18:58 #15337

  • GregG's Avatar

  • GregG


  • Posts: 7
  • Hi Chris,

    Chr(128) returns C7 and ChrW(128) returns 3F. What is the correct, in a VO-compatible application with SetAnsi(False), to get the value of 128 to be 80?

    Thanks,

    Greg

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Jul 2020 20:16 #15339

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Greg,

    You mean 80 in hex right? In this case, you need to use ChrW(), this alternative version of Chr() does not make any ansi<->unicode conversions, and instead returns the unicode char with the exact value you specified. Not there's also AscW(), which does the opposite thing (since Asc() also does unicode/ansi conversions)
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 27 Jul 2020 20:37 #15340

  • GregG's Avatar

  • GregG


  • Posts: 7
  • Hi Chris,

    Yes, sorry, I should have clarified that we're trying to get 0x80. As mentioned, ChrW(128) results in a hex value of 3F.

    Thanks,

    Greg

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 28 Jul 2020 00:45 #15343

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Greg,

    Oh, sorry, I did not read your post carefully enough! But there is no reason for ChrW() to return anything else than the exact value you pass to it. How are you checking what is the actual value? You must not use Asc() for that, because this will also do ansi<>unicode conversions, while AscW() will indeed give you the actual unicode value. If it's not Asc() that you are sing, can you please show how you do the check, or where you see the result of ChrW(128) being different from 128?
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 28 Jul 2020 01:51 #15344

  • boonnam's Avatar

  • boonnam


  • Posts: 61
  • Chris,

    We are writing ChrW(128) to a text file and reading it with a hex editor shows a value of 3F.

    0-127 appear to be correct, and so are values 129-255.

    Please Log in or Create an account to join the conversation.

    Comparison of (Ansi) strings 28 Jul 2020 09:36 #15345

  • Chris's Avatar

  • Chris


  • Posts: 2039
  • Hi Boonam,

    OK, that's because also the file read/write functions (FWrite() etc) do ansi<>unicode conversions, that's necessary in order to correctly output international characters. Edit: That is, if you are using those functions to output the data of course!

    Is it only this 128 char that you want to write in the file as "binary" value and the rest of the contents are normal text? In this case, you must actually use Chr(128) (not ChrW(128)), because the two conversions will cancel each other and the char value of 128 will be saved on disk.

    If it's all binary data, then you should better use the FWrite3() function that deals with it, or even better use methods of the System.IO.File class, which give you full control over how you write the data to disk.

    Also please keep in mind that if you are using FRead() and similar functions to read back the data, there are again ansi to unicode conversions taking place that you have to consider, since even though the byte 128 has been written on disk, FRead() will result to a different char...

    I know, it can become really complicated, so I think the best way to deal with this is to please tell us exactly how you are using those files and what kind of text and data are written to it, so we can suggest the best way to deal with all those conversions.
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Last edit: by Chris.
    • Page:
    • 1