ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Auto-trim trailing blanks on variable size field?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Auto-trim trailing blanks on variable size field?

    Hello,

    I build an IFS path for a CPYTOIMPF command in my program and I was wondering if there was a way to do this through a datastructure? The issue here being that one of the field has a varying length of data, it could be 4 or it could be 11 characters

    Here's a simple example, to demonstrate what I'm trying to do;

    Code:
    D #IFS            Ds                                                     
    D  #IFSPath                                                              
    D   #IFSDir                     15a   OVERLAY(#IFSPATH)                  
    D                                     INZ('/ifs/directory/')             
    D   #Client                     11a   OVERLAY(#IFSPATH:*NEXT)            
    D   #Space                       1a   OVERLAY(#IFSPATH:*NEXT) INZ(' ')   
    D   #Date                        7a   OVERLAY(#IFSPATH:*NEXT)            
    D                                     INZ('03-2018')                     
    D   #Ext                         4a   OVERLAY(#IFSPATH:*NEXT) INZ('.CSV')
    
         #Client = 'Client';                                                 
    
         Dsply #IFS;                                                         
    
         *INLR = *ON;
    So during processing, the client name will be read from a field in a file and set - the issue being it could be 4 characters or 11.

    Naturally, because I've defined it as 11 long, when the field is referenced it has trailing blanks;

    Code:
    DSPLY  /ifs/directory/Client      03-2018.CSV
    Is there any special way to define #Client so that the blanks are auto-trimmed?

    I tried the "Varying" keyword but this gave a weird result and from reading about it, I think it's how it is stored rather than displayed;

    Code:
    DSPLY  /ifs/directory/ ■Client      03-2018.CSV
    That square shows as a ? on the iSeries display.

    Thanks in advance,
    Ryan

  • #2
    I'm afraid not, not with a data structure. The whole point of a data structure is its subfields are at specific fixed positions within the structure.
    I.e.

    #IFSDir starts at position 1
    #Client starts at position 16 (#IFSDIR start pos 1 + length 15)
    #Space starts at position 27 (#Client start pos 16 + length 11)
    etc.

    Data structures are used to build strings from sub components, where the start position and length of each sub component is fixed and constant. So it won't work for what you want.

    You will have to use regular string manipulation:

    Code:
    D #IFS            S             40A                                      
    D #IFSDir         S             15a   INZ('/ifs/directory/')             
    D #Client         S             11a              
    D #Space          S              1a   INZ(' ')   
    D #Date           S              7a   INZ('03-2018')                     
    D #Ext            S              4a   OVERLAY(#IFSPATH:*NEXT) INZ('.CSV')
    
         #Client = 'Client';   
    
         #IFS = %trim(#IFSDir) + %trim(#Client) + ' ' 
              + %trim(#Date) + %trim(#Ext);                                             
    
         Dsply #IFS;                                                         
    
         *INLR = *ON;

    Comment


    • JonBoy
      JonBoy commented
      Editing a comment
      I'd personally avoid the constant use of %Trim (and %TrimR is all you need it is also more obvious in intent and faster) and define the base items as varchar too. So it would be:

      dcl-s #IFSDir Varchar(50) Inz('/ifs/directory/');
      dcl-s #Client Varchar(11);
      dcl-d #Date Char(7) Inz('03-2018')

      #IFS = #IFSDir + #Client + ' ' + #Date + '.csv';

  • #3
    Thanks for the info, was trying to get fancy but failed drastically... Haha.

    I'll try the VARCHAR definitions out.

    Comment


    • #4
      Note about using varchar - it can hold strings of varying length, but that is not the same thing as auto trimming trailing blanks.
      If you put a string literal that contains trailing blanks or a non-var char with trailing blanks into a varchar, you will get trailing blanks.

      Example:
      Code:
      dcl-s userId  char(10);
      dcl-s userIdVar  varchar(10);
      
      
      userIdVar = 'BOB';  // userIdVar is length 3, contains 'BOB'
      
      userId = 'BOB';       
      userIdVar = userId;  // userIdVar is length 10, contains 'BOB       ' (BOB + 7 trailing blanks) because iserId did.
      
      userIdVar = %trimr(userId);  // userIdVar is length 3, contains 'BOB'

      Comment


      • #5
        Ah right, then varchar isn't for me here - "client" will come from a config file that holds the value in a 11 char field.

        I'll just keep it simple with the %trimxx bifs, thanks again Vector!

        Comment


        • #6
          I'd stick with the string manipulation and using the %TRIM. (I rarely use the %TRIMR). However if you're building on a string - like building the path incrementally I'd declare the variable as VARCHAR and use the %TRIM against the variables you're adding to it.

          One argued using the VARCHAR rather than the %TRIMR because it's faster... while technically true the difference is so minute you'd have to do millions of them before you could effectively measure the difference. I did a test with 5 MILLION iterations - 1 with varchar, the other with %TRIMR... they both took 3 seconds. I wouldn't put performance difference in the consideration. Clarity of code and functionality should be the criteria.

          Comment


          • #7
            I just did 50 MILLION iterations - 2 second difference after 50,000,000 iterations.... It's funny sometimes what hoops we put ourselves through to make code more efficient...

            Comment


            • #8
              I stand corrected - I had an invalid test in my program.... after 50,000,000 iterations with %TRIMR it took 27 seconds, using VARCHAR took 3 seconds - but this is over 50,000,000 iterations. Percentage wise there's a huge difference - in the big scheme of things pretty insignificant - unless you're doing like 30 assignments for every record and there are 150 million records...

              Comment


              • #9
                If there are blanks on the string that don't belong there, use %TRIM (or %TRIMR, %TRIML) to remove them. No problem with doing that...

                The problem that I keep seeing is people adding the blanks, then trimming them off again, because typing "varchar" instead of "char" is somehow seen as "difficult". Really, this is just a stubbornness, unwilling to change something from the way you did it 30 years ago, because using varchar isn't any harder, and in most programming languages is in fact the only choice (RPG, CL, Cobol have fixed length character strings... but I don't know of any other language anywhere that does.)

                So nothing wrong with %TRIM -- just only use it when it's necessary! There's no value added to your program by adding tons of blanks and then immediately trimming them off again. Sure, the performance difference won't matter unless you do it lots of times -- but why do it if its unnecessary and provides no value?

                Comment

                Working...
                X