I have been trying to use a table for the first time and I have hit a small snag. I have figured out how to make a table, but I cannot figure out how to search the table or move the stored information to another field. Here is the table:
01 SALESMAN-TABLE.
05 TABLE-ENTRIES OCCURS 99 TIMES.
10 SALESMAN-NUMBER PIC 99 VALUE ZEROS.
10 SALESMAN-NAME PIC X(20) VALUE SPACES.
01 SALESMAN-COUNT PIC 9(3) VALUE ZEROS.
This is what I got so far to try and search for data:
510-TABLE-SEARCH.
SEARCH TABLE-ENTRIES
WHEN SALESMAN-NUMBER (ROUTINE-CHECK) = ROUTINE-CHECK
PERFORM 520-WRITE-FILE
WHEN SALESMAN-NUMBER (ROUTINE-CHECK) = 0
CONTINUE
END-SEARCH.
And this is what I am using to move the data:
SET DL-NAME-COLUMN TO SALESMAN-NAME
but it says that DL-NAME-COLUMN should be numeric even though SALESMAN-NAME is alphanumeric. What should I do? Any help will be appreciated.
You should index your table using something like:
05 TABLE-ENTRIES OCCURS 99 TIMES INDEXED BY IND-TABLE-ENTRIES.
Then you can use the SEARCH verb:
510-TABLE-SEARCH.
SEARCH TABLE-ENTRIES
UNTIL SALESMAN-NUMBER (IND) = 0
WHEN SALESMAN-NUMBER (IND) = ROUTINE-CHECK
PERFORM 520-WRITE-FILE
END-SEARCH.
Table indices are always numeric since they are used as pointers (they contain a memory address). The SET verb is normally used to modify table indices.
Use
MOVE SALESMAN-NAME (IND) TO DL-NAME-COLUMN
instead of
SET DL-NAME-COLUMN TO SALESMAN-NAME
Related
I'm reading a file into a table, note the first line is not part of the table.
1000
MS 1 - Join Grps Group Project 5 5
Four Programs Programming 15 9
Quiz 1 Quizzes 10 7
FORTRAN Programming 25 18
Quiz 2 Quizzes 10 9
HW 1 - Looplang Homework 20 15
In the code, the table is represented as follows:
01 GRADES.
05 GRADE OCCURS 1 TO 100 TIMES DEPENDING ON RECORD-COUNT INDEXED BY J.
10 ASSIGNMENT-NAME PIC X(20).
10 CATEGORY PIC X(20).
10 POINTS-POSSIBLE PIC 9(14).
10 POINTS-EARNED PIC 9(14).
I have a few other accumulator variables designated for calculating sums/percentages later on.
01 RECORD-COUNT PIC 9(8) VALUE 0.
01 TOTAL-EARNED-POINTS PIC 9(14).
01 TOTAL-POSSIBLE-POINTS PIC 9(14) VALUE 0.
My issue is, while I'm reading the records, line by line, I want to do the following:
ADD POINTS-EARNED(RECORD-COUNT) TO TOTAL-EARNED-POINTS
Where RECORD-COUNT is the current position in the iteration.
I expect the value of TOTAL-EARNED-POINTS after the first iteration to simply be 5, right?
However, when I DISPLAY the value of TOTAL-EARNED-POINTS, the console reads:
50000000000000
Is this 50 trillion? Or is it a funny looking representation of the number 5?
How can I write this so that I can do proper mathematics with it to print a proper grade report?
EDIT: I know it's likely that there's better ways of writing this program but I've never used cobol before attempting to write this program, and I probably won't use it ever again, or at least for a very long time. This is for a class, so as long as I can print my output properly, I'm good.
Full code, so far:
IDENTIFICATION DIVISION.
PROGRAM-ID. GRADEREPORT.
AUTHOR. JORDAN RENAUD.
DATE-WRITTEN. 09/18/2020.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT GRADES-FILE ASSIGN TO "bill"
ORGANIZATION IS LINE SEQUENTIAL
ACCESS IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD GRADES-FILE.
01 INPUT-TOTAL-POINTS PIC 9(4).
01 INPUT-GRADES.
05 INPUT-GRADE OCCURS 1 to 100 TIMES DEPENDING ON RECORD-COUNT INDEXED BY I.
10 INPUT-ASSIGNMENT-NAME PIC X(20).
10 INPUT-CATEGORY PIC X(20).
10 INPUT-POINTS-POSSIBLE PIC 9(14).
10 INPUT-POINTS-EARNED PIC 9(14).
WORKING-STORAGE SECTION.
77 GRADES-FILE-EOF PIC 9.
01 RECORD-COUNT PIC 9(8) VALUE 0.
01 TOTAL-EARNED-POINTS PIC 9(4) VALUE ZERO.
01 TOTAL-POSSIBLE-POINTS PIC 9(14) VALUE 5.
01 K PIC 9(14) VALUE 1.
01 TMP PIC 9(14).
01 CURRENT-CATEGORY PIC X(20).
01 CATEGORY-WEIGHT PIC X(3).
01 LAST-CATEGORY PIC X(20).
01 TOTAL-POINTS PIC 9(4).
01 GRADES.
05 GRADE OCCURS 1 TO 100 TIMES DEPENDING ON RECORD-COUNT INDEXED BY J.
10 ASSIGNMENT-NAME PIC X(20).
10 CATEGORY PIC X(20).
10 POINTS-POSSIBLE PIC 9(14).
10 POINTS-EARNED PIC 9(14).
PROCEDURE DIVISION.
OPEN INPUT GRADES-FILE.
READ GRADES-FILE INTO TOTAL-POINTS.
DISPLAY TOTAL-EARNED-POINTS
PERFORM UNTIL GRADES-FILE-EOF = 1
READ GRADES-FILE
AT END SET
GRADES-FILE-EOF TO 1
NOT AT END
ADD 1 TO RECORD-COUNT
MOVE INPUT-GRADES TO GRADE(RECORD-COUNT)
SET TOTAL-EARNED-POINTS UP BY POINTS-EARNED(RECORD-COUNT)
DISPLAY TOTAL-EARNED-POINTS
END-READ
END-PERFORM.
CLOSE GRADES-FILE.
DISPLAY TOTAL-EARNED-POINTS.
SORT GRADE ASCENDING CATEGORY.
MOVE CATEGORY(1) TO LAST-CATEGORY.
PERFORM RECORD-COUNT TIMES
MOVE CATEGORY(K) TO CURRENT-CATEGORY
IF CURRENT-CATEGORY = LAST-CATEGORY THEN
DISPLAY "SAME CATEGORY"
ELSE
DISPLAY "NEW CATEGORY"
MOVE LAST-CATEGORY TO CURRENT-CATEGORY
END-IF
SET K UP BY 1
END-PERFORM
DISPLAY GRADES.
STOP RUN.
Edit 2: Upon implementing the given answer to convert the input from the file to a numeric form, the FIRST ROW of the table reads fine, but from then on it's all blank values.
Here's the READ block's new code, I'm not sure if there's a more efficient way to read and convert specific fields in a group field but this is how I assumed it should be done.
PERFORM UNTIL GRADES-FILE-EOF = 1
READ GRADES-FILE
AT END SET
GRADES-FILE-EOF TO 1
NOT AT END
ADD 1 TO RECORD-COUNT
MOVE INPUT-ASSIGNMENT-NAME(RECORD-COUNT) TO ASSIGNMENT-NAME(RECORD-COUNT)
DISPLAY INPUT-ASSIGNMENT-NAME(RECORD-COUNT)
DISPLAY ASSIGNMENT-NAME(RECORD-COUNT)
MOVE INPUT-CATEGORY(RECORD-COUNT) TO CATEGORY(RECORD-COUNT)
DISPLAY INPUT-CATEGORY(RECORD-COUNT)
DISPLAY CATEGORY(RECORD-COUNT)
MOVE FUNCTION NUMVAL (INPUT-POINTS-POSSIBLE(RECORD-COUNT)) TO POINTS-POSSIBLE(RECORD-COUNT)
DISPLAY INPUT-POINTS-POSSIBLE(RECORD-COUNT)
DISPLAY POINTS-POSSIBLE(RECORD-COUNT)
MOVE FUNCTION NUMVAL (INPUT-POINTS-EARNED(RECORD-COUNT)) TO POINTS-EARNED(RECORD-COUNT)
DISPLAY INPUT-POINTS-EARNED(RECORD-COUNT)
DISPLAY POINTS-EARNED(RECORD-COUNT)
COMPUTE TOTAL-EARNED-POINTS = TOTAL-EARNED-POINTS + POINTS-EARNED(RECORD-COUNT)
DISPLAY TOTAL-EARNED-POINTS
END-READ
END-PERFORM.
is it a funny looking representation of the number 5?
No, it is an unchecked fatal exception: EC-DATA-INCOMPATIBLE.
The reason:
Your data definition and record-definition doesn't match:
10 POINTS-EARNED PIC 9(14).
would be
"00000000000005"
not
"5 "
which looks like the better definition for would be
10 SOME-POSSIBILY-NUMERIC-DATA PIC X(14).
If you use GnuCOBOL as the tags suggest, then add -debug to the compile command and you will see the fatal exception stopping the program (the COBOL standard defines that all exception checking is off by default, in my opinion: because of legacy and performance, but at least for developing and testing it is very reasonable to activate them [in most cases it is even more reasonable to let the program abend instead of doing wrong math when the test is over]).
As with any computer language you should be very sure to have valid data (never trust external data, no matter if it is part of a blockchain or a text file you read in).
How can I write this so that I can do proper mathematics with it to
print a proper grade report?
If you want to go with "bad data is just ignored" (which may be appropriate here) just convert it:
MOVE FUNCTION NUMVAL (SOME-POSSIBILY-NUMERIC-DATA)
TO POINTS-EARNED(RECORD-COUNT)
Otherwise do an explicit check (either of completely numeric [own check], or numeric with possible spaces to the left/right FUNCTION TEST-NUMVAL) and stop the program/skip the bad line with a DISPLAY ... UPON SYSERR or whatever is appropriate for you.
According to the COBOL code below when I try to sum WS-NUM1 with WS-NUM2, COBOL seems to supress the last number. For example: variable WS-NUM1 and WS-NUM2 are 10.15, I get 20.20 as result but expected 20.30. What's wrong?
WS-NUM1 PIC 9(2)V99.
WS-NUM2 PIC 9(2)V99.
WS-RESULTADO PIC 9(2)V99.
DISPLAY "Enter the first number:"
ACCEPT WS-NUM1.
DISPLAY "Enter the second number:"
ACCEPT WS-NUM2.
COMPUTE WS-RESULTADO = WS-NUM1 + WS-NUM2.
Thanks in advance.
PIC 9(2)v99 defines a variable with an implied decimal place not a real one. You're trying to enter data containing a decimal point and it's not working because you have to strip out the '.' to get the numeric part of your data to properly fit in the 4 bytes that your working storage area occupies.
PROGRAM-ID. ADD2.
data division.
working-storage section.
01 ws-num-input pic x(5).
01 WS-NUM1 PIC 9(2)V99 value 0.
01 redefines ws-num1.
05 ws-high-num pic 99.
05 ws-low-num pic 99.
01 WS-NUM2 PIC 9(2)V99 value 0.
01 redefines ws-num2.
05 ws-high-num2 pic 99.
05 ws-low-num2 pic 99.
01 WS-RESULTADO PIC 9(2)V99.
PROCEDURE DIVISION.
DISPLAY "Enter the first number:"
*
accept ws-num-input
unstring ws-num-input delimited by '.'
into ws-high-num, ws-low-num
DISPLAY "Enter the second number:"
accept ws-num-input
unstring ws-num-input delimited by '.'
into ws-high-num2, ws-low-num2
*
COMPUTE WS-RESULTADO = WS-NUM1 + WS-NUM2.
DISPLAY WS-RESULTADO
STOP RUN
.
This is just a simple demonstration. In a real world application you would have to insure much more robust edits to ensure that valid numeric data was entered.
If I declare it like this
01 WS-NUM1 PIC 9(2)V99.
01 WS-NUM2 PIC 9(2)V99.
01 WS-RESULTADO PIC 9(2)V99.
and define and sum them up like this
SET WS-NUM1 TO 10.15.
SET WS-NUM2 TO 10.15.
COMPUTE WS-RESULTADO = WS-NUM1 + WS-NUM2.
DISPLAY WS-RESULTADO.
I get the expected result of 20.30.
This looks like a job for a special type of PICture : Edited picture
Indeed you seem to know about the vanilla PICture clause (I'm writing PICture because as you may know it you can either write PIC or PICTURE).
A vanilla number PIC contains only 4 different symbols (and the parentheses and numbers in order to repeat some of the symbols)
9 : Represents a digit. You can repeat by using a number between parentheses like said before.
S : Means that the number is signed
V : Show the position of the implicit decimal point
P : I've been told that it exists but I honestly never found it in the codebase of my workplace. Its another kind of decimal point used for scaling factors but I don't know much about it.
But there are other symbols.
If you use theses other mysterious symbols the numeric PIC becomes an edited numeric PIC. As its name says, an edited PICture is made to be shown. It will allow you to format your numbers for better presentation or to receive number formatted for human reading.
Once edited, you cannot use it to make computations so you will have to transfer from edited to vanilla to perform computations on the latter. And you move from vanilla to edited in order to display your results.
So now I shall reveal some of these mysterious symbols :
B : Insert a blank at the place it is put
0 : Insert a zero at the place it is put
. : Insert the decimal point at the place it is put
: Insert a + if the number is positive and a - if the number is negative
Z : Acts like a 9 if the digits it represents has a value different than 0. Acts like a blank if the digits has the value of 0.
To my knowledge there are also : / , CR DB * $ -
You can look up for it on the internet. They really show the accountant essence of cobol.
For your problems we are really interested by the "." which will allow us to take into account the decimal point you have the write when you type down your input.
For a bonus I will also use Z which will make your result looks like 2.37 instead of 02.37 if the number is less than ten.
Note that you cannot use the repeating pattern with parenthesis ( 9(03) for instance) when describing an edited picture ! Each digits has to represented explicitly
IDENTIFICATION DIVISION.
PROGRAM-ID. EDITCOMP.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-NUM1-EDITED PIC 99.99.
01 WS-NUM2-EDITED PIC 99.99.
01 WS-NUM1-CALC PIC 9(2)V99.
01 WS-NUM2-CALC PIC 9(2)V99.
01 WS-RESULTADO-EDITED PIC Z9.99.
PROCEDURE DIVISION.
ACCEPT WS-NUM1-EDITED.
ACCEPT WS-NUM2-EDITED.
MOVE WS-NUM1-EDITED TO WS-NUM1-CALC.
MOVE WS-NUM2-EDITED TO WS-NUM2-CALC.
COMPUTE WS-RESULTADO-EDITED = WS-NUM1-CALC + WS-NUM2-CALC.
DISPLAY WS-RESULTADO-EDITED.
STOP RUN.
You should note that there also exist edited alphanumeric picture. You can insert Blank (B), zeroes (0) or / (/) in it.
My problem is: I have data in a database table. The column is: Z-ZYTL-RTPDHR defined as NOT NULL NUMBER(5,2) .
So I have a program that I need to move my data in one variable "H-ZYTL-RTPDHR" and after I will move this value divide by 100 in one column Z8 when i compile i obtained Excel with data in the different column.
My data:
Z8
------
34,28
70
97
8,57
21,43
94,28
94,28
100
40
40
what I should get:
Z8
-------
0,3428
0,7
0,97
0,0857
0,2143
0,9428
0,9428
0,100
0,40
0,40
my question how to declare the variable to obtain the good result?
Variables that I declared:
01 FILLER.
05 H-ZYTL-RTPDHR.
10 PIC S9(5)V9(2) comp-3 VALUE.
05 FILLER REDEFINES H-ZYTL-RTPDHR.
10 H-ZYTL-RTPDHR comp-3 pic s9(5)v99.
Equivalent Temps Plein
05 W-Z8 PIC -(5),99.
05 FILLER PIC X(001) VALUE ';'.
ALIM-WZ8 SECTION.
IF Z-ZYTL-NOMBRE > ZERO
IF TLCODTRA(Z-ZYTL-NOMBRE) NOT = SPACES
MOVE Z-ZYTL-RTPDHR(Z-ZYTL-NOMBRE) TO
H-ZYTL-RTPDHR
DISPLAY 'H-ZYTL-RTPDHR:' H-ZYTL-RTPDHR
DIVIDE H-ZYTL-RTPDHR BY 100 GIVING W-Z8
DISPLAY 'W-Z8 : ' W-Z8
END-IF
END-IF.
You have defined the name H-ZYTL-RTPDHR twice: that will confuse you and and the compiler as well.
Your second definition of H-ZYTL-RTPDHR is good for doing arithmetic. All you need is
01 FILLER.
10 H-ZYTL-RTPDHR comp-3 pic s9(5)v99.
Your first definition of H-ZYTL-RTPDHR defines a group level item, and you can't do arithmetic with it.
However, your question doesn't show the definition of Z-ZYTL-RTPDHR. If it's not numeric, then you won't get the results you expect.
I am trying to accept input from jcl for example 'John Snow' and run it from my cobol program Im using JUSTIFIED RIGHT VALUE SPACES to move the string to the right side however I need to delete the extra spaces using my cobol pgm.
example
my working storage is:
01 ALPHA-ITEM PIC X(50).
01 MOVE-ITEM REDEFINES ALPHA-ITEM PIC X(50).
01 NUM-ITEM PIC X(50) JUSTIFIED RIGHT VALUE SPACES.
and in my PROCEDURE DIVISION
ACCEPT ALPHA-ITEM.
MOVE MOVE-ITEM TO NUM-ITEM.
DISPLAY NUM-ITEM.
it displays 'John Snow' on the right of the screen however i don't know how to remove the extra spaces.
you need something like this:
01 ALPHA-ITEM PIC X(50).
01 WS-INDEX PIC 99.
ACCEPT ALPHA-ITEM
PERFORM VARYING WS-INDEX
FROM 50 BY -1
UNTIL ALPHA-ITEM(WS-INDEX:1) NOT EQUAL SPACE
OR WS-INDEX < 1
END-PERFORM
DISPLAY ALPHA-ITEM(1:WS-INDEX).
This code will accept the alpha item, then run a loop to find out how long the data actually is. Then it will display that field starting from position 1 until the counter that was set in the loop.
There is also.. Unpopular for some reason.
UNSTRING MOVE-ITEM DELIMITED BY SPACES INTO NUM-ITEM.
I'm quite the noob on COBOL i bought myself one of those "for dummies" type book but it lacks some depth.
I'm trying to assign and retrieve the value of a field from a nested record. I'm trying per my book suggested, this :
WRITE REPORT-LINE FROM DATE OF HEADER
AFTER ADVANCING PAGE.
WRITE REPORT-LINE FROM INSTITUTION OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM BRANCH OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM DIVISION OF HEADER
AFTER 1.
WRITE REPORT-LINE FROM FILLER-LINE
The layout for my header is this one:
01 HEADER.
02 DATE.
03 O-MONTH PIC ZZ.
03 FILLER PIC X(01) VALUE '/'.
03 O-DAY PIC 99.
03 FILLER PIC X(01) VALUE '/'.
03 O-YEAR PIC 99.
03 FILLER PIC X(116) VALUE SPACES.
03 PAGE PIC A(4) VALUE 'PAGE'.
03 FILLER PIC X(1) VALUE SPACE.
So basically my question is, How for example will I access 0-DAY field of the record DATE from HEADER?
Both for assignment and retrieval. Will it be something like:
MOVE 21 TO 0-DAY OF DATE OF HEADER.
Firstly avoid data-names which are "words". DATE for instance is a word, SOMETHNG-DATE or DATE-SOMETHING are not.
DATE itself is a Reserved Word in COBOL, so I think it unlikely that your example will compile. A word like HEADER could easily become reserved in the future (although these days the standards committee try to avoid that).
HEADER is a group-item. DATE is a group item. The other fields are elementary items. We don't regard structures such as this as "nested", just as group-items which must contain at least one elementary item.
The only time you need to use OF/IN is when there are non-unique names (which you should avoid).
So:
MOVE 21 TO 0-DAY
Will work, as long as 0-DAY is not a duplicate name. The syntax you showed will also work, but why add all the extra for no point, it is just increasing the possibility of a typo, and making the next reader think that your program has non-unique names.
Try to avoid full-stops/periods in the PROCEDURE DIVISION except for those which are necessary (after the PROCEDURE DIVISION header, before a paragraph/SECTION after a paragraph/SECTION label, before the end of the program).