COBOL - copy an array to another array - arrays

how to copy an array to another array in cobol ?
A PIC 9999 occurs 5.
B PIC 9999 occurs 5.
i need to copy A to B. anyone can help me ?
Thanks All.

Working Storage
01 AA.
03 A PIC 9999 occurs 5.
01 BB.
03 B PIC 9999 occurs 5.
Procedure:
MOVE AA TO BB.
HTH!

If you were looking for a loop:
01 AA-Length Pic S9(8) Binary value +0.
01 BB-Length Pic S9(8) Binary value +0.
01 II Pic S9(8) Binary value +0.
...and...
Compute AA-Length = Length of AA / Length of A(1)
Compute BB-Length = Length of BB / Length of B(1)
Perform varying II from 1 by 1
until II > AA-Length or II > BB-Length
Move A (II) to B (II)
End-Perform

Related

How to make a loop in Cobol Language that displays like a pyramid

IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NAME PIC A(9) VALUE 'FELIX'.
is there other way of looping?
PROCEDURE DIVISION.
PERFORM A-PARA THRU E-PARA.
A-PARA.
DISPLAY 'L'.
B-PARA.
DISPLAY 'I I I'.
C-PARA.
DISPLAY 'A A A A A'.
D-PARA.
DISPLAY 'M M M M M M M'.
This is the Output:
L
III
AAAAA
MMMMMMM
My expecting Output Should be:
L
III
AAAAA
MMMMMMM
thanks for the response in advance. I'm new to this programing language and its very confusing.
Really shouldn't ask people to do your homework . . .
I did this on an openvms machine. You will have to tweak for whatever COBOL environment you are using.
$ cob/reserved_words=200x PYRAMID.COB
$ LINK PYRAMID
$ RUN PYRAMID
*
***
*****
*******
*********
You can get yourself a free account in the same place if you have access to a good VT-100 emulator.
https://eisner.decus.org/
IDENTIFICATION DIVISION.
PROGRAM-ID. A.
*> COB/RESERVED_WORDS=200X PYRAMID.COB
*> LINK PYRAMID
*> RUN PYRAMID
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MY-NUMBERS.
05 START-POS PIC 9(4) USAGE IS COMP VALUE IS ZERO.
05 END-POS PIC 9(4) USAGE IS COMP VALUE IS ZERO.
05 SUB-POS PIC 9(4) USAGE IS COMP.
05 DISTANCE PIC 9(4) USAGE IS COMP.
77 MAX-WIDTH PIC 9(4) USAGE IS COMP VALUE IS 10.
77 CENTER-POS PIC 9(4) USAGE IS COMP VALUE IS 5.
01 MY-DISPLAYS.
05 DISPLAY-LINE.
10 DISPLAY-CELL PIC X OCCURS 10.
PROCEDURE DIVISION.
A000-MAIN.
PERFORM B000-CREATE-PYRAMID
VARYING DISTANCE FROM 0 BY 1
UNTIL DISTANCE IS GREATER THAN 4.
STOP RUN.
B000-CREATE-PYRAMID.
MOVE SPACES TO DISPLAY-LINE.
SUBTRACT DISTANCE FROM CENTER-POS GIVING START-POS.
ADD DISTANCE TO CENTER-POS GIVING END-POS.
PERFORM C000-FILL-LINE
VARYING SUB-POS FROM START-POS BY 1
UNTIL SUB-POS IS GREATER THAN END-POS.
DISPLAY DISPLAY-LINE.
C000-FILL-LINE.
MOVE '*' TO DISPLAY-CELL (SUB-POS).
To make a character-based pyramid in COBOL, the first thing to determine is the width of the base of the pyramid. This depends on the number of levels and the "slope" of the sides. For Example 1, at a slope of one character per line, the base will be (2 * (number-of-levels - 1)) + 1, or (2 * (4 - 1)) + 1 = 7 for the width of the base.
Next find the starting position (mid-point) for the top of the pyramid. This is (width-of-base + 1) / 2. For Example 1, (7 + 1) / 2 = 4.
For each level (PERFORM VARYING) of the pyramid, decrease the starting position by 1 and increase the width by 2.
For Example 2, a "slope" of two characters per line is used. The base is 13, the starting position is 7, the starting position is decreased by 2 (the "slope") and the width is increased by 4.
For both Examples 1 and 2, asterisks (* or * ) are inserted where the intended characters are to be placed, then an INSPECT statement is used to change the asterisks to the correct characters. INSPECT is also a "loop" statement (internally).
For Example 3, a pyramid-like structure, with a "slope" of one, is built from text. The number of levels, the width and starting point are calculated based on the length of the text to be displayed.
Code:
data division.
working-storage section.
1 pyramid-chars pic x(4) value "LIAM".
1 level-number comp pic 9(4).
1 start-point comp pic 9(4).
1 width comp pic 9(4).
1 display-line pic x(50).
1 number-of-levels comp pic 9(4).
1 max-move comp pic 9(4).
1 text-ptr comp pic 9(4).
1 para-text pic x(116) value "This is a long paragraph to "
& "demonstrate building a pyramid from text. The only "
& "explicit loop is the PERFORM VARYING.".
procedure division.
* Example 1
move space to display-line
move 4 to start-point
move 1 to width
perform varying level-number from 1 by 1
until level-number > 4
move all "*" to display-line (start-point:width)
inspect display-line replacing
all "*" by pyramid-chars (level-number:1)
subtract 1 from start-point
add 2 to width
display display-line
end-perform
* Example 2
display space
move space to display-line
move 7 to start-point
move 1 to width
perform varying level-number from 1 by 1
until level-number > 4
move all "* " to display-line (start-point:width)
inspect display-line replacing
all "*" by pyramid-chars (level-number:1)
subtract 2 from start-point
add 4 to width
display display-line
end-perform
* Example 3
display space
compute number-of-levels = ( function sqrt
( 16 * function length (para-text) ) ) / 4
if (number-of-levels *
(2 + 2 * (number-of-levels - 1))) / 2
< function length (para-text)
add 1 to number-of-levels
end-if
compute start-point =
( 2 * (number-of-levels - 1) + 1 ) / 2 + 1
move 1 to width
move 1 to text-ptr
move space to display-line
perform varying level-number from 1 by 1
until level-number > number-of-levels
compute max-move = function min ( (function length
(para-text) - text-ptr + 1) width )
move para-text (text-ptr:max-move)
to display-line (start-point:width)
add max-move to text-ptr
subtract 1 from start-point
add 2 to width
display display-line
end-perform
stop run
.
Output:
L
III
AAAAA
MMMMMMM
L
I I I
A A A A A
M M M M M M M
T
his
is a
long p
aragraph
to demonstr
ate building
a pyramid from
text. The only ex
plicit loop is the
PERFORM VARYING.
there are several ways to loop in cobol
go to how to use GO TO in COBOL (I wouldn't recommend to use)
perform statements https://www.tutorialspoint.com/cobol/cobol_loop_statements.htm

Cobol - Date loop

How can I implement a loop that will display subsequent months (01/01/2018, 01/02/2018 etc.) x-times? Additionally, how can I set day,month,year as a variable? By the way, I'm new to Cobol.
This is my code I wrote so far
01 YYYYMMDD Pic 9(8).
01 Integer-Form Pic S9(9).
Move Function Current-Date(1:8) to YYYYMMDD
Compute Integer-Form = Function Integer-of-Date(YYYYMMDD)
Add 12 to Integer-Form
Compute YYYYMMDD = Function Date-of-Integer(Integer-Form)
Display 'Date: ' YYYYMMDD.
EDIT!
PERFORM VARYING Number-Periods FROM 0 BY 1 UNTIL Number-Periods > 36
DISPLAY ws-current-day, "/", ws-current-month, "/", ws-current-year
ADD 1 TO WS-current-month
IF ws-current-month > 12 THEN
COMPUTE ws-current-month = 1
ADD 1 TO WS-current-year
END-IF
END-PERFORM
Best to use redefines and 88 to check month:
01 YYYYMMDD PIC 9(8).
01 YYYYMMDD-R REDEFINES YYYYMMDD.
05 YYYY PIC 9(4).
05 MM PIC 9(2).
88 VALID-MONTH VALUE 1 2 3 4 5 6
7 8 9 10 11 12.
05 DD PIC 9(2).
Then you can use the 88 in the check (within the PERFORM VARYING as you discovered):
IF NOT VALID-MONTH
... increment year

fpe2 and sp78 data types?

I've been analysing the code needed to get CPU temperature and CPU fan speed on Mac OS X.
There are many examples out there. Here is one of them:
https://github.com/lavoiesl/osx-cpu-temp
Now, in the smc.h file there are some strange(to me) data types defined:
#define DATATYPE_FPE2 "fpe2"
#define DATATYPE_SP78 "sp78"
These are data types that later Apple's IOKit writes in memory as a return value, and that then need to be converted to something usable. The author of the code does it like so (Note that he made a typo writing fp78 instead sp78 in comments...):
// convert fp78 value to temperature
int intValue = (val.bytes[0] * 256 + val.bytes[1]) >> 2;
return intValue / 64.0;
What I find mind boggling is that I'm unable to find any note about these two codes fpe2 and sp78, beside in unofficial code examples for accessing temp and fan readings on a Mac.
Does anyone here know how would one ever figure this out on his own, about these codes?! And basically can someone point me out to some documentation about this and/or explain here what those data types are?
While there doesn't seem to be any "official" documentation of these type names, they are generic enough to figure out.
FP = Floating point, unsigned.
SP = floating point, signed.
The last two (hex) digits indicate the integer/fraction bits. The total tells us that the value fits into 16 bits.
So: FPE2 = floating point, unsigned, 14 (0xE) bits integer, 2 (0x2) bits fraction.
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
I I I I I I I I I I I I I I F F
The SP values have the added complication of a sign bit.
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
S I I I I I I I F F F F F F F F
To convert these values to integers, discard the F bits (by shifting) and cast to an integer type. Be careful with the sign bit on the SP values, whether or not the sign is preserved depends on the type you are shifting.

Efficiently iterating successive elements of a transposed matrix (via bit operators)

Let's consider matrices which are internally represented as a 1 dimensional array.
For instance a matrix(3, 4) is really an array (of say type double) or 3*4 elements. Here is the 'memory layout' of the matrix:
00 01 02 03
04 05 06 07
08 09 10 11
As such it's very easy to iterate (row by row, left to right) over all the elements of the matrix: it's just an 32-bit integer going from 0 to 11. This is what the transpose looks like:
00 04 08
01 05 09
02 06 10
03 07 11
What is a (fast) algorithm that taking as input a single 32-bit integer representing the i-th element of the transposed matrix (row by row, left to right) returns the index corresponding to the internal representation? By single I mean that an 'incremental' algorithm is not what I'm looking for, the function just take as input a single 32-bit integer (plus number of rows and columns) and output a single 32-bit integer. I mentioned bit-wise operators as it's likely to be the fastest way to solve the problem but any efficient solution suffice really.
In the example above:
0 --> 0
1 --> 4
2 --> 8
3 --> 1
4 --> 5
5 --> 9
6 --> 2
...
Also, what restrictions (if any) need to be imposed on the number of rows and columns (we already have that num_row*num_col fits in a 32-bit integer) so that the algorithms is guaranteed to work.
Thank you!
As long as the dimensions remain small, you can use a constant as a lookup table:
0x4cd0b73a62951840 >> (x*4)) & 15
If they get slightly larger, you could split this into e.g. generating the upper and lower bits of the result:
((0x00fea540 >> (x*2)) & 3) | (((0x00924924 >> (x*2) & 3) << 2))
Eventually though, the straight-forward approach will be faster.

How can I process this array without huge amounts of code?

I'll start by admitting this is for my homework and I don't expect anything specific just a tip perhaps. The input file is just one 30 byte field that contains names. The output file is two fields 30 bytes each. I'll list the code to show what I mean by this. The program needs to read the input file putting the names into an array and then print them to the two fields in the output file. It would be simple enough if the out put file was like this:
name 1 name 2
name 3 name 4
etc...
but it's supposed to be:
name 1 name 55
name 2 name 56
....
name 54 name 108
I'm not quite understanding how I can code the program to do this without having 54 lines of code (1 for each line in the output). Well here's the code I have so far:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT NAMELIST-FILE-IN
ASSIGN TO 'NAMELIST.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT NAMELIST-FILE-OUT
ASSIGN TO 'NAMELIST.RPT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD NAMELIST-FILE-IN.
01 NAME-IN PIC X(30).
FD NAMELIST-FILE-OUT.
01 NAME-OUT PIC X(60).
WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.
01 PAGE-CTR PIC 99 VALUE ZERO.
01 SUB PIC 999 VALUE 1.
01 LEFT-NAME PIC 99 VALUE 54.
01 RIGHT-NAME PIC 9(3) VALUE 108.
01 WS-DATE.
05 RUN-YEAR PIC XX.
05 RUN-MONTH PIC XX.
05 RUN-DAY PIC XX.
01 HEADING-LINE.
05 PIC X(15) VALUE SPACES.
05 PIC X(20)
VALUE 'NAME LIST REPORT'.
05 HL-DATE.
10 DAY-HL PIC XX.
10 PIC X VALUE '/'.
10 MONTH-HL PIC XX.
10 PIC X VALUE '/'.
10 YEAR-HL PIC XX.
05 PIC X(3) VALUE SPACES.
05 PIC X(5) VALUE 'PAGE'.
05 PAGE-NUMBER-HL PIC Z9 VALUE 1.
01 DETAIL-LINE.
05 NAME-LEFT PIC X(30).
05 NAME-RIGHT PIC X(30).
01 NAME-ARRAY.
05 NAME-X OCCURS 108 PIC X(30).
PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT NAMELIST-FILE-IN
OPEN OUTPUT NAMELIST-FILE-OUT
ACCEPT WS-DATE FROM DATE.
MOVE RUN-MONTH TO MONTH-HL
MOVE RUN-DAY TO DAY-HL
MOVE RUN-YEAR TO YEAR-HL
PERFORM 200-ACCEPT-INPUT
CLOSE NAMELIST-FILE-IN
CLOSE NAMELIST-FILE-OUT
STOP RUN.
200-ACCEPT-INPUT.
PERFORM UNTIL SUB > 108
READ NAMELIST-FILE-IN
MOVE NAME-IN TO NAME-X (SUB)
ADD 1 TO SUB
END-PERFORM
PERFORM 300-PRINT-ONE-PAGE.
300-PRINT-ONE-PAGE.
WRITE NAME-OUT FROM HEADING-LINE
AFTER ADVANCING PAGE
ADD 1 TO PAGE-CTR
Here's the final code for this program if anyone is interested in seeing it.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT NAMELIST-FILE-IN
ASSIGN TO 'NAMELIST.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT NAMELIST-FILE-OUT
ASSIGN TO 'NAMELIST.RPT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD NAMELIST-FILE-IN.
01 NAME-IN PIC X(30).
FD NAMELIST-FILE-OUT.
01 NAME-OUT PIC X(80).
WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.
01 PAGE-CTR PIC 99 VALUE ZERO.
01 SUB PIC 999.
01 SUB2 PIC 999.
01 LEFT-NAME PIC 99 VALUE 54.
01 RIGHT-NAME PIC 9(3) VALUE 108.
01 WS-DATE.
05 RUN-YEAR PIC XX.
05 RUN-MONTH PIC XX.
05 RUN-DAY PIC XX.
01 HEADING-LINE.
05 PIC X(26) VALUE SPACES.
05 PIC X(35)
VALUE 'NAME LIST REPORT'.
05 HL-DATE.
10 DAY-HL PIC XX.
10 PIC X VALUE '/'.
10 MONTH-HL PIC XX.
10 PIC X VALUE '/'.
10 YEAR-HL PIC XX.
05 PIC X(3) VALUE SPACES.
05 PIC X(5) VALUE 'PAGE'.
05 PAGE-NUMBER-HL PIC Z9.
01 DETAIL-LINE.
05 NAME-LEFT PIC X(40).
05 NAME-RIGHT PIC X(40).
01 NAME-ARRAY.
05 NAME-X OCCURS 108 PIC X(30).
PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT NAMELIST-FILE-IN
OPEN OUTPUT NAMELIST-FILE-OUT
ACCEPT WS-DATE FROM DATE.
MOVE RUN-MONTH TO MONTH-HL
MOVE RUN-DAY TO DAY-HL
MOVE RUN-YEAR TO YEAR-HL
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO'
PERFORM 200-ACCEPT-INPUT
END-PERFORM
CLOSE NAMELIST-FILE-IN
CLOSE NAMELIST-FILE-OUT
STOP RUN.
200-ACCEPT-INPUT.
INITIALIZE NAME-ARRAY
MOVE 1 TO SUB
PERFORM UNTIL SUB > 108 OR ARE-THERE-MORE-RECORDS = 'NO'
READ NAMELIST-FILE-IN
AT END
MOVE 'NO' TO ARE-THERE-MORE-RECORDS
MOVE SPACES TO NAME-IN
END-READ
MOVE NAME-IN TO NAME-X (SUB)
ADD 1 TO SUB
END-PERFORM
PERFORM 300-PRINT-ONE-PAGE.
300-PRINT-ONE-PAGE.
ADD 1 TO PAGE-CTR
MOVE PAGE-CTR TO PAGE-NUMBER-HL
WRITE NAME-OUT FROM HEADING-LINE
AFTER ADVANCING PAGE
MOVE SPACES TO DETAIL-LINE
WRITE NAME-OUT FROM DETAIL-LINE
AFTER ADVANCING 1
PERFORM VARYING SUB FROM 1 BY 1 UNTIL SUB > 54
MOVE NAME-X (SUB) TO NAME-LEFT
COMPUTE SUB2 = SUB + 54
MOVE NAME-X (SUB2) TO NAME-RIGHT
WRITE NAME-OUT FROM DETAIL-LINE
AFTER ADVANCING 1
END-PERFORM.
I must apologize, I cannot think of a way to guide you without giving away the answer. I guess this is a spoiler alert.
One possible method you could use would be to add a variable SUB2 to Working-Storage and...
Perform Varying SUB From 1 By 1 Until SUB > 54
Move NAME-X(SUB) to NAME-LEFT
Compute SUB2 = SUB + 54
MOVE NAME-X(SUB2) to NAME-RIGHT
Write NAME-OUT from DETAIL-LINE After Advancing 1 Line
End-Perform
This is kind of kludgy and ties you to an array of 108 elements. You could use a record counter that you increment by 1 for each record read and then compute the values I show hardcoded in the sample above (54 is simply half of 108).
I don't show the page break logic, so perhaps I didn't give the whole show away.
I hope this helps you.
I would have 2 arrays.
One containing the whole file.
01 DETAIL-LINE-ARRAY.
02 DETAIL-LINE OCCURS 54.
05 NAME-LEFT PIC X(30).
05 NAME-RIGHT PIC X(30).
Another like you did with NAME-ARRAY
Then I would populate first the DETAIL-LINE-ARRAY.
I would read twice DETAIL-LINE-ARRAY to fill NAME-ARRAY
Then you can read sequentially NAME-ARRAY
==========================================================================
Another solution:
You can read the file twice. While the first read, you take care only of the left name and populate NAME-ARRAY.
While the second reading, you take care only of the right name and continue to populate NAME-ARRAY.
After the first and second read, you can read your array NAME-ARRAY.
==========================================================================
There is a problem with both last solutions : you have to know how much lines contains your file. Yep, you can have dynamic programming in cobol too :-)
You have to use SORT.
In FILE SECTION add
SD SORT-WORK
01 SORT-RECORD.
05 SR-ORDER PIC 9(09).
05 SR-NAME PIC X(30).
In your PROCEDURE DIVISION add (in pseude-code, you'll need to add some variables in your working storage section.
SORT SORT-WORK
ASCENDING SORT-ORDER
INPUT PROCEDURE IS 1000-INPUT
OUTPUT PROCEDURE IS 2000-OUTPUT
1000-INPUT SECTION.
MOVE 0 TO I.
PERFORM until end-of-file of NAMELIST-FILE-IN
ADD 1 TO I
READ left-name
MOVE I TO SORT-ORDER
MOVE left-name TO SR-NAME
* This operation populates the sort file...
RELEASE SORT-RECORD
END-PERFORM.
PERFORM until end-of-file of NAMELIST-FILE-IN
ADD 1 TO I
READ right-name
MOVE I TO SORT-ORDER
MOVE right-name TO SR-NAME
* This operation populates the sort file...
RELEASE SORT-RECORD
END-PERFORM.
MOVE I TO WS-NB-NAMES.
2000-OUTPUT SECTION.
PERFORM VARYING I FROM 1 BY 1 UNTIL I > WS-NB-NAMES
* This operation returns the "next" record. It begins by the first, second...
RETURN SORT-RECORD
MOVE SR-NAME TO NAME-LEFT
RETURN SORT-RECORD
MOVE SR-NAME TO NAME-RIGHT
WRITE NAMELIST-FILE-OUT FROM DETAIL-LINE
END-PERFORM.
You have some example here for SORT
Have fun !

Resources