Reputation: 49
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
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
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
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
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