can i use replacing clause and let below codes
base on IBM cobol
fieldcpy:
01 field-define
03 :aaa:-field-1
03 :aaa:-field-2
i'd like to remove the prefix of :aaa:- and have this:
01 field-define
03 field-1
03 field-2
i tried below statement but it does work:
copy fieldcopy
replacing ==:aaa:-== with " ".
it seems i have 2 problems:
replacing clause does not identify the "-" of :aaa:-
by clause does not accept null value or space value
similar question i found :
http://computer-programming-forum.com/48-cobol/2cd93fd177e39127.htm
but the advise of below does work.
COPY SBKACDET REPLACING ==(PR)-== BY ==''==.
I think what you really wanted was something like this: (syntax is from memory, I hope I got it right):
01 :aaa:-define.
03 :aaa:-1 pic x(1).
03 :aaa:-2 pic x(1).
Then copy it like this:
copy "FILENAME"
replacing ==:aaa:== with ==field==.
copy "FILENAME"
replacing ==:aaa:== with ==second==.
To get this:
01 field-define.
03 field-1 pic x(1).
03 field-2 pic x(1).
01 second-define.
03 second-1 pic x(1).
03 second-2 pic x(1).
Answer: According to IBM docs it should work. But you need to use correct syntax that replaces partial-words:
copy fieldcopy
replacing leading ==:aaa:-== by == ==.
Related
I have some IBM COBOL of 2006 vintage. It contains "$CICS ON" and "$CICS OFF". I'm generally familiar with IBM COBOL "EXEC CICS" statements and directives, but I've never seen this pair.
What do these commands do, and where are they documented (IBM reference manual name would be ideal answer)? Searching the web didn't show an obvious result.
COBOL program fragment below:
000750 01 WG-YOB.
000760 05 FILLER PIC X(4).
000770 05 WX-YOB PIC X(2).
000780$CICS ON.
000790$CICS OFF.
000800$COPY CMPLDBF.
000810$COPY CMPLDBH.
000820 LINKAGE SECTION.
000830 01 DFHCOMMAREA.
000840 COPY COMMAREA.
000850 PROCEDURE DIVISION.
EDIT: This is a code base of about 1000 programs ~~ 450K SLOC. The only $ commands I find across this entire code base are:
$CICS ON.
$CICS OFF.
$COPY <filename>.
$BLOCK.
$BlOCKS.
If it helps, the copy libs referenced by $COPY contain nonstandard COBOL declarations (note "COMMBLOCK" and "FORM" starting in column 7)
000100COMMBLOCK OF HCPDSDB.
000110 01 HCPDSDB-DB.
000120 05 RECORD-NAME.
000130 05 RETURN-KODE.
000140 05 FREE.
000150 05 LAST-RECORD-FLAG.
000160 05 PASSWD.
000170 05 NO-OF-RECORDS.
...
000380FORM YYMMDD.
000390 05 C4-RED REDEFINES C4.
000400 07 C4-YY PIC 99.
000410 07 C4-MM PIC 99.
000420 07 C4-DD PIC 99.
000430 05 C5 PIC 9(11).
000440 05 C6 PIC 9(6).
Converting comment to an answer at OP request.
May be System 2000 references. V1 PDF from 20+ years ago includes $CICS ON and $CICS OFF directives. I cannot locate any V2 documentation that includes these directives.
From comments, OP found a more helpful manual at https://support.sas.com/resources/papers/proceedings/pdfs/s2k/PLEX.pdf which "appears to contain all the $xxxx directives mentioned" in the question.
I'm glad I was able to at least point in a helpful direction.
Looking to replace the beginning letters of this copybook from "O-" to "IT-". Would anyone know how to do this.
FD INPUT-TRANSACTION-FILE
RECORDING MODE IS F.
01 ITRANS-RECORD.
05 O-ACCOUNT-ID PIC X(6).
05 O-FIRST-NAME PIC X(15).
05 O-SURNAME PIC X(20).
05 O-SALARY PIC 9(6)V99.
05 O-TEMP REDEFINES O-SALARY PIC X(7).
When I call the copybook in my program I want to replace the "O" to "IT". I believe you can use REPLACING but I cannot seem to get it to work
It depends on the compiler in use (which you did not specify) but "in COBOL" you have a LEADING phrase for the REPLACING clause:
COPY FDITF REPLACING LEADING ==O-== BY ==IT-==.
It seems like you are building the copy inside your program.
In that case, you can call them whatever you like, so just change them from 'O' to 'IT' manually.
If the copy (say we call it 'ITRANS') is outside the program,
you need to add to the copy a colon (:) before and after the letters to change:
FD INPUT-TRANSACTION-FILE
RECORDING MODE IS F.
01 ITRANS-RECORD.
COPY 'ITRANS' REPLACING ==:O:== BY ==IT==.
Where the file copy 'ITRANS' is in the copy library.
05 :O:-ACCOUNT-ID PIC X(6).
05 :O:-FIRST-NAME PIC X(15).
05 :O:-SURNAME PIC X(20).
05 :O:-SALARY PIC 9(6)V99.
05 :O:-TEMP REDEFINES :O:-SALARY PIC X(7).
IBM DOC - COPY statement
I have a very simple COBOL code here that has a given input data and output data. The problem is that, it shows an error on line 60 which is the MOVE STUD-AGE TO AGE-OUT. and everytime I run OpenCOBOLIDE, I always get and error which is:
libcob: test.cob: 60: 'STUD-AGE' not numeric: ' '
WARNING - Implicit CLOSE of STUDENT-OUT ('C:\STUD-OUT.DAT')
WARNING - Implicit CLOSE of STUDENT-IN ('C:\STUD-IN.DAT')
And I don't know exactly what's wrong with it. Here is supposedly the input file I created:
----5---10---15---20---25---30---35---40--
00-123345 ALISON MARTIN WOLF 1912056
00-789012 KEN DENNIOS ROME 1914156
00-345678 JACK ADRIAN TOCKSIN 1622234
00-901234 EJHAYZ ALONEY 2045645
00-567890 CHARLES JOHN GUINNIVER 1813243
00-123457 JEAN MICHAEL YARTER 2034253
Here's the code to it:
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STUDENT-IN ASSIGN TO "C:\STUD-IN.DAT".
SELECT STUDENT-OUT ASSIGN TO "C:\STUD-OUT.DAT".
DATA DIVISION.
FILE SECTION.
FD STUDENT-IN.
01 STUD-REC.
02 STUD-NO PIC X(10).
02 STUD-NAME PIC X(25).
02 STUD-AGE PIC 99.
02 STUD-ALLOWANCE PIC 999V99.
FD STUDENT-OUT.
01 PRINT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 HDG-1.
02 FILLER PIC X(20) VALUE SPACES.
02 FILLER PIC X(22) VALUE "WILLOW PARK UNIVERSITY".
02 FILLER PIC X(14) VALUE " OF MADAGASCAR".
01 HDG-2.
02 FILLER PIC X(9) VALUE SPACES.
02 FILLER PIC X(14) VALUE "STUDENT NUMBER".
02 FILLER PIC X(8) VALUE SPACES.
02 FILLER PIC X(12) VALUE "STUDENT NAME".
02 FILLER PIC X(15) VALUE SPACES.
02 FILLER PIC X(3) VALUE "AGE".
02 FILLER PIC X(8) VALUE SPACES.
02 FILLER PIC X(9) VALUE "ALLOWANCE".
01 PRINT-LINE.
02 FILLER PIC X(9) VALUE SPACES.
02 SNO-OUT PIC X(10).
02 FILLER PIC X(12) VALUE SPACES.
02 SNAME-OUT PIC X(25).
02 FILLER PIC X(2) VALUE SPACE.
02 AGE-OUT PIC Z9.
02 FILLER PIC X(9) VALUE SPACES.
02 ALL-OUT PIC ZZZ.99.
01 E-O-F PIC XXX VALUE "NO".
PROCEDURE DIVISION.
OPEN INPUT STUDENT-IN
OUTPUT STUDENT-OUT.
WRITE PRINT-REC FROM HDG-1 BEFORE 1 LINE.
WRITE PRINT-REC FROM HDG-2 AFTER 2 LINES.
MOVE SPACES TO PRINT-REC.
WRITE PRINT-REC AFTER 1 LINE.
PERFORM READ-RTN UNTIL E-O-F = "YES".
PERFORM CLOSE-RTN.
READ-RTN.
READ STUDENT-IN AT END MOVE "YES" TO E-O-F.
MOVE STUD-NO TO SNO-OUT.
MOVE STUD-NAME TO SNAME-OUT.
MOVE STUD-AGE TO AGE-OUT.
MOVE STUD-ALLOWANCE TO ALL-OUT.
WRITE PRINT-REC FROM PRINT-LINE AFTER 1 LINE.
CLOSE-RTN.
CLOSE STUDENT-IN, STUDENT-OUT.
STOP RUN.
What I want to achieve is just to output the file correctly but the error only inputs the HDG-1 and then the rest blank.
To answer your question: COBOL accept numeric data however you define it.
So for "text data" (as long as it isn't UTF-16 or another multibyte encoded file) PIC 99 (which says "two digits in the default USAGE DISPLAY - so one byte per digit) is perfectly fine.
As with every other language: "never trust input data" is something I can recommend. For example: someone could run this program with a file that was saved with an UTF-8 encoded character in the name and then it "looks" right but the code has an unexpected shift in its data. For COBOL things like FUNCTION TEST-NUMVAL(inp) [ignores spaces and allows decimal-point] or IS NUMERIC (strict class test) can be useful.
Using data-check you could for example also skip empty lines or leading/trailing extra data (temporary rulers, headline, summary, ...).
For the actual problem:
It looks like you feed the program with a "common" text file, but you actually did not specify this so your COBOL implementation uses the default SEQUENTIAL. Because of the missing check of the input data you did not spot this directly.
To align expectations and code:
SELECT STUDENT-IN ASSIGN TO "C:\STUD-IN.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT STUDENT-OUT ASSIGN TO "C:\STUD-OUT.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
I am a newbie of COBOL, I am facing the following problem.
I have a input file with content:
2 3 2 4
4 numbers are in the same row and separated with exactly one space.
the 4 numbers can be in 1 digit, 2 digit and 3 digit
Can I put those 4 numbers to 4 variables with PIC?
such as: PIC XXX XXX XXX XXX (This is not working.)
currently I am using substring to achieve the task, but this is not efficient and messy, is there any other way i can finish the task easily?
Thanks
You can do this by two ways. Number one is to use unstring sentence. Or you can declare a variable level 01 and define in it every variable of the string separately.
For example:
01 WS-FILE.
05 WS-FIELD-01 PIC 9.
05 FILLER PIC X.
05 WS-FIELD-02 PIC 9.
05 FILLER PIC X.
05 WS-FIELD-03 PIC 9.
05 FILLER PIC X.
05 WS-FIELD-04 PIC 9.
05 FILLER PIC X.
And when you read the file use:
READ FILE INTO WS-FILE.
You can use an UNSTRING function (i dont know if you refer to that with substring)
UNSTRING WS-FILE-RECORD DELIMITED BY SPACE
INTO WS-FIELD1
WS-FIELD2
WS-FIELD3
WS-FIELD4
END-UNSTRING
with this if you have:
WS-FILE-RECORD="1 2 3 4"
WS-FIELD1 = "1"
WS-FIELD2 = "2"
WS-FIELD3 = "3"
WS-FIELD4 = "4"
or if you have:
WS-FILE-RECORD="1 22 333 4444"
WS-FIELD1 = "1"
WS-FIELD2 = "22"
WS-FIELD3 = "333"
WS-FIELD4 = "4444"
01 YOUR-NUMBERS.
03 YOUR-NUMBER PIC 9(04) OCCURS 4.
01 INDEX-YOUR-NUMBERS PIC 9(01).
01 YOUR-RECORD.
03 YOUR-RECORD-4.
05 YOUR-RECORD-4-NUM PIC X(04).
05 FILLER PIC X(01).
05 YOUR-RECORD-4-REST.
07 FILLER PIC X(09).
07 YOUR-RECORD-4-END PIC X(05).
03 YOUR-RECORD-3 REDEFINES YOUR-RECORD-4.
05 YOUR-RECORD-3-NUM PIC X(03).
05 FILLER PIC X(01).
05 YOUR-RECORD-3-REST.
07 FILLER PIC X(11).
07 YOUR-RECORD-3-END PIC X(04).
03 YOUR-RECORD-2 REDEFINES YOUR-RECORD-4.
05 YOUR-RECORD-2-NUM PIC X(02).
05 FILLER PIC X(01).
05 YOUR-RECORD-2-REST.
07 FILLER PIC X(13).
07 YOUR-RECORD-2-END PIC X(03).
03 YOUR-RECORD-1 REDEFINES YOUR-RECORD-4.
05 YOUR-RECORD-1-NUM PIC X(01).
05 FILLER PIC X(01).
05 YOUR-RECORD-1-REST.
07 FILLER PIC X(15).
07 YOUR-RECORD-1-END PIC X(02).
MOVE SPACES TO YOUR-RECORD.
READ YOUR-RECORD.
PERFORM 0100-FIND-NUMBERS
VARYING INDEX-YOUR-NUMBERS
FROM 1
TO 4.
0100-FIND-NUMBERS.
IF YOUR-RECORD-4-NUM IS NUMERIC
MOVE YOUR-RECORD-4-NUM TO YOUR-NUMBER(INDEX-YOUR-NUMBERS)
MOVE YOUR-RECORD-4-REST TO YOUR-RECORD-4
MOVE SPACES TO YOUR-RECORD-4-END
ELSE
IF YOUR-RECORD-3-NUM IS NUMERIC
MOVE YOUR-RECORD-3-NUM TO YOUR-NUMBER(INDEX-YOUR-NUMBERS)
MOVE YOUR-RECORD-3-REST TO YOUR-RECORD-4
MOVE SPACES TO YOUR-RECORD-3-END
ELSE
IF YOUR-RECORD-2-NUM IS NUMERIC
MOVE YOUR-RECORD-2-NUM TO YOUR-NUMBER(INDEX-YOUR-NUMBERS)
MOVE YOUR-RECORD-2-REST TO YOUR-RECORD-4
MOVE SPACES TO YOUR-RECORD-2-END
ELSE
MOVE YOUR-RECORD-1-NUM TO YOUR-NUMBER(INDEX-YOUR-NUMBERS)
MOVE YOUR-RECORD-1-REST TO YOUR-RECORD-4
MOVE SPACES TO YOUR-RECORD-1-END.
Here's a way to do it. Maybe not a good way. Maybe not an efficient way. Maybe not an easy way. But certainly a way that doesn't involve string/unstring - using PIC only. ish.
You could create a little state machine that ran through and calculated every number as it goes. There are many advantages to approaching things on a character by character basis for parsing. The code is usually very simple, especially with a simple regex like number or whitespace.
Identification Division.
Program-ID. PARSENUM.
Data Division.
Working-Storage Section.
01 II comp-5 pic s9(8) value 0.
01 Num-Val comp-5 pic s9(8) value 0.
01 In-Str pic x(80).
01 In-Ch pic 9.
01 pic x(1).
88 In-Number value 'N'.
88 In-Whitespace value 'W'.
Procedure Division.
*> Fake up some data...
Move '1 212 303 44 5678 6 75 888 976' to In-Str
*> Parse Numbers
Set In-Whitespace to true
Perform varying II from 1 by 1
until II > Length of In-Str
If In-Str (II:1) is numeric
Move In-Str (II:1) to In-Ch
Evaluate true
when In-Whitespace
Compute Num-Val = In-Ch
Set In-Number to true
when In-Number
Compute Num-Val = (Num-Val * 10) + In-Ch
End-Evaluate
Else
If In-Number
Display 'Found Number: ' Num-Val
Set In-Whitespace to true
End-If
End-If
End-Perform
Goback.
You should get output that looks like:
Found Number: +0000000001
Found Number: +0000000212
Found Number: +0000000303
Found Number: +0000000044
Found Number: +0000005678
Found Number: +0000000006
Found Number: +0000000075
Found Number: +0000000888
Found Number: +0000000976
I am having a bit of trouble with my COBOL homework. I have to make a program that writes out the names of people and their social security numbers. Basically I have toy make a number like 123456789 show up like 123-45-6789 and a name like JSDOE show up like J S DOE. Can someone help me out?
You should do something like.
01 toyNumber pic 9(9).
01 yourNumber.
03 a pic x(3).
03 b pic x(2).
03 c pic x(4).
01 outNumber.
03 a1 pic x(3).
03 filler pic x value "-".
03 b1 pic x(2).
03 filler pic x value "-".
03 c1 pic x(4).
and in the procedure:
move 123456789 to toyNumber.
....
move toyNumber to yourNumber.
move a to a1.
move b to b1.
move c to c1.
display outNumber.
Or you may use "move corresponding" if you are allowed in your homework.
Hope this help!
PS: The trick for the name is the same ...
COBOL!!
I am writing this after a long time. So, apply caution. Something like this may work:
01 SSN.
03 SSN-FIRST PIC X(03) VALUE SPACES.
03 SSN-FDASH PIC X VALUE "-".
03 SSN-MIDDLE PIC X(02) VALUE SPACES.
03 SSN-MDASH PIC X VALUE "-".
03 SSN-LAST PIC X(04) VALUE SPACES.
01 NAME.
03 FNAME PIC X(10) VALUE SPACES.
03 FDASH PIC X VALUE SPACES.
03 FMIDDLE PIC X(10) VALUE SPACES.
03 MDASH PIC X VALUE SPACES.
03 FLAST PIC X(10) VALUE SPACES.
A more modern (less ancient?) approach :-
STRING SSNUMBER(1:3) DELIMITED BY SIZE
'-' DELIMITED BY SIZE
SSNUMBER(4:5) DELIMITED BY SIZE
'-' DELIMITED BY SIZE
SSNUMBER(6:9) DELIMITED BY SIZE
INTO PRINTFIELD.