Need help with some text functions

I wonder if that was from the days of a 16 bit compiler as I have always understood LONGs to be fastest in 32 bit. When I get time I will do some testing.

thanks Carl for delving into the generated assembly to see why using numeric comparisons is faster than the string comparisons on the case statements.

yes perhaps “technically”. We will all face challenges if/when forced to use Unicode or I guess any other data format where there is no longer a 1:1 correspondence between byte and character.

And so old habits will need to change if/when that time comes and code will need to be re-visited. I guess it depends if you know the format of your data and if you want to take the inevitable performance hit earlier or later.

On the one hand you have the “don’t waste resources coding now for things that may never happen” school and on the other you have “just remember Y2K”.

Of course some users (depending on the languages they are catering for) may already have this requirement and so will already have adjusted their coding practices whereas for others (perhaps mainly English speaking?) this is yet to become an issue.

anyway at the least it is something to be aware of and bear in mind.

Donn you are putting a procedure in the embed that mentions Routines.

See if there is something like

! Start of “Local Procedures”

and if using a local procedure you will also need to put a prototype in a MAP.

I usually put in a MAP just before the procedure’s CODE statement.

But to be honest it is probably easier for a beginner to not have the procedures local - just create separate procedures and if you make them global (there is a check box) then they will be in scope and all should compile without further problems.

1 Like

The sooner we start thinking in terms of 1 char <> 1 byte, and the sooner we start applying that to our code the
a) easier it will be to refactor old code when the time comes and
b) less code will need refactoring when the time comes.

Thanks for sorting out my confusion. I am busy experimenting.

In the meantime I have another solution, based on what Bruce said, in the TakeCompleted section of the form

The DO FullNameCalc is working exactly as I wanted, too.

Everyone who contributed has taught me something, for which I am most grateful. Thank you one and all!

I see that the problem is solved, just want to add one more solution with regular expressions (one of the Clarion implementations could be found here). Below is SortField calculation as Donn described in starting topic.

sSortField                      STRING(6)
re                              TJSRegExp

  re.CreateNew('[^a-zA-Z]', 'g')    !- remove any char except latin letters
  sSortField[1:3] = UPPER(re.Replace(pLastName, ''))
  sSortField[4:6] = LOWER(re.Replace(pFirstName, ''))
  
  MESSAGE(sSortField)
1 Like

You said you wanted to learn Clarion … Being able to create your own Functions and call them is a common need. I’ll repost the code and the MAP you need to do that …

I’ll keep it simple. My chars have 8 bits, just like .KeepChars() works Bruce. I’ll make them local functions, when that works we can make the APP functions.

#1 - In Embed “Local Data - Other Declarations” put the MAP Prototype declarions. In Clarion you must Declare and Define.

   MAP
SortName3x3   PROCEDURE(STRING pFirstName, STRING pLastName),STRING
SortPart4Name PROCEDURE(*STRING pName, BOOL pIsLastName=1, BYTE pLenPart=3),STRING
   END

#2 - In Embed “Local Procedures” define your Procedure. Note here the “Parameters” have the RETURN as a ! comment ()!,STRING because that only goes in the MAP.

SortName3x3 PROCEDURE(STRING pFirstName, STRING pLastName)  !,STRING
    CODE
    RETURN SortPart4Name(pLastName, 1,3) & |
           SortPart4Name(pFirstName,0,3) 

SortPart4Name PROCEDURE(*STRING pName, BOOL pIsLastName=1, BYTE pLenPart=3)  !,STRING
Part STRING(pLenPart)  !<-- Sized as specified
P   BYTE
X   LONG,AUTO
    CODE
    LOOP X=1 TO SIZE(pName)
        CASE pName[X]
        OF   'a' to 'z'      !First as more common                                             
        OROF 'A' to 'Z'
           P += 1
           Part[P]=pName[X]
           IF P=pLenPart THEN BREAK.
        END
    END
    Part=CHOOSE(~pIsLastName,lower(Part),UPPER(Part))
    RETURN Part

#3 - In Embed “Procedure Routines”

NameCalcs ROUTINE
  Cus:FullName=LEFT(CLIP(Cus:FirstName)&' ') & Cus:LastName
  DISPLAY(?Cus:FullName)
  Cus:SortField=SortName3x3(Cus:FirstName,Cus:LastName)
  DISPLAY(?Cus:SortField)    

The code you posted earlier had an extra “)” that would cause a compile error.

image

I’ll toss out this code as possibly better for non A-Z alphabets. I don’t deal with international issues so YMMV. Read the docs on IsLower(). Edit: change *STRING to no * because PName gets changed.

SortPart4Name PROCEDURE(STRING pName, BOOL pIsLastName=1, BYTE pLenPart=3)  !,STRING
Part STRING(pLenPart)  !<-- Sized as specified
P   BYTE
X   LONG,AUTO
    CODE
    pName=CHOOSE(~pIsLastName,lower(pName),UPPER(pName))
    LOOP X=1 TO SIZE(pName)
        IF ( pIsLastName AND isUPPER(pName[X])) |
        OR (~pIsLastName AND ISlower(pName[X])) THEN 
           P += 1
           Part[P]=pName[X]
           IF P=pLenPart THEN BREAK.
        END
    END
    RETURN Part

Hello again Donn

to be honest this is something of a variation on what I gave you early on (just scroll up) when I posted :

st stringTheory
sortField stringTheory

(snip)

st.setValue(upper(LastName))
st.keepChars(‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’)
sortField.setvalue(st.slice(1,3))
sortField.setLength(3) ! in case last name < 3 chars

st.setValue(lower(FirstName))
st.keepChars(‘abcdefghijklmnopqrstuvwxyz’)
sortField.append(st.slice(1,3))

mySortField = sortField.getValue()   

However there is a bug in what you have now implemented in that it does not cater for the possibility of a last name with fewer than 3 characters. This was the purpose of this line above:

sortField.setLength(3) ! in case last name < 3 chars

just another thought Donn as there are always lots of ways to do these things.

where you currently have

cus:SortField = stL.sub(1,3) & stF.sub(1,3)

you could fix the problem of a short Last Name by using string slicing on the LHS as Mike did in his example:

cus:SortField[1 : 3] = stL.sub(1,3)
cus:SortField[4 : 6] = stF.sub(1,3)

note you could also have used stL.slice(1,3) or even just stL.getvalue()

in fact you could have done it with just one ST object:

st stringTheory

(snip)

st.setValue(upper(cus:LastName))
st.keepChars(‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’)
cus:SortField[1 : 3] = st.slice(1,3)

st.setValue(lower(cus:FirstName))
st.keepChars(‘abcdefghijklmnopqrstuvwxyz’)
cus:SortField[4 : 6] = st.slice(1,3)

again you could have just used st.getValue() instead of st.slice(1,3) or st.sub(1,3) but I think the intention is probably clearer using slice or sub.

re Carl’s comment about learning Clarion, I agree you will learn more doing it by “long hand” and I recommend you get Carl’s version working for you and make sure you study and understand it as you will definitely learn more.

once you have that knowledge it will also help you understand that string classes like ST can save you a lot of work.

You guys have all taught me so much. I’m really grateful. It has given me the confidence to continue with my project. I will pay it forward at some point.

Thank you to Carl, Geoff, Mike, Bruce, Richard, Douglas, Jeff and Sean. You have each taught me stuff, and encouraged me tremendously, even when I got things wrong.

1 Like

You learn more by fixing a fkuc up than any other time :laughing: … and the stress usually means you remember it for next time :upside_down_face:

1 Like

That is absolutely true, and funny too :rofl: I have made plenty of mistakes and you guys have been gracious enough to help me fix them and learn.