Maxcc0
Maxcc0

Reputation: 49

Suppressing leading zeroes

We use a numeric-edited picture clause Z(4).99 to supress leading zeroes. It replaces leading zeros with spaces. My question here is, can we remove those spaces and display only the actual value without leading spaces?

I have ws-amount which is pic 9(09)v99. If I move 100 into it,it will look like 00000010000. But in my report I need it to be displayed like "LOAN AMOUNT $100.00".

Upvotes: 3

Views: 13256

Answers (4)

Kennah
Kennah

Reputation: 497

This uses part of my code here.

https://codereview.stackexchange.com/questions/69220/trim-functions-in-cobol

ws-amount                           pic 9(09)V99.
ws-formated-amount                  pic $$$$,$$$,$$9.99.
ws-output-message                   pic X(27).

MOVE ws-amount
  TO ws-formated-amount.
MOVE ws-formated-amount
  TO STR-VALUE-IN.
MOVE FUNCTION LENGTH (ws-formated-amount)
  TO STR-LENGTH-IN.
PERFORM 5100-LTRIM.
MOVE SPACES TO ws-output-message.
STRING
   'LOAN AMOUNT '
   STR-VALUE-OUT (1:STR-LENGTH-OUT)
       DELIMITED SIZE
INTO
   ws-output-message
END-STRING.

Upvotes: 1

Brian Tiffin
Brian Tiffin

Reputation: 4116

Here is a sample, "to spec", but it may not be "to vendor", depending on how old the compiler is, as gazzz0x2z pointed out. (FUNCTION TRIM was in the 1989 amendment, so 26 years later...) EDIT: Turns out, that's a mistake. As Bill pointed out, TRIM is only in the recent spec from 2014. I be dissin' where I shouldn't be dissin'. Leaving the comment in, and drooping head in shame.

   identification division.
   program-id. left-just.

   data division.
   working-storage section.
   01 amount      pic 9(9)v99 value 100.00.
   01 dollars     pic $(8)9.99.
   01 show-loan   pic x(32).

   procedure division.
   move amount to dollars
   string
       "LOAN AMOUNT " delimited by size
       function trim(dollars leading) delimited by size
     into show-loan
   display function trim(show-loan trailing)
   goback.
   end program left-just.

Upvotes: 3

Bill Woodger
Bill Woodger

Reputation: 13076

Since you seem to have concerns over what a reviewer may say, here's the code which actually does what you have asked for:

   UNSTRING edited-field
             DELIMITED BY ALL SPACE
                                INTO ignore-this
                                     no-leading-space-field

I'm not at all sure how that would be difficult to review. It does need these definitions:

01  edited-field                        PIC Z(10).99.
01  no-leading-space-field              PIC x(13).
01  ignore-this                         PIC X.

If you are talking of optimisation for performance, then you'd need to work on the code that gazzz0x2z provided in their answer. But then your reviewer will get all confused again with multiple lines of code.


COBOL verbs STRING and UNSTRING have been around since the 1974 COBOL Standard, so should be widely available. For manipulation of regular text they have many uses.

   IDENTIFICATION DIVISION.
   PROGRAM-ID. supspace.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01  unedited-field                      PIC 9(9)v99.
   01  edited-field                        PIC Z(10).99.
   01  no-leading-space-field              PIC x(13).
   01  output-text                         PIC x(80).
   01  text-intro                          PIC x(13) VALUE 
                                             "LOAN AMOUNT $".
   01  text-outro                          PIC x(12) VALUE 
                                             " TO PAY SOON".
   01  ignore-this                         PIC X.
   PROCEDURE DIVISION.
       MOVE 0.01                    TO unedited-field
       PERFORM                      the-work
       MOVE 123.01                  TO unedited-field
       PERFORM                      the-work
       MOVE ZERO                    TO unedited-field
       PERFORM                      the-work
       MOVE 123456789.01            TO unedited-field
       PERFORM                      the-work
       GOBACK
       .
   the-work.
       PERFORM                      left-justify-edit
       PERFORM                      assemble-output
       DISPLAY 
              output-text
       .
   left-justify-edit.
       MOVE unedited-field          TO edited-field
       UNSTRING edited-field
                 DELIMITED BY ALL SPACE
                                    INTO ignore-this
                                         no-leading-space-field
       .
   assemble-output.
       MOVE SPACE                   TO output-text
       STRING 
              text-intro
               DELIMITED BY SIZE
              no-leading-space-field
               DELIMITED BY SPACE
              text-outro
               DELIMITED BY SIZE
                                    INTO output-text
       .

Output is:

LOAN AMOUNT $.01 TO PAY SOON
LOAN AMOUNT $123.01 TO PAY SOON
LOAN AMOUNT $.00 TO PAY SOON
LOAN AMOUNT $123456789.01 TO PAY SOON

Note that edited-field is define one byte longer than otherwise necessary, Z(10) instead of Z(9). This is to ensure that there is always at least one leading space for the DELIMITED of the UNSTRING.

Note that STRING does not space-pad its target field when the resultant value is less than the size of the target, so if the resultant value can be variable in length, clear the target field before the using the STRING verb.

UNSTRING uses specified delimiters to split a single field into multiple fields.

The key to how it works is the field ignore-this and the DELIMITED BY ALL SPACE, and the guaranteed presence of at least one leading space.

ALL SPACE is any number of spaces from one to the size of the field it is being applied to. Any delimiter named in UNSTRING is not included in the INTO fields. The presence of a leading delimiter means that the first INTO field will "contain" a zero-length piece of data, space-padded to the length of that first INTO field. The second INTO field will contain the data with no leading spaces, and will be space-padded to the length of that field.

STRING takes multiple fields, which can be delimited by data within them, and puts them together to make one piece of data which is placed in the INTO field, with truncation if necessary, but without space-padding if the data is shorter than the INTO field.

In the STRING as used here, only SPACE is a delimiter, rather than ALL SPACE, as a single space is sufficient to delimit and the code will be faster than using ALL SPACE.

Upvotes: 3

gazzz0x2z
gazzz0x2z

Reputation: 326

Didn't use any functions, as those are site-dependant.

So the result is quite a monster(and I won't spend more time refining it) :

   01  WS.
       05  W-AMOUNT                    PIC 9(09)v99.
       05  W-AMOUNT-ALPHA              REDEFINES W-AMOUNT
                                       PIC X(01) OCCURS 11.
       05  W-DISPLAY                   PIC X(25).
       05  W-DISPLAY-TAB               REDEFINES W-DISPLAY
                                       PIC X(01) OCCURS 25.
       05  W-SENTENCE                  PIC X(12)
                                       VALUE " TO PAY SOON".
       05  W-SENTENCE-TAB              REDEFINES W-SENTENCE
                                       PIC X(01) OCCURS 12.
       05  W-SENTENCE-LENGTH           PIC 9(04) COMP-5.
       05  W-POSITION-AMOUNT           PIC 9(04) COMP-5.
       05  W-POSITION-SENTENCE         PIC 9(04) COMP-5.
       05  W-POSITION-DISPLAY          PIC 9(04) COMP-5.
       05  W-LEADING-ZEROES            PIC X(01).
           88  STILL-LEADING-ZEROES    VALUE "Y".
           88  NO-MORE-LEADING-ZEROES  VALUE "N".

followed by :

   PROCEDURE DIVISION.
  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
   CONTROL-PROCEDURE.
  **
  * The main procedure of the program
  **
       MOVE 15314.16 TO  W-AMOUNT
       PERFORM SUB-PROCEDURE
       DISPLAY  "LOAN AMOUNT $"
       W-DISPLAY
       MOVE 314.16 TO  W-AMOUNT
       PERFORM SUB-PROCEDURE
       DISPLAY  "LOAN AMOUNT $" W-DISPLAY
       GOBACK
       .
   SUB-PROCEDURE.
       MOVE ZERO   TO  W-POSITION-DISPLAY
                       W-POSITION-SENTENCE
       MOVE SPACES TO  W-DISPLAY
       SET STILL-LEADING-ZEROES TO TRUE
       PERFORM VARYING     W-POSITION-AMOUNT
               FROM        1 BY 1
               UNTIL       W-POSITION-AMOUNT > 9
           IF (W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
              NOT EQUAL ZERO) THEN 
              SET NO-MORE-LEADING-ZEROES TO TRUE
           END-IF
           IF NO-MORE-LEADING-ZEROES THEN 
               ADD 1 TO W-POSITION-DISPLAY
               MOVE W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
                 TO W-DISPLAY-TAB  (W-POSITION-DISPLAY)
           END-IF
       END-PERFORM
       ADD 1 TO    W-POSITION-DISPLAY
       MOVE "." TO W-DISPLAY-TAB (W-POSITION-DISPLAY)
       ADD 1 TO    W-POSITION-DISPLAY
       MOVE        W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
         TO        W-DISPLAY-TAB  (W-POSITION-DISPLAY)
       ADD 1 TO    W-POSITION-DISPLAY
                   W-POSITION-AMOUNT
       MOVE        W-AMOUNT-ALPHA (W-POSITION-AMOUNT)
         TO        W-DISPLAY-TAB  (W-POSITION-DISPLAY)
       MOVE LENGTH OF W-SENTENCE TO W-SENTENCE-LENGTH
       PERFORM W-SENTENCE-LENGTH TIMES
           ADD  1  TO  W-POSITION-DISPLAY
                       W-POSITION-SENTENCE
           MOVE W-SENTENCE-TAB     (W-POSITION-SENTENCE)
             TO W-DISPLAY-TAB      (W-POSITION-DISPLAY)
       END-PERFORM
       .

final result :

LOAN AMOUNT $15314.16 TO PAY SOON     
LOAN AMOUNT $314.16 TO PAY SOON  

There are plenty of ways optimizing it(especially the way I'm handling digits behind the dot, it's absolutely awful, but I'm doing it while watching other things, so I went to simpler things). I would not dare submitting that to code review. But it works.

Upvotes: 3

Related Questions