Professional Documents
Culture Documents
ABS B2C BITAND BITOR BITXOR C2B C2X CENTER CENTRE COMPARE CONDITION COPIES D2C DATATYPE DATE DELSTR DELWORD DIGITS ERRORTEXT FORM FORMAT FUZZ INDEX INSERT LASTPOS LEFT LENGTH MAX MIN OVERLAY POS RANDOM REVERSE SECTION INDEX THE LANGUAGE CONCEPTS INSTRUCTIONS CONDITIONS LOOPS OTHERS STRING FUNCTIONS ALIGNMENT COMPARISON COMBINING EXTRACTION SEARCH OTHER OTHER FUNCTIONS WORD NUMBER CONVERSION BIT PROGRAM PARSE EDITOR PARSE RIGHT VERIFY SOURCELINE WORD SPACE WORDINDEX STRIP WORDLENGTH SUBSTR WORDPOS SUBWORD WORDS SYMBOL X2C TIME X2D TRANSLATE XRANGE TRUNC VALUE
2. String Functions
2.1 String Alignment Functions: CENTER, CENTRE, LEFT & RIGHT
CenteredString CenteredString LeftAdjustedString RightAdjustedString = = = = CENTER( CENTRE( LEFT( RIGHT( Instr, Instr, Instr, Instr, Length, Length, Length, Length, PadChar) PadChar) PadChar) PadChar)
All of these are pretty standard really. LEFT & RIGHT are normally used to ensure that a string is a particular length for printing alignment. The LEFT function can be used to see if the first characters of one string are the same as another but it is better to use the ABBREV function for that type of thing.
CENTRE('hello',14) CENTER('=1234567890 abc---' = ' hello =',5) = '34567' ' CENTER('abc',8,'-') = '--
Note that you can use either the word CENTRE or CENTER it doesn't matter. It hardly needs saying but in all of these functions (and loads of others) the default pad character is a space. This pad is used when the source string is shorter than the length. If the CENTRE can not get it exactly right because there is an odd number of spaces, the leading gap is smaller.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
These two are doing exactly what they say they are: COMPARE compares two strings while ABBREV checks that one string is an abbreviation of the other. Note the odd purpose of the last argument on ABBREV, it checks that the abbreviated string is of a particular length! If it's not the function will always return a 0.
COMPARE('ABC','ABC') = 0; COMPARE('ABCD','ABC') = 4; COMPARE('ABC','ABCD') = 4; COMPARE('ABCD','ABcD') = 3; COMPARE('WXYZ ','WXYZ') = 0; COMPARE('ABC---','ABC-','-')=0 ABBREV('abcdefghi','abcd') = ABBREV('abcdefghi','abzz') = ABBREV('abcdefghi','abcd',6)= ABBREV('abcdefghi','abcd',4)= 1 0 0 1
Note that COMPARE is returning the position of the first mis-match while ABBREV is returning a Boolean 0 or a 1. On the second to last example ABBREV has returned a '0' because the second string is not 6 characters in length!
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
These two are used to put all or part of one string into another. The difference between the two functions is obvious INSERT doesn't over type any of the second string. Again we have a pad character (the default is a space) if the our string is less than the length we want to insert or overlay.
INSERT('12345','abcdef') INSERT('12345','abcdef',3) INSERT('12345','abcdef',3,2) INSERT('123','abcdef',2,5,'*') = = = = '12345abcdef' 'abc12345def' 'abc12def' 'ab123**cdef'
The most confusing thing here is the order of the first two strings, from these examples you can see that it's the 2nd argument, which is overlaid/inserted into the 1st argument. I use OVERLAY a lot when creating output lines. I set a line to be blank and then use OVERLAY to put into the output the variables at the required column. This may not be very efficient, but if that doesn't matter too much, you will find it very easy to built up an output line and modify it later. For example:
OUT OUT OUT OUT SAY = "" = OVERLAY( TimeVar , OUT , TIMECOLUMN ) = OVERLAY( DateVar , OUT , DATECOLUMN ) = OVERLAY( NameVar , OUT , NAMECOLUMN ) OUT TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
These functions are all to do with extracting part of string and putting it into another. DELSTR will delete a section of a string while SUBSTR does the opposite and extracts a section. You will find you hardly ever use DELSTR and use SUBSTR all the time With DELSTR if you don't code a length it will delete from the start point to the end of the string. With SUBSTR not coding a length means you get everything from the start position and the end of the string. When we say 'delete a section of the string' we don't mean that 'InStr' is change.
DELSTR('12345678',5)= '1234' '123678' DELSTR('abcdefgh',12) = 'abcdefgh' '45678' SUBSTR('12345678',4,2) = '45' ' SUBSTR('12345678',5,7) = '5678 ' '5678---' DELSTR('12345678',4,2) SUBSTR('12345678',4) SUBSTR('12345678',14,2) = = = '
SUBSTR('12345678',5,7,'-')=
As usual here are some amazing examples. Look at the first one, note that '5' is not in the returned string because it is the first character of the block to be deleted. Compare this with the first SUBSTR example where we do get a '4' because this is the first character of the sub-section that we require. Note if you find you need more than one SUBSTR instruction when getting different bits out of the same string, you should consider using PARSE VAR instead!!
TOP . . NEXT . . PREVIOUS . . INDEX . . SECTION INDEX . . FUNCTION-LIST . . HOME
These all search one string (the 'StingToLookIn' string) to see if it contains another (the 'StringToBeFound' string). POS and INDEX are the same but the 1st and 2nd arguments are coded in the reverse order. With any of these functions coding a 3rd argument limits the area searched. They return the start position within the 'target' string, which matches the 'find' string. LASTPOS searches from the right hand end of the 'target' string but it still returns the position from the front of the string.
POS('x', '1234567x90ABCDxFG') = 8 POS('xx','1234567xx0ABCDxxG',10)= 15 POS('z', '1234567x90ABCDxFG') = 0 INDEX('1234567xx0ABCDxxG','xx') = 8 LASTPOS('x','1234567x90ABCDxFG')= 15 LASTPOS('x','123x567x90ABCDxFG',10)= 8
Here are some examples to have a look at. Note that the functions return a '0' if the string is not found. Some platforms do not support both POS and INDEX (my Amiga does of course) but obviously this is not a headache. If you are looking for a single word (i.e. some letters with spaces either side) then you many want to use the WORDPOS function although this returns the word number not its position.
TOP . .NEXT . .PREVIOUS . .SECTION INDEX . .FUNCTION-LIST . .HOME
COPIES is used to multiple a string a number of times. It is far more useful than it sounds. If you wish to output lines of dashes or asterisks then use this function to generate them with a PageWidth variable in the second argument. That way when (not if) you decide you want longer or shorter lines you change one constant at the top. There is nothing odds about them worth mentioning, may be just that while on the Amiga only the first character of StringTobeRepeated is used on TSO its the whole string! Below is a near little program COPIES and RANDOM can be used.
/* REXX showing COPIES and RANDOM functions */ Array. = 0 ; PageWidth = 44 DO UNTIL Array.RandNum = (PageWidth - 8) /* DO TIL WEVE HAD ONE NO. 36 times */ RandNum = RANDOM(1,10) /* GET RANDOM NUMBER BETWEEN 1 -10 */
Array.RandNum = Array.RandNum + 1 ; END /* COUNT NO.OF TIMES WE GOT THIS NO.*/ SAY COPIES("*", PageWidth) /* PRINT LINE OF STARS */ DO X = 1 TO 10 /* PRINT NO.OF TIMES WE GOT RANDOM..*/ SAY RIGHT(X,2) RIGHT(Array.X,2) COPIES("*", Array.X ) END /* ...NO. + LINE FOR BAR GRAPH */ SAY COPIES("*", PageWidth) /* PRINT LINE OF STARS */ ----------------------------------------------------------------------******************************************** 1 23 *********************** 2 20 ******************** 3 14 ************** 4 17 ***************** 5 9 ********* 6 36 ************************************ 7 26 ************************** 8 22 ********************** 9 22 ********************** 10 25 ************************* ******************************************** TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
If you need help working out what this one can do its pretty sad. However one of the examples may give you a surprise, look at the last one!!!!
LENGTH(123456789) = 9 LENGTH(") = 0 LENGTH(ABCDEFGHIJKLM) = 13 LENGTH(COPIES("*",50)) = 50 LENGTH("12.000000000") = 12 TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This is a very silly function, I am sure there is an anorak who thinks that one day they may want to reverse the contents of a string but who else!
REVERSE('abcdefghijk') = 'kjihgfedcba' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This is very useful, it is usually used to ensure you have no spaces at the being or end of a string, however it can be used just to clear leading or trailing spaces or in fact any other characters.
STRIP(' remove spaces ') = 'remove spaces' STRIP(' leading only ','l') = 'leading only ' STRIP(' trailing only ','t') = ' trailing only' STRIP(' both (default) ','b') = 'both (default)' STRIP('---remove dashes---','b','-') = 'remove dashes' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
There are two purposes for this function, one simple, one not. If you just code one argument then all lower case characters in 'InStr' are converted to capitals! That's the simple one use. If 3 or 4 arguments are given then the conversion (translation) is more complex. The functions takes the 1st character in 'TranI' and hunts through 'InStr' and tries to finds all occurrences of this, these are changed into the first character in the 'TranO' string. In then hunts for the any occurrence of the 2nd character in 'TranI' and converts this to the second character in 'TranO' . It keeps going until all characters in 'TranI' have been converted. If it runs out of characters in 'TranO' then all remaining character in 'TranI' are converted to the pad character.
TRANSLATE('abcdefghi') = 'ABCDEFGHI' TRANSLATE('abcdef','123','abc') = '123def' TRANSLATE('abcdef','1','abcd','*') = '1***ef' TRANSLATE('No Exclaiming! Or questions?','','!?','.') = ' No Exclaiming. Or Questions.'
This starts off being quite sensible and ends up being heavily hairy. The first example shows a straightforward conversion to upper case characters. Look at the second example. This is converting any 'a' characters to '1's, any 'b's to '2's and any 'c's o '3's. All other characters are left alone - they are not even changed into upper case. The third example shows what happens when you add a 4th argument and the 2nd is shorter than the 3rd. Now any 'a's are converted into '1's but there are no character to correspond with b, c or d. Now that take the value of the 4th argument! A semi-practical example is shown last. Here we are converting all '!' and '?' to '.'.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
VERIFY can be used to check that all the characters in a 'target' string are in another 'reference' string. If there are no rogue character it returns a 0, if there are it's the position of the first bad one.
VERIFY('4567','1234567890') = '0' VERIFY('45x7','1234567890') = '3'
Here are some examples. The first checks to see if the string '4567' just contains any character between 0 and 9, as it does the result is a zero. In the second example the 'x' means the result is 3, the position of the 'x' .
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
Three of the examples show how we can build the reference string required for VERIFY with XRANGE. This could be much easier if it's a very long range.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
3. 3. Other Functions
3.1.1 The WORD function
TheNthWord = WORD(InputString, NoOfWordRequired )
Highly simple this, the WORD function always returns one word of an input string, which word will depend on the number given in the second argument.
WORD('one two three four five',3) = WORD('one two three four five',1) = WORD('one two three four five',6) = 'three' 'one' ''
Not a lot more to say really except remember there is also a WORDS function (returns the number of words in a string) and its easy to get the two confused.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This function returns the position of a word!!! You can see from the examples below the position is the character position.
WORDINDEX('one two three four five',3) = '9' WORDINDEX('one two three four five',4) = '15'
Don't get this function confused with WORDPOS , which is searching a string for a word.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This function searches a string for a word and returns the word number if the word is found.
WORDPOS('four','one two three four five' ) = '4' WORDPOS('five','one two three four five',3) = '5'
This function returns the length of a word within a string, the second argument gives the number of the word for which we require the length.
WORDLENGTH('one two three four five',3) = WORDLENGTH('one two three four five',5) = '5' '4'
This function extracts part of string, the second argument gives the first word to be copied and the third argument gives the no of words to be copied.
SUBWORD('one two three four five',3) = 'three four five' SUBWORD('one two three four five',3,2) = 'three four'
You may be better off using SUBSTR which works on character positions and character length it all depends on what you are doing.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This function copies the whole string except a block defined by the 2nd and 3rd arguments. The 2nd argument is the number of the first word not to be copied and the 3rd argument (if coded) is the number of words not to be copied. If the 3rd argument is not coded all the remaining words are not copied.
DELWORD('one two three four five',3) = 'one two ' DELWORD('one two three four five',3,2) = 'one two five' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This very simply tells you have many words are in a string!
WORDS('one two three four five') = '5' WORDS('' ) = '0'
In its simplest form this function will output a string with only one space between each word. However to get this to happen you must give the 2nd argument a value of 1. Its default value is zero, which will remove all the spaces. If a 3rd argument is coded, this is the character between the words (the default being a space of course)
SPACE(' one two three four ') = 'onetwothreefour'
SPACE(' one two three four ',1) = 'one two three four' SPACE(' one two three four ',3,'_') = 'one___two___three___four' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
= hh (whole since midnight) = mm (whole since midnight) = ss (whole since midnight) 'C' = hh:mmAM/PM
The little baby has two uses, the first obvious one is to tell you what the time is on any of the formatted detailed above. It can also be used as a timer which can be very useful as well as a bit of fun. Code TIME('R') near the beginning of a block of code and SAY "elapsed time=" TIME('E') after it. Record the time and then try changing the code, use different functions of many be different loop options. Record the time again and see if you change has altered the speed of your code. Sometimes the results are quite surprising.
TIME() = '20:04:41' TIME('N') = '20:04:41' TIME('C') = '8:04PM' TIME('H') = '20' -completed hours from midnight. TIME('M') = '1204' -completed mins. from midnight. TIME('S') = '72281' -completed secs. from midnight. TIME('R') = '0.00' - Start timer. DO X = 1 TO 1000: END TIME('E') = '0.006' -seconds since reset.
If you want the split up the current time considering using PARSE with an instruction like this:
PARSE VALUE TIME() WITH hhVar ':' mmVar ':' ssVar TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
Here WYSIWYG. Note that I have found the 'J' option doesn't work on all platforms.
DATE() = '02 Nov 1997' DATE('N') (Normal) = '02 Nov 1997' DATE('E')(European) = '02/11/97' DATE('U') (USA) = '11/02/97' DATE('O') (Ordered) = '97/11/02' DATE('S') (Sorted) = '97/11/02' DATE('D') (Julian) = '306' DATE('M') (Month) = 'November' DATE('W') (Weekday) = 'Sunday' DATE('B') (Base) = '729695'
Don't try and work out the 'B' unless you understand all the rules for leap year and you now your date-alignment history!!
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
6 6 6
3 4 5
___ ___ 1.11144 1.11122 - considered the same. ____ ____ 2 1.11144 1.11122 - considered the same. _____ _____ 1 1.11144 1.11122 - considered the same. TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME 3
In the program above you can see how the exponential format can be changed. Note how the NUMERIC DIGITS instruction can be used to alter the length a number needs to be before the exponential format is invoked. The usual default is 9 but the D IGITS() function will always tell you what the value is.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
The 2nd argument gives the number of places to the right of the decimal point, the 3rd digit gives the number of spaces after the decimal point.
FORMAT(' 123.456789',4,4) = ' 123.4567' FORMAT('12.34',5,4) = ' 12.3400'
Note that the number is always padded out with spaces if necessary. Note that sometimes it may be better to use TRUNC function.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
The 2nd argument can give the number of places to the right of the decimal point,
TRUNC(' +0123.45678 ') = '123' TRUNC(' +0123.45678 ',2) = '123.45'
Note that the number is always padded out with spaces if necessary. Note that it may be better to use FORMAT if you want to ensure the number is a specific length for output alignment.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
Here's a program using MIN , MAX and RANDOM. Note that I've had to use INTERPRET because of the commas between the numbers.
/* REXX Number functions */ NumString = RANDOM(1,50) DO A = 1 TO 7 NumString = NumString || "," RANDOM(1,50) END SAY 'Numstring =' NumString INTERPRET "SAY 'Highest =' MAX(" NumString ")" INTERPRET "SAY 'Lowest =' MIN(" NumString ")" ------------------------Numstring = 25, 42, 28, 42, 10, 21, 23, 22 Highest = 42 Lowest = 10 TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
'1' if the data in the input string matches the type you are looking for or '0' if it doesn't. Note the fact you can look for a whole number, when checking data this may be better than seeing if the result is 'NUM' . These are the options you can code.
either BooleanNo = DATATYPE( String , Option ) or CHARorNUM = DATATYPE( String ) Options: A - Alphanumeric (A-Z,a-z,0-9) N - Valid Number B - Binary only (0,1) U - Uppercase only (A-Z) L - Lower case only(a-z) W - Whole Number M -Mixed case (A-Z, a-z) X - Hexadecimal (0-9, A-E) S - Valid REXX Symbol(A-Z,a-z, 0-9 ! ? _ .)
Some Examples:
DATATYPE('+123.4567') = 'NUM' DATATYPE('This is not a number.') = 'CHAR' DATATYPE('Only4AlphanemericChars','a') = '1' DATATYPE('No spaces or specials!','Alphanum') = '0' DATATYPE(SPACE('Include Spaces',0),'A') = '1' DATATYPE('onlylowercasechars','l')(Lowercase) = '1' DATATYPE('MixedCaseCharacters','m')(Mixedcase)= '1' DATATYPE('UPPERCASECHARACTERS','u')(Uppercase)= '1' DATATYPE('Valid_REXX_Symbol','s) (Symbol) = '1' DATATYPE('Not a Valid Symbol','s') (Symbol) = '0' DATATYPE('010101110010111010111','b')(Binary) = '1' DATATYPE('A3b6C35689e2A9C4c905fff','x') (Hex) = '1' DATATYPE('+123456.7890000000','n') (Number) = '1' DATATYPE('+123456','w') (Whole number) = '1' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
C2B(BITOR('00010001'b,'01010101'b)) = '01010101' C2X(BITOR('11'x,'55'x)) = '55' C2B(BITXOR('00010001'b,'01010101'b)) = '01000100' C2X(BITXOR('11'x,'55'x)) = '44' C2B(BITAND('11110000'b,'00111100'b)) = '00110000' C2X(BITAND('F0'x,'5C'x)) = '50' TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
If you hit an un-recoverable error in your program you may want to use this to jump to a routine which is going to detail all the horrible things that have just happened (to create the error) before ending execution. The advantage of coding it in a separate routine is that it gets all the messages out of the main body of the program and also it may get called from one of several instructions. The S IGNAL ON condition can be used to say when you should jump to your error routine and what the routine is called (trapname). The 'condition' can be:
ERROR - external command error FAILURE - external command failure. HALT - on external halt request. NOVALUE - using an un-initialized variable. NOTREADY - i/o stream error SYNTAX - syntax or execution error.
The difference between S IGNAL and C ALL is that S IGNAL will not return you from the function it acts as a G OTO. Note that some of the conditions can not be used with C ALL. The C ONDITION function can be placed in an error sub-routine and it will give you some useful data about the error. Without an option it will say whether a CALL or a S IGNAL (not very exciting) involved the routine. An Option of ' C' returns the condition name, for example ' ERROR' or' N OVALUE'. An option of ' D' gives the type of trap. An option of ' I' returns ' SIGNAL' or ' CALL' depending on how the routine was requested. An option of ' S' returns the status of the trapped condition.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
When you execute an error function it may be useful to know which line of your program invoked the error which created the jump to the function. The variable SIGL is defined
for you and gives you the line number. The SOURCELINE function can be used to print out that line of code. See the program in the next section for an example.
TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
The RC variable is another one set for you and it gives the error code number. Unless you are very clever (in wish case you wont be reading this) this number is not much good but feed it as the argument to ERRORTEXT and it will give you a description of the error. See the example here:
/* REXX Showing the SIGNAL instruction */ 1 SIGNAL ON SYNTAX 2 My_Result = 0 3 IF MyResult THEN SAY "HELLO" 4 EXIT 0 5 SYNTAX: 6 SAY "*** SYNTAX / EXECUTION ERROR******" 7 SAY "Line Number:" SIGL 8 SAY "The Line read '" || SOURCELINE(SIGL)"'" 9 SAY "The Error was:'" || ERRORTEXT(RC)"'" 10 SAY "(Total Lines): " SOURCELINE() 11 SAY "************************************" 12 RETURN 0 OUTPUT---------------------------------------------*** SYNTAX / EXECUTION ERROR****** Line Number: 3 The Line read 'IF MyResult THEN SAY "HELLO"' The Error was:'Boolean value not 0 or 1' (Total Lines): 16 ************************************ TOP . . NEXT . . PREVIOUS . . SECTION INDEX . . FUNCTION-LIST . . HOME
This is similar to the INTERPRET instruction. The template above InString is a variable that would contain the name of a 2nd variable. The function would return the contents of this second variable.
/* REXX program to show VALUE() */ A = 23 B = A SAY VALUE(B) -------------------------------23
I've never found this particularly useful! It will tell you if the contents of Instring is a valid variable name by returning V AR, a valid symbol name by returning LIT or BAD if its neither.
END OF FUNCTIONS
GOTO PARSE