• 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 — %CHAR, %EDITC and %EDITW

    February 13, 2019 Jon Paris

    Author’s Note: The reason I chose this particular tip to revisit was that a similar question came up on one of the RPG web forums the other day. The questioner was looking for an easy way to edit a numeric field to include the use of colons as separators. Because the answer involves the use of %EditW I have added a simple example of its use at the end of this tip.

    “I need to convert a numeric value into a character string. How do I . . . ?” This question is often asked by RPGers as they face having to produce CSV files, XML and JSON documents, or Web pages (HTML). Generating such data has become a common requirement in the lives of many RPGers.

    I’ll start by taking a quick look at one of my most frequently used built-in functions: %Char. Originally introduced to handle conversion of date fields to a character form, %Char was quickly upgraded for use with numeric fields and expressions. But the way in which it operates catches many programmers by surprise. Why? Because %Char performs leading zero suppression and then trims the resulting string to remove leading and trailing blanks. As a result, the length of the resulting string varies depending on the value in the field being converted. As we will see later, this is very different from %EDITC (and its companion %EDITW), which will always produce a consistent-length output from a given input field definition and edit code combination, regardless of the actual content of the field.

    As a result, when you run the code below, the first DSPLY message (A) will say “%Char value is (12.34)” and the second (B) “%Char value is (10012.34)”. When you are building text such as that used in the message here, this is a good thing. It saves you having to worry about stripping the blanks etc. It will even place a minus sign in front of negative numbers and, as you can see, will insert a decimal point when the expression contains decimal places. Very useful.

    But what if you want to simply convert a numeric value to its character equivalent? For example, to replace an old-fashioned MOVE operation. If you try to use %Char for that purpose you will be disappointed for many reasons. For one you may find an unwanted decimal point inserted as in our examples, and for another, because you’ll either end up with trailing spaces in the output field (C) “Value of 12.34 results in (12.34  )”, or worse still, truncation of the decimal places (D) “Value of 10012.34 results in (10012.3)” and that’s probably not what you expect, or indeed want.

           Dcl-s  testNum   packed(7:2)  inz(12.34);
           Dcl-s  testChar  char(7);
           Dcl-s  phoneNum  packed(11)  inz(2535551234);
    
           // Effect of %Char when building a string
           Dsply ('Showing effect of %Char in string build');
    (A)    Dsply ('%Char value is (' + %Char(testNum) + ')');
           testNum += 10000;
    (B)    Dsply ('%Char value is (' + %Char(testNum) + ')');
           testNum = 12.34; // Reset to original value
    
           // Attempt to use %Char() as equivalent to MOVE
           Dsply ('Showing effect of %Char as replacement for MOVE');
           testChar = %Char(testNum);
    (C)    Dsply  ('Value of ' + %Char(testNum)
                    + ' results in (' + testChar + ')');
           testNum += 10000;
           testChar = %Char(testNum);
    (D)    Dsply  ('Value of ' + %Char(testNum)
                    + ' results in (' + testChar + ')');
           testNum = 12.34; // Reset to original value
    

    Replacing the MOVE Operation

    So how do you handle the requirement to replace a MOVE operation? The answer is %EditC. %EditC applies an edit code to a numeric field just as it would if you used that code on an O-spec or in a DDS definition. It then returns you the edited character string. So what’s the magic code that allows us to insert leading zeros and not have to worry about decimal place insertion etc? ‘X’ marks the spot! The X edit code will retain leading zeros, and will not insert a decimal point, comma, or anything else. The result is that our test program will output (E) “Value of 12.34 results in (0001234)” and (F) “Value of 10012.34 results in (1001234)”. Note that the length of the display string is identical in each case. Any negative values will be indicated by an alpha character in the right-most position of the field just as they would have been with a MOVE.

    We won’t go into details of all of the edit code options available. As we noted earlier they are identical to those used on O-specs and in DDS. Having said that, there is one difference between the way certain editing requirements are specified with %EditC relative to O-specs. If you require the resulting string to have leading zeros replaced by asterisks, then the keyword *ASTFILL should be specified as the third parameter to %EditC. Similarly, if you want a floating currency sign to be added to the field, you can specify *CURSYM for the default value, or enter a single character of your own choosing to have that act as the floating currency symbol.

    Using %EditW for Even More Options

    Just as with %EditC, the format of the edit words used by %EditW is exactly the same as on O-specs and DDS. To round out this tip, I have added a couple of examples of using %EditW, one of which is similar to the requirements of the original questioner to insert colon separators into a numeric field.

    The first example (G) applies the edit word ‘0(bbb)&bbb-bbbb’ (where the letter “b” represents a blank) to a numeric field intended to represent a phone number. The resulting display looks like this: “Edited 2535551234 as phone number: (253) 555-1234”. This demonstrates a slightly annoying feature of edit words in that the field has to be specified as one digit longer than we really need it to be (11 digits and not 10) in order that we can specify a “0” (zero) in the string ahead of the “(“. The rule is that there has to be a digit from the field ahead of the first insertion character. Annoying but there it is.

    The second example (H) simply breaks the number up into pairs of digits separated by colons using the edit word ‘b0b:bb:bb:bb:bb’ resulting in the display “Simple colon insertion results in: 25:35:55:12:34”.

           // Now use %EditC as substitute for MOVE
           Dsply ('Showing effect of %EditC as replacement for MOVE');
           testChar = %EditC(testNum: 'X');
    (E)    Dsply  ('Value of ' + %Char(testNum)
                    + ' results in (' + testChar + ')');
           testNum += 10000;
           testChar = %EditC(testNum: 'X');
    (F)    Dsply  ('Value of ' + %Char(testNum)
                    + ' results in (' + testChar + ')');
    
           // Simple examples of %EditW        
           Dsply ('Showing effect of using %EditW');
    (G)    Dsply ('Edited ' + %Char(phoneNum) + ' as phone number:'
                   + %EditW(phoneNum: '0(   )&   -    ') );
    (H)    Dsply ('Simple colon insertion results in:'
                   + %EditW(phoneNum: ' 0 :  :  :  :  ') );
    
           *InLR = *On;
    

    As you can see, there’s a lot you can do with these BIFs. If you have been using O-specs or other techniques to format this kind of data, perhaps it is time to revise your coding techniques.

    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: BIF, FHGC, Four Hundred Guru Classic, IBM i

    Sponsored by
    Midrange Dynamics North America

    With MDRapid, you can drastically reduce application downtime from hours to minutes. Deploying database changes quickly, even for multi-million and multi-billion record files, MDRapid is easy to integrate into day-to-day operations, allowing change and innovation to be continuous while reducing major business risks.

    Learn more.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Settling In With IBM i For The Long Haul Guru Classic: Who Needs Custom Perspectives In RDi?

    Leave a Reply Cancel reply

TFH Volume: 29 Issue: 10

This Issue Sponsored By

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

Table of Contents

  • Guru Classic: Triggers – Allow Repeated Change
  • Guru Classic: Who Needs Custom Perspectives In RDi?
  • Guru Classic: A Bevy of BIFs — %CHAR, %EDITC and %EDITW

Content archive

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

Recent Posts

  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24
  • Big Blue Raises IBM i License Transfer Fees, Other Prices
  • Keep The IBM i Youth Movement Going With More Training, Better Tools
  • Remain Begins Migrating DevOps Tools To VS Code
  • IBM Readies LTO-10 Tape Drives And Libraries
  • IBM i PTF Guide, Volume 27, Number 23

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