Cobol Introduction

by "Blag" - Senior Developer Evangelist

Return to Geeky Thursday

What is Cobol?


Really...what is Cobol?


Cobol (Common business-oriented language) is a compiled English-like computer programming language designed for business use.


It is imperative, procedural and, since 2002, object-oriented.


Designed in 1959 and partly based on the previous work of Grace Hopper.


GnuCOBOL is a transpiler that parses COBOL and converts it to C before compiling it.

How to install GNU Cobol?


On Linux as simple as sudo apt-get install open-cobol


On Windows, you can go here

Who uses Cobol?


Question should be...who doesn't use Cobol?!


  • IBM
  • Deloitte
  • Capital One
  • Visa
  • Citibank
  • Honeywell
  • American Express
  • Fujitsu
  • Many many more...

Starting out...


Cobol doesn't come with a REPL...I don't think REPL's existed when Cobol was around...


Basically you need to create your file and test it out...


And I would recommend getting Geany an awesome editor that will make things easier for you...

Creating our first Cobol file


To makes thing easier, we're going to create a file and use it as our sandbox...


Call it sandbox.cob


And type in the following...

				
IDENTIFICATION DIVISION.

PROGRAM-ID. Sandbox.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.



PROCEDURE DIVISION.

PROGRAM-BEGIN.

    DISPLAY "Hello World!".



PROGRAM-DONE.

STOP RUN.
				

In order to run this app we need to compile into a exe...


cobc -x -free -o Sandbox Sandbox.cob


After that, we can call our application using /.Sandbox

Yep...I know what you are thinking...all that code for a single Hello World?


That's right...Cobol is very structured...


So you need to use the same structure for every single program...


A good idea is to keep that Sandbox as a template for future projects...

Basic Concepts


Printing on the screen is easy...

And only one line comments are allowed...

				
DISPLAY "This a line"


*> And this is a comment
				

Variables


Variables need to declared urder the WORKING-STORAGE SECTION.

And their length is always fixed...

				
WORKING-STORAGE SECTION.

    01 MY-VARIABLE    PIC X(16).
    
    01 MY-AGE         PIC 99.
    
PROCEDURE DIVISION.

PROGRAM-BEGIN.

    MOVE 'My name is Blag' TO MY-VARIABLE.

    DISPLAY MY-VARIABLE.

    MOVE 41 TO MY-AGE.

    DISPLAY "I'm " MY-AGE " years old".
				
				
*> 9 is used for numeric values

*> X is used for alphanumeric values

*> S is used for sign

*> V is used for decimal point


01 MY-DECIMAL    PIC 9(2)V99 VALUE 17.98



*> Keep in mind that lengths are fixed...hence...



01 MY-NUMBER     PIC 9(4) VALUE 15.


*> 0015
				

Arrays are easy...although there are no arrays...we have records...

				
WORKING-STORAGE SECTION.

    01 MY-RECORD.
        
        05 MY-NAME   PIC X(4).
		
        05 FILLER    PIC X(5) VALUE " --> ".
		
        05 MY-AGE    PIC 9(2).
        

PROGRAM-BEGIN.

    MOVE 'Blag' TO MY-NAME.

    MOVE 41 TO MY-AGE.

    DISPLAY MY-RECORD.
    
    
    
*> Blag --> 41
				

What if we have more than one record?

				
WORKING-STORAGE SECTION.

    01 MY-RECORD.

        05 RECORD-LINES OCCURS 2 TIMES.

            10 MY-NAME    PIC X(5).

            10 FILLER	  PIC X(5) VALUE " --> ".

            10 MY-AGE     PIC 9(2).
		    
		    
PROGRAM-BEGIN.

	MOVE 'Blag' TO MY-NAME(1).

	MOVE 41 TO MY-AGE(1).

	MOVE 'Kiara' TO MY-NAME(2).

	MOVE 10 TO MY-AGE(2).	

	DISPLAY RECORD-LINES(1).

	DISPLAY RECORD-LINES(2).		    
				

No functions...no procedures...

Cobol provides us with paragraphs...


				
PROGRAM-BEGIN.

    PERFORM SAY-HELLO.
    
    
PROGRAM-DONE.

STOP RUN.


SAY-HELLO.

    DISPLAY "Hello World!".    
				

Looping

There's no looping...there's calling paragraphs multiple times...

				
WORKING-STORAGE SECTION.

    01 COUNTER    PIC 9 VALUE 1.


PROCEDURE DIVISION.

PROGRAM-BEGIN.

    PERFORM SHOW-COUNTER WITH TEST AFTER 
        
        UNTIL COUNTER = 4.



PROGRAM-DONE.

STOP RUN.
				
				
SHOW-COUNTER.

    DISPLAY "COUNTER is " COUNTER.

    ADD 1 TO COUNTER.
    
    
    
    
*> Counter is 1

*> Counter is 2

*> Counter is 3    
				
				
WORKING-STORAGE SECTION.

    01 COUNTER    PIC 9 VALUE 1.



PROCEDURE DIVISION.

PROGRAM-BEGIN.

    PERFORM SHOW-COUNTER VARYING COUNTER 

        FROM 1 BY 1 UNTIL COUNTER > 3.



PROGRAM-DONE.

STOP RUN.


SHOW-COUNTER.

	DISPLAY "COUNTER is " COUNTER.
				

Hold on...this is weird...


We tackled most of the Cobol's reserved words...


and most of the things that you can use in Cobol...


So better check the examples...


Fibonacci List


Finally...we're going to make our first application...


So grab your favorite text editor and get ready...


Name your file "fibonacci.cob"


				
IDENTIFICATION DIVISION.

PROGRAM-ID. fibonacci.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.

    01 USER-NUMBER       PIC 9(3).

    01 A                 PIC 9(3).

    01 B                 PIC 9(3).

    01 AB                PIC 9(3).

    01 COUNTER           PIC 9(3).	

    01 COUNTER-SPACES    PIC 9(3).
				
				  
PROCEDURE DIVISION.

PROGRAM-BEGIN.

    MOVE 0 TO A.
    
    MOVE 1 TO B.
    
    DISPLAY "Enter a number: ".
    
    ACCEPT USER-NUMBER.
    
    PERFORM GET-FIBO WITH TEST AFTER UNTIL 
    
            USER-NUMBER = 1.
            
    DISPLAY " ". 



PROGRAM-DONE.

STOP RUN.
				
				  
GET-FIBO.

    IF A = 0

        COMPUTE AB = A + B

        INSPECT AB TALLYING COUNTER FOR CHARACTERS

        INSPECT AB TALLYING COUNTER-SPACES FOR
        
                            LEADING ZEROS

        COMPUTE COUNTER-SPACES = COUNTER-SPACES -
        
                                 COUNTER

        DISPLAY 0 " " 1 " " AB(COUNTER:COUNTER-SPACES)
        
                WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 1

        MOVE AB TO A
				
				  
    ELSE

        MOVE 0 TO COUNTER

        MOVE 0 TO COUNTER-SPACES		

        COMPUTE AB = A + B

        INSPECT AB TALLYING COUNTER FOR CHARACTERS

        INSPECT AB TALLYING COUNTER-SPACES FOR 
        
                            LEADING ZEROS

        IF COUNTER-SPACES = 0

            DISPLAY " " AB WITH NO ADVANCING

        END-IF
				
				  
        IF COUNTER-SPACES = 1

            COMPUTE COUNTER = COUNTER - COUNTER-SPACES

            DISPLAY " " AB(COUNTER:COUNTER) 
            
                    WITH NO ADVANCING

        END-IF
        
        IF COUNTER-SPACES = 2

            COMPUTE COUNTER-SPACES = COUNTER-SPACES - 
            
                                     COUNTER

            DISPLAY " " AB(COUNTER:COUNTER-SPACES) 
            
                    WITH NO ADVANCING

        END-IF

        COMPUTE USER-NUMBER = USER-NUMBER - 1

        MOVE A TO B

        MOVE AB TO A

    END-IF.
				

Open the Terminal and go to your source code folder...

cobc -x -free -o fibonacci fibonacci.cob

When we run it we're going to see...


Making an LED Number App


This is one of my favorite codes of all time...


Name your file "LED_Numbers.cob"


				
IDENTIFICATION DIVISION.

PROGRAM-ID. led_numbers.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.

01 LED-TABLE.

    05 LED-DIGITS OCCURS 30 TIMES.

        10 LED-DIGIT PIC X(4).

01 USER-NUMBER 		PIC X(15).

01 COUNTER              PIC 9(2).

01 COUNTER-SPACES	PIC 9(2).

01 NUM-COUNTER		PIC 9(2).

01 LINE-DIGIT 		PIC 9(2).
				
				
01 SINGLE-DIGIT		PIC 9.

01 LINE-COUNT   	PIC 9.


PROCEDURE DIVISION.

PROGRAM-BEGIN.

    DISPLAY "Enter a number: ".

    ACCEPT USER-NUMBER.

    INSPECT USER-NUMBER TALLYING COUNTER FOR 
    
            CHARACTERS.

    INSPECT USER-NUMBER TALLYING COUNTER-SPACES FOR 
    
            TRAILING SPACES.

    COMPUTE COUNTER = COUNTER - COUNTER-SPACES.
				
				
*> This needs to be on the same line...

*> I cut it here just for visibility    
    
    MOVE ' _  | | |_|      |   |   _   _| |_  _   _|  
    
           
          _|      |_|   |  _  |_   _|  _  |_  |_| _
           
           
         |   |   _  |_| |_|  _  |_|  _| ' TO LED-TABLE.

    
    
    MOVE 1 TO LINE-COUNT.

    PERFORM PRINT-LINE WITH TEST AFTER UNTIL 
    
            NUM-COUNTER = COUNTER.

    MOVE 0 TO NUM-COUNTER.

    MOVE 2 TO LINE-COUNT.

    DISPLAY " ".
				
				
    PERFORM PRINT-LINE WITH TEST AFTER UNTIL 
     
            NUM-COUNTER = COUNTER.

    MOVE 0 TO NUM-COUNTER.

    MOVE 3 TO LINE-COUNT.

    DISPLAY " ".

    PERFORM PRINT-LINE WITH TEST AFTER UNTIL 
    
            NUM-COUNTER = COUNTER.		


PROGRAM-DONE.

STOP RUN.



SHOW-LINE.

    DISPLAY LED-DIGITS(LINE-DIGIT) 
	
            WITH NO ADVANCING.
				
				
PRINT-LINE.

    ADD 1 TO NUM-COUNTER.

    MOVE USER-NUMBER(1:NUM-COUNTER) TO SINGLE-DIGIT.

    IF SINGLE-DIGIT NOT = SPACE

        IF SINGLE-DIGIT = 0

            MOVE LINE-COUNT TO LINE-DIGIT

        ELSE

            COMPUTE LINE-DIGIT = SINGLE-DIGIT * 3 
            
                                 + LINE-COUNT

        END-IF

    END-IF.


    PERFORM SHOW-LINE.
				

When we run it we're going to see...


Random Names


This App will generate 100,000 random names using two 16 elements records


We will measure the runtime


Name your file "random_names.cob"


				
IDENTIFICATION DIVISION.

PROGRAM-ID. random_names.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.

    01 RAND-NAME  PIC 9.

    01 RAND-LAST-NAME  PIC 9.

    01 COUNTER		PIC 9(6). 

    01 NAMES.

        05 BAG-OF-NAMES OCCURS 16 TIMES.

            10 NAME PIC X(10).

    01 LAST-NAMES.

        05 BAG-OF-LAST-NAMES OCCURS 16 TIMES.

            10 LAST-NAME PIC X(13).
				
				
    01 FULL-NAMES.

        05 BAG-OF-FULL-NAMES OCCURS 100001 TIMES.

            10 FULL-NAME PIC X(23).				


PROCEDURE DIVISION.

PROGRAM-BEGIN.

    MOVE 1 TO COUNTER.

    MOVE 'Anne      Gigi      Blag      Juergen   
    
          Marek     Ingo      Lars      Julia     
          
          Danielle  Rocky     Julien    Uwe       
          
          Myles     Mike      Steven    
          
          Fanny      ' TO NAMES.
			
				
    MOVE 'Hardy        Read         Tejada       
    
          Schmerder    Kowalkiewicz Sauerzapf    
          
          Karg         Satsuta      Keene        
          
          Ongkowidjojo Vayssiere    Kayly        
          
          Fenlon       Flynn        Taylor       
          
          Tan          ' TO LAST-NAMES.

    MOVE FUNCTION RANDOM(FUNCTION 
    
         SECONDS-PAST-MIDNIGHT) TO RAND-NAME.

    MOVE FUNCTION RANDOM(FUNCTION 
    
         SECONDS-PAST-MIDNIGHT) TO RAND-LAST-NAME.

    PERFORM GENERATE-NAMES 100001 TIMES.

    DISPLAY "100000 names generated".	

PROGRAM-DONE.

STOP RUN.
			
				
GENERATE-NAMES.

    COMPUTE RAND-NAME = (FUNCTION RANDOM * 15) + 1.

    COMPUTE RAND-LAST-NAME = (FUNCTION RANDOM 
    
                              * 15) + 1.	

    MOVE FUNCTION CONCATENATE(
    
         NAME(RAND-NAME), LAST-NAME(RAND-LAST-NAME)) 
                              
         TO FULL-NAME(COUNTER).

    ADD 1 TO COUNTER.
    
			

How this behaves in Python?

And what about Go?

Decimal to Romans


This App will create a Roman Numeral based on a decimal number


This could have been done is a much nicer way...but...it works like this...so...


				
IDENTIFICATION DIVISION.

PROGRAM-ID. decimal_to_roman.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.

    01 USER-NUMBER    PIC 9(4).



PROCEDURE DIVISION.

PROGRAM-BEGIN.

    DISPLAY "Enter a number: ".

    ACCEPT USER-NUMBER.

    PERFORM PRINT-ROMAN WITH TEST AFTER 
    
            UNTIL USER-NUMBER = 0.
            
    DISPLAY " ".
			
				
PROGRAM-DONE.

STOP RUN.



PRINT-ROMAN.

    IF USER-NUMBER >= 1000

        DISPLAY "M" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 1000

    ELSE IF USER-NUMBER >= 900

        DISPLAY "CM" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 900

    ELSE IF USER-NUMBER >= 500

        DISPLAY "D" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 500
			
				
    ELSE IF USER-NUMBER >= 400

        DISPLAY "CD" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 400

    ELSE IF USER-NUMBER >= 100

        DISPLAY "C" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 100

    ELSE IF USER-NUMBER >= 90

        DISPLAY "XC" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 90

    ELSE IF USER-NUMBER >= 50

        DISPLAY "L" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 50
			
				
    ELSE IF USER-NUMBER >= 40

        DISPLAY "XL" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 40

    ELSE IF USER-NUMBER >= 10

        DISPLAY "X" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 10

   ELSE IF USER-NUMBER >= 9

        DISPLAY "IX" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 9

   ELSE IF USER-NUMBER >= 5

        DISPLAY "V" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 5
			
				
   ELSE IF USER-NUMBER >= 4

        DISPLAY "IV" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 4

   ELSE IF USER-NUMBER >= 1

        DISPLAY "I" WITH NO ADVANCING

        COMPUTE USER-NUMBER = USER-NUMBER - 1	

   END-IF.
			

When we run it we're going to see...


Count Letters


In this example we're going to read a file and count how many time a letter appears...


Call your file "count_letters.cob" (all in lowercase).


Create a file called "readme.txt" with the following text...


"This is a text file that we're going to read using Cobol"


				
IDENTIFICATION DIVISION.

PROGRAM-ID. count_letters.

ENVIRONMENT DIVISION.

INPUT-OUTPUT SECTION.

FILE-CONTROL.

    SELECT README-FILE ASSIGN TO DISK

        ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.

FILE SECTION.

FD README-FILE

   LABEL RECORDS ARE STANDARD

   RECORD CONTAINS 56 CHARACTERS

   VALUE OF FILE-ID IS "README.txt"

   DATA RECORD IS README-RECORD.
				
				
01 README-RECORD.

    05 README-LINES PIC X(56).



WORKING-STORAGE SECTION.

01 CHARACTER-LINES.

    05 CHARACTER-LINE OCCURS 56 TIMES.

        10 SINGLE-CHARACTER PIC X(1) VALUE ZEROS.

        10 NUMBER-CHARACTER PIC 9.

01 COUNTER          PIC 99.

01 NUM-COUNTER      PIC 99.

01 PAIR-COUNT       PIC 99.

01 FOUND-LINE       PIC 99.

01 LAST-FOUND       PIC 99.

01 TOTAL-LETTERS    PIC 99.
				
				
PROCEDURE DIVISION.

PROGRAM-BEGIN.

    MOVE 57 TO TOTAL-LETTERS.

    MOVE 1 TO COUNTER.

    MOVE 0 TO FOUND-LINE.

    PERFORM OPENING-PROCEDURE.

    READ README-FILE NEXT RECORD.

    PERFORM CHECK-LETTERS WITH TEST AFTER UNTIL 
    
            COUNTER = TOTAL-LETTERS.

    PERFORM CLOSING-PROCEDURE.

    MOVE 1 TO COUNTER.

    PERFORM SHOW-PAIRS WITH TEST AFTER UNTIL 
    
            COUNTER = PAIR-COUNT.

    DISPLAY " ".
				
				 
PROGRAM-DONE.

STOP RUN.



OPENING-PROCEDURE.

    OPEN INPUT README-FILE.



CLOSING-PROCEDURE.

    CLOSE README-FILE.



CHECK-LETTERS.

    MOVE 1 TO NUM-COUNTER.

    MOVE 0 TO FOUND-LINE.

    PERFORM CHECK-RECORDS WITH TEST AFTER UNTIL 
    
            NUM-COUNTER = TOTAL-LETTERS.
				
				 
    IF FOUND-LINE = 0 AND LAST-FOUND = 0

        MOVE README-LINES(COUNTER:1) TO 
        
             SINGLE-CHARACTER(COUNTER)

        MOVE 1 TO NUMBER-CHARACTER(COUNTER)

        ADD 1 TO PAIR-COUNT

    ELSE IF FOUND-LINE > 0

        COMPUTE NUMBER-CHARACTER(FOUND-LINE) = 
        
                NUMBER-CHARACTER(FOUND-LINE) + 1	

    ELSE IF LAST-FOUND > 0

        MOVE README-LINES(COUNTER:1) TO 
        
             SINGLE-CHARACTER(LAST-FOUND + 1)

        MOVE 1 TO NUMBER-CHARACTER(LAST-FOUND + 1)

        ADD 1 TO PAIR-COUNT

    END-IF.
				
				 
    ADD 1 TO COUNTER.



CHECK-RECORDS.

    IF README-LINES(COUNTER:1) = 
    
        SINGLE-CHARACTER(NUM-COUNTER)

        MOVE NUM-COUNTER TO FOUND-LINE

    END-IF.

    IF SINGLE-CHARACTER(NUM-COUNTER) NOT = 0

        MOVE NUM-COUNTER TO LAST-FOUND

    END-IF.

    ADD 1 TO NUM-COUNTER.
				
				 
SHOW-PAIRS.

    IF SINGLE-CHARACTER(COUNTER) NOT = 0

        DISPLAY SINGLE-CHARACTER(COUNTER) 
        
                " --> " 
                
                NUMBER-CHARACTER(COUNTER)

    END-IF

    ADD 1 TO COUNTER.
				

When we run it we're going to see...


That's it for now


Well...Cobol is pretty old...


Doesn't have much keywords...


You're not going to use it for Web Development...although technically you can...


Learning Cobol will make you glimpse into the past...and see how ancient programmers used to work...

Contact Information


Blag --> blag@blagarts.com

@Blag on Twitter

Go back home...