• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru Classic: A Bevy of BIFs – %SCAN and %CHECK

    January 16, 2019 Jon Paris

    Many RPG programmers seem to get confused about the usage and operation of a number of built-in functions (BIFs). In particular the BIFs %XLATE, %REPLACE, %SCAN, and %CHECK seem to cause a lot of confusion. In this tip, I focus on %CHECK and %SCAN. I decided to re-visit this particular tip because of the recent introduction of %SCAN’s companion BIF %SCANR and a related enhancement to %SCAN itself. More on this later.

    The %SCAN BIF has been with us since V3R7, when it was introduced along with %EDITC and %EDITW, to improve string handling. %CHECK, on the other hand, is a relative newcomer, having been introduced in V5R1 to support the functionality of the old CHECK op-code in /Free form coding. As with all BIFs, one of the major advantages compared with the old op-code version is that the BIF can be used directly in a conditional expression–no need to create a temporary work variable and test that.

    Here’s the syntax definition for our two BIFs:

    %CHECK( comparator : base {: startpos})
    %SCAN( search argument : source {: startpos} {: length}})
    

    As you can see the parameters are at first glance very much alike, particularly if, like me, you tend to mentally convert terms such as “comparator” to “search string”. Perhaps this accounts in part for the confusion. But there are two very big differences between these two BIFs.

    This story contains code, which you can download here.

    The first is that with %CHECK, the compare string is treated as a list of individual characters, whereas %SCAN operates on it as a single string. The second is that %SCAN tries to locate an occurrence of the characters in the search argument, whereas %CHECK tries to identify any characters that are not present in the compare string.

    %CHECK

    Let’s review the operation of %CHECK first. This BIF steps through the input a character at a time, comparing each one with the list in the compare string. If it encounters a character that does not exist in the compare set, it returns the position of that character in the input string. In other words, you can think of the compare string as being a list of the characters that are valid in the input field.

    For example, a compare string that validates the individual characters in a phone number field might look like this:

    '0123456789-( )'
    

    Since %CHECK is a function, it can be used directly in validation tests such as this one:

    If %Check( ' 0123456789-()': character) <> 0;
        // Bad character in phone #
    EndIf;
    

    This is useful where the actual position of the “bad” character in the string is not important. Note that in practice I would have coded the string of valid characters as a constant, but I coded the literal in this example for ease of explanation.

    %CHECK has a companion BIF, %CHECKR, which works exactly like %CHECK, but backwards. In other words, it begins its scan at the right-hand end of the input field. At one time this feature was very useful when dealing with fields that were padded with characters other than spaces. However, the %TRIMx family of BIFs has been updated to allow any specified character to be trimmed, so %CHECKR has less utility than it once did.

    %SCAN

    Like many RPGers, I used to have problems remembering whether the first parameter to %SCAN was the string I was searching, or the string I was searching for. For me this was resolved by an example from former RPG compiler team member, Hans Boldt. His version of the syntax was:

    %SCAN( needle : haystack ... )
    

    I’ve never had a problem remembering the sequence since!

    As we noted earlier, %SCAN is looking for a specific character string. That string can be a single character, or a group of characters. If it finds the requested string in the input (or should I say “haystack”), it returns the position of the first matching character. If it fails to find a match, it returns zero.

    When using %SCAN, don’t forget that you may need to take spaces into account. For example, when searching for the word “is”, you may need to specify it with both a leading and trailing space. If you don’t, then words such as “This” and “issue” will also give a positive response — and that may not be what you want.

    As I mentioned at the beginning of this tip, %SCAN was joined in the 7.3 release by the %SCANR BIF. As you might expect, %SCANR starts the scan with the last character position in the string. A great use for this capability is to extract the file name from a complete IFS path name by scanning backwards for the “/” that separates the file name from the rest of the path. In addition to adding the %SCANR version, IBM also included a fourth parameter in both versions of %SCANx that can be used to limit the length of the search. There are excellent examples of the BIF in action in the RPG manual here: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzasd/bbscanr.htm so I won’t duplicate that here.

    One last point on %SCANx. If you want to make your scan code as generic as possible, consider using a variable length field (i.e., one defined as VarChar or with the keyword VARYING) for the compare string. If you use a fixed-length string then it may contain trailing spaces which will mess up the comparison. You could avoid the problem by surrounding the comparison string with %TRIMR, but using a variable-length field is more efficient.

    The following brief sample demonstrates this:

           Dcl-s  fixedLengthTarget    Char(10);
           Dcl-s  varyingLengthTarget  VarChar(10);
    
           Dcl-s  source    Char(30);
           Dcl-s  position  Int(5);
    
           source = 'this is the test input string';
           Dsply ('Input string: ' + source );
    
           // Scan for fixed length target
          
          fixedLengthTarget = 'is';
          position = %Scan( fixedLengthTarget: source);
             // position value is zero due to trailing spaces in target
           Dsply ('Fixed target ' + fixedLengthTarget
                  + ' at position ' + %Char(position));
    
           position = %Scan( %TrimR(fixedLengthTarget): source);
             // position value is 3 as trailing spaces stripped off
           Dsply ('Trimmed target ' + fixedLengthTarget
                  + ' at posiiton ' + %Char(position));
    
    
           //  Scan for varying length target
    
           varyingLengthTarget = 'is';  // Length of target set to 2 (length of value)
           position = %Scan( varyingLengthTarget: source);
             // position value is 3
           Dsply ('Varying target '
                  + varyingLengthTarget +  ' at position ' + %Char(position));
    
           *InLr = *On;
    
    

    Before I close, I should just touch on the one parameter I haven’t mentioned, the start position, which is common to both of these BIFs and works in the same way. It determines the point at which the comparison is to begin. By default the start position is 1, except for %CHECKR, of course, where it is the last character in the input field. This parameter is most commonly used when calling the BIF in a loop, where you need to skip past any instances of the search string that have already been handled. I can’t recall ever using it with %CHECK, but I use it often with %SCAN.

    Hopefully this tip will further your understanding of their utility and help clear up some common misunderstandings.

    Jon Paris is one of the world’s foremost experts on programming on the IBM i platform. A frequent author, forum contributor, and speaker at User Groups and technical conferences around the world, he is also an IBM Champion and a partner at Partner400 and System i Developer. He hosts the RPG & DB2 Summit twice per year with partners Susan Gantner and Paul Tuohy.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guruclassic, BIF, built-in function, FHGC, Four Hundred Guru Classic, IBM i, RPG

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Guru Classic: Call Again And Again And Again . . . Guru Classic: Automatic Or Static Storage?

    Leave a Reply Cancel reply

TFH Volume: 29 Issue: 3

This Issue Sponsored By

  • RPG & DB2 Summit
  • RPG & DB2 Summit
  • RPG & DB2 Summit

Table of Contents

  • Guru Classic: Automatic Or Static Storage?
  • Guru Classic: A Bevy of BIFs – %SCAN and %CHECK
  • Guru Classic: Call Again And Again And Again . . .

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • POWERUp 2025 –Your Source For IBM i 7.6 Information
  • Maxava Consulting Services Does More Than HA/DR Project Management – A Lot More
  • Guru: Creating An SQL Stored Procedure That Returns A Result Set
  • As I See It: At Any Cost
  • IBM i PTF Guide, Volume 27, Number 19
  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle