Guru: Unlocking The Power Of %CONCAT And %CONCATARR In RPG
April 14, 2025 Gregory Simmons
When working with strings in RPG, especially in modern free-format code, the %CONCAT and %CONCATARR built-in functions (BIFs) offer efficient and readable solutions for combining strings. These functions simplify the process of concatenating multiple string values, making your code cleaner and easier to maintain. In this article, we will explore how they work and demonstrate their practical applications.
The %CONCAT BIF allows you to combine multiple strings. It’s a more efficient and readable alternative to traditional concatenation using the + operator.
Here’s a simple example:
**Free Ctl-Opt Main(CONCAT_1) ActGrp(*Caller); Dcl-Pr pause ExtProc('sleep'); time_to_sleep Uns(10) Value; End-Pr; Dcl-Proc CONCAT_1; Dcl-S firstName Char(20) Inz('John'); Dcl-S lastName Char(20) Inz('Doe'); Dcl-S fullName Char(50); fullName = %CONCAT(‘ ‘:firstName:lastName); SND-MSG *STATUS fullName %TARGET(*EXT); // Output:John Doe pause(3); End-Proc CONCAT_1;
In this example, %Concat combines firstName, a space, and lastName into a single fullName variable. It’s clean and eliminates the need for multiple concatenation operators. Compiling and running this program will output this to the bottom of your screen and wait for 10 seconds before continuing execution:
‘John Doe’
On a side note, have you played with the Snd-Msg operator yet? I find that I like it better than Dsply. When I use the Snd-Msg, combined with the *Status and %Target(*EXT) parameters, it’s just nicer to have the message(s) show up under my command line instead of flashing really quick and then I have to display the joblog to see the output. Yes, you can make the Dsply operation ‘pause’ but then you have to press enter to continue processing; I just like the flow afforded by the Snd-Msg operation better. If you haven’t already, I recommend you give it a try.
Okay, back to the previous example. The output is a bit ugly because the variables are 20 characters long and the value I initialized them to are only four and three long, respectively. There are a couple ways to make this nicer. One practical usage of this would be to combine the above example with the %Trim BIF. Like this:
fullName = %Concat(‘ ‘:%Trim(firstName):%Trim(lastName)); SND-MSG *STATUS fullName %TARGET(*EXT); // Output:John Doe
Much nicer!
Another, perhaps even nicer way to clean that output up is to simple change the declaration of the firstName and lastName standalone variables from Char(20) to VarChar(20). I prefer working with VarChar, but both tactics will have the desired result.
The %CONCATARR BIF is particularly useful when you need to concatenate elements from an array. It simplifies scenarios where you would otherwise loop through an array to combine values.
**Free Ctl-Opt Main(CONCAT_2) Ctl-Opt ActGrp(*Caller); Dcl-Pr pause ExtProc('sleep'); time_to_sleep Uns(10) Value; End-Pr; Dcl-Proc CONCAT_2; Dcl-S names VarChar(20) Dim(4) Inz(*Blanks); Dcl-S nameList VarChar(100); names(1) = 'Alice'; names(2) = 'Bob'; names(3) = 'Charlie'; names(4) = 'David'; nameList = %Concatarr(', ':names); SND-MSG *STATUS nameList %TARGET(*EXT); // Output:Alice, Bob, Charlie, David pause(3); End-Proc CONCAT_2;
In the above example, note that for the first parameter for %CONCATARR, I passed a comma and then one blank space. This keeps the output string a nicely formatted list of names. However, as with many, if not all BIFs in RPG, that parameter could be any expression you needed; providing the result of your expression is a string.
It is also important to note that in my example, to keep it simple, the ‘names’ array only has Dim(4) or 4 elements. This is not a practical real-world example. If, for example, I changed the array to Dim(1000), and re-ran the program, the output would be ‘Alice, Bob, Charlie, David’ followed by 996 repetitions of ‘, ‘. I can change the %CONCATARR statement to only consider the elements in the array which are not blank, using this approach:
nameList = %ConcatArr(', ':%SubArr(names:1:%Lookup(' ':names:1)-1));
This new version, with the addition of the %SUBARR and %LOOKUP BIFs, instructs the %CONCATARR BIF to only use the portion of the array which contain non-blank values. Perhaps a nicer way to solve the issue of excessive comma-space at the end of your resulting string would be to change the definition of your array:
**Free Ctl-Opt Main(CONCAT_3) ActGrp(*Caller); Dcl-Pr pause ExtProc('sleep'); time_to_sleep Uns(10) Value; End-Pr; Dcl-Proc CONCAT_3; Dcl-S names VarChar(20) Dim(*Auto:10); Dcl-S nameList VarChar(100); names(1) = 'Alice'; names(2) = 'Bob'; names(3) = 'Charlie'; names(4) = 'David'; nameList = %Concatarr(', ':names); SND-MSG *STATUS nameList %TARGET(*EXT); //Output:Alice, Bob, Charlie, David pause(3); End-Proc CONCAT_3;
The previous two examples have the same output, but I believe the second example reads more nicely.
One final note – All of my examples above demonstrate using %CONCAT and %CONCATARR to combine strings together, with something to act as a spacer between the strings. But if you have a need to combine the strings together without a spacer, both BIFs support *NONE as their first parameter.
Using %CONCAT and %CONCATARR in RPG can greatly enhance your string manipulation capabilities. They not only make your code cleaner and more readable but also reduce potential errors caused by manual concatenation.
Until next time, happy (assisted) coding.
Gregory Simmons is a Project Manager with PC Richard & Son. He started on the IBM i platform in 1994, graduated with a degree in Computer Information Systems in 1997 and has been working on the OS/400 and IBM i platform ever since. He has been a registered instructor with the IBM Academic Initiative since 2007, an IBM Champion and holds a COMMON Application Developer certification. When he’s not trying to figure out how to speed up legacy programs, he enjoys speaking at technical conferences, running, backpacking, hunting, and fishing.
RELATED STORIES
Guru: AI Pair Programming In RPG With Continue
Guru: AI Pair Programming In RPG With GitHub Copilot
Guru: RPG Receives Enumerator Operator
Guru: RPG Select Operation Gets Some Sweet Upgrades
Guru: Growing A More Productive Team With Procedure Driven RPG
Guru: With Procedure Driven RPG, Be Precise With Options(*Exact)
Guru: Testing URLs With HTTP_GET_VERBOSE
Guru: Fooling Around With SQL And RPG
Guru: Procedure Driven RPG And Adopting The Pillars Of Object-Oriented Programming
Guru: Getting Started With The Code 4 i Extension Within VS Code
Guru: Procedure Driven RPG Means Keeping Your Variables Local
Guru: Procedure Driven RPG With Linear-Main Programs
Guru: Speeding Up RPG By Reducing I/O Operations, Part 2
Guru: Speeding Up RPG By Reducing I/O Operations, Part 1
Guru: Watch Out For This Pitfall When Working With Integer Columns