The only problem with the %CHAR BIF is that it brings over the period and commas and removes any leading zeros. And sometimes that is not what you want. Fortunately, there are a couple of other BIFs that you can use. Part One here.
Editor's Note: This article is excerpted from chapter 12 of 21st Century RPG: /Free, ILE, and MVC, by David Shirey.
%EDITC (Edit with Edit Code)
This BIF also allows you to specify a numeric value or expression and return a character string. Why would you use this when you can use the %CHAR? Flexibility. You have more options here than you do with the straight %CHAR.
There are really four parms involved: two required and two optional.
%EDITC(numeric : edit code : [*ASTFIL] : [*CURSYM])
Numeric is the numeric value or expression that you are going to screw around with.
Edit code is the RPG edit code that you want to use. It must be one of the valid RPG edit codes that I can never remember, and it has to be enclosed in quotes.
*ASTFIL is optional and, if specified, will left-fill any leading zeros with asterisks.
*CURSYM is optional and allows you to specify a currency symbol that will be placed to the left of the first significant digit.
What will the resultant field look like? Sort of depends on the edit code that is used. Pick the one that shows the format the way you want it to look.
%EDITW (EDIT with Edit Word)
The last character-conversion BIF we will look at is similar to %EDITC except that now you are using an edit word, not an edit code.
%EDITW (numeric : 'edit word');
There are a couple of things to remember here. First, this baby won’t work if you have a floating point representation. In that case, you would have to use %DEC to convert the floating point to packed and then go from there. But, remember that since the BIF will allow you to specify another BIF as an operand, you can do it within this function.
The edit word parm must then be a valid edit word. It has to be enclosed in quotes and have valid edit word formats. Again, what the result looks like will depend on the edit mask that you use. But it will be character.
%EDITFLT (Edit with Floating Point)
Just for the heck of it, I am going to do one more, although you probably won’t use this that much. This BIF converts any numeric value (including floating point) into a 23-position character value, the international standard for a floating-point field.
%EDITFLT(numeric value or expression);
Not much to say. Use it if you need it.
Date and Time Stuff
The most useful BIFs for me are the date-oriented ones. There are a number of formats available, so let’s go through this one at a time.
%Date();
%Time();
This format, sans parameters, will give you today’s date or time. The default is *ISO and *USA, and if you want another format when using the ( ) parm, too bad, you can’t have it. To do that, you have to use the format below.
%DATE(value or function : date-format-code);
The second option will convert a value or function into a date-type field.
This value can be either numeric or character. If you are using a character field, then you can also stipulate a separator value. That is not allowed if you use a numeric value.
So, if we did want to pick up today’s date in a format other than *ISO, we could simply specify:
x = %date(%date():*MDY);
This is the real power of the BIFs: the fact that they can be used in lieu of variables in another BIF statement.
Dates can get very complicated, and switching between the different formats can be challenging.
SCAN, REPLACE, XLATE
There are a number of BIFs that allow you to operate on character strings and either replace whole sections of the string or else specific characters within the string.
%REPLACE
Often you need to modify a character string, and there are several ways to do this. The first is the replace, which allows you to replace part of one character string with another.
%REPLACE(new string : old string : start position : length);
Remember that %REPLACE operates at the string level. It only replaces those characters that match the replacement string value.
%SCAN
%REPLACE is often used in tandem with %SCAN, where the %SCAN is issued first and is used to determine the starting position for a replace operation.
%SCAN(pattern : data to be scanned : start position);
In this case, the %SCAN will return a value that shows the position in a string (data to be scanned) where the pattern we are looking for first appears.
%CHECK
The mirror-image companion to %SCAN is %CHECK. This BIF will also go through a character string, but instead of finding a character that is in a pattern as %SCAN does, it looks for the first character in the string that is not in the pattern and returns its position.
%CHECK(pattern : data to be checked : start position);
Nominally, this function goes from left to right in the character string, but there is also a %CHECKR that goes upstream, if that is your preference.
Remember, it is not looking to see if the whole pattern is in the data; rather it looks to find a character in that data that is not in the pattern set.
%XLATE
The %XLATE function is similar in that it replaces characters, but this is on a more selective basis.
%XLATE(from-pattern : to-pattern : initial-value : start position);
The function uses two patterns, rather than straight character strings. The patterns show what should be substituted for what. For example, if we had a date field and we wanted to change the separation characters, we could do this. Note that here we are assuming we will start in the first position, so it is not specified.
%XLATE(- : / : '2015-03-02')
and it would be translated to 2015/03/02.
The thing that you have to remember about %XLATE is that it is not operating on a character string. It is operating on individual characters within that string. As a result, if you set up a BIF such as
%XLATE('AB' : '12' : input) where input = 'ABAA1136B'
then this will be translated as 121111362, not as 121136B because the function is not operating on AB, but on A and B separately.
Trim
Finally, we will go over the trim functions, again dealing with character strings. There are three of these.
%TRIM
%TRIMR
%TRIML
The descriptions of these three BIFs are pretty self-explanatory: remove leading and trailing characters (not just spaces), remove trailing characters, and remove leading characters.
%TRIM( base value : trim characters);
The trim character is optional and, if left off, then is assumed to represent blanks. If there are multiple characters to be trimmed, they can just be listed in a line with no separation characters. So, for example:
%TRIM(address : '.,');
will remove both periods and commas from the address.
To remove blanks when you specify characters, simply include a blank in the character string to be removed.
Why Personal Responsibility Matters
BIFs are great tools, but, like most things, they must be used responsibly.
The fact that a BIF can act on another BIF seems to have given some people the license to pile BIF on BIF in a single statement until it takes an IT lawyer to separate out who did what to whom. You end up with BIFs operating on BIFs, which are the results of other BIFs. In some cases, this is the only way to do things, but in others it is just showmanship.
And I guess there are different levels of understanding in the IBM i community. Most of us like things bite-wise, one step at a time. But some people, and often they are the ones writing articles, move faster and can digest more in one step.
I am not one of those people. I need things set up in a logical order. And so, in case I ever have to look at your code, I recommend that rather than writing five BIFs in one, that you break them down a bit. It may require some intermediary fields, but I think that will be overshadowed by the step-by-step progression of the separate BIFs.
Just my opinion. Everyone may be smarter than me, and I would not be surprised. Follow your heart on this one.
What Ya Shoulda Learned
There are a few things I want to be sure that you take away from this.
First, get away from the old RPG III way of converting data from one format to another (by using MOVEs and a bunch of work fields). Similarly, get away from reviewing text strings by putting them in an array and using a loop.
Instead, start using BIFs to do this kind of processing. It is cleaner, involves fewer lines of code, and is quite similar to the PHP way of handling things through functions.
Second, there are quite a few BIFs, and you should be familiar with most of them, at least as far as knowing they exist and what they do. For more information about what you can do with BIFs, I would start with the two references I mentioned earlier.
Third, you should know that one of the big strengths of BIFs is that they can be used in tandem. That is, since a BIF is a function that returns a value, you can easily use a BIF as an argument for another BIF. A good example is if you want to get a date and then convert that to a straight character string.
Sometimes the most difficult thing is reading compound BIFs, and for that I would recommend spending some time poring over the examples in the search400 reference I mentioned.
Fourth, you need to set aside some time to play with these things. Don’t just assume they will work the way you think they will. I mean, how many other things in your life have worked out that way? No reason it should start now. BIFs are a serious way to save time and make your coding less confusing (although a few comments sometimes when you have multiple BIFs in a function is not a bad idea).
Want to learn more? You can pick up Dave Shirey's book, 21st Century RPG: /Free, ILE, and MVC, at the MC Press Bookstore Today!
LATEST COMMENTS
MC Press Online