Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language COBOL

(Short Version with Descriptive Varnames.)

Date:07/14/08
Author:Joseph James Frantz
URL:http://www.aoirthoir.com
Comments:17
Info:http://www.opencobol.org
Score: (3.05 in 193 votes)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. 99-Bottles-of-Beer-On-The-Wall.
       AUTHOR. Joseph James Frantz.
      *COMMENTS.
      ******************************************************************
      * PURPOSE:
      *   This is a sample COBOL program to display the lyrics of the
      *   song "99 Bottles of Beer on the Wall."
      *   This version of the COBOL 99 beers program demonstrates a few
      *   features of COBOL:
      *
      *   1. PERFORM VARYING, Cobol's version of a Loop.
      *   2. ADD/SUBTRACT with GIVING for math calculations.
      *   3. EVALUATE/WHEN, Cobol's version of Case.
      *   4. INSPECT/TALLYING, which finds the number of specified
      *      characters in a variable.
      *   5. Reference Modification:
      *      Var-name(Start character:Number of characters)
      *      which is essentially Cobol's version of text subscripting.
      *   6. Long descriptive variable names.
      *   7. Use of SPACES and ZEROES for field/display values.
      *   8. Highlight the self documenting nature of COBOL.
      ******************************************************************
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 Keeping-Track-Variables.
          05 Bottles                      PIC S99   VALUE 0.
          05 Remaining-Bottles            PIC S99   VALUE 0.
          05 Counting                     PIC 99    VALUE 0.
          05 Start-Position               PIC 99    VALUE 0.
          05 Positions                    PIC 99    VALUE 0.
       PROCEDURE DIVISION.
       PASS-AROUND-THOSE-BEERS.
        PERFORM VARYING Bottles FROM 99 BY -1 UNTIL Bottles = -1
          DISPLAY SPACES
          SUBTRACT 1 FROM Bottles GIVING Remaining-Bottles
          EVALUATE Bottles
            WHEN 0
              DISPLAY "No more bottles of beer on the wall, "
                      "no more bottles of beer."
              DISPLAY "Go to the store and buy some more, "
                      "99 bottles of beer on the wall."
            WHEN 1
              DISPLAY "1 bottle of beer on the wall, "
                      "1 bottle of beer."
              DISPLAY "Take one down and pass it around, "
                      "no more bottles of beer on the wall."
            WHEN 2 Thru 99
              MOVE ZEROES TO Counting
              INSPECT Bottles,
                TALLYING Counting FOR LEADING ZEROES
              ADD 1 TO Counting GIVING Start-Position
              SUBTRACT Counting FROM 2 GIVING Positions
              DISPLAY Bottles(Start-Position:Positions)
                      " bottles of beer on the wall, "
                      Bottles(Start-Position:Positions)
                      " bottles of beer."
              MOVE ZEROES TO Counting
              INSPECT Remaining-Bottles TALLYING
                Counting FOR LEADING ZEROES
              ADD 1 TO Counting GIVING Start-Position
              SUBTRACT Counting FROM 2 GIVING Positions
              DISPLAY "Take one down and pass it around, "
                      Remaining-Bottles(Start-Position:Positions)
                      " bottles of beer on the wall."
          END-EVALUATE
        END-PERFORM
       STOP RUN.

Download Source | Write Comment

Alternative Versions

VersionAuthorDateCommentsRate
1Donald Fraser04/20/056
"Pretty" versionSumanta Mukhopadhyay10/06/051
Typical of mainframe COBOL programsBill Bass04/24/088

Comments

>>  jim said on 07/30/08 19:53:48

jim Tight code and nice demo of some COBOL strengths. Pretty short program too for a language that's often accused of being "verbose".

>>  Joseph James Frantz said on 08/09/08 00:42:16

Joseph James Frantz Thanks Jim.

I am always surprised when people object to COBOL on the basis of its being verbose. Generally I find out that their vast experience with COBOL extends to having taken one college course on the subject, if even that. COBOL can be as verbose or as slim as you want.

There are many reserved words of course, but none of them are terribly large. For instance:

MOVE "Hello World" TO myvar

Is not much different than

SET myvar = "Hello World"
or
$myvar = "Hello World";

The same is true with the vast majority of COBOL reserved words. EVALUATE...WHEN is not much different from SWITCH...CASE or CASE...WHEN in other languages. PERFORM VARYING myvar FROM 1 by 1 UNTIL myvar = 100 is one of the rarer cases that is more wordy than in SOME other languages, but not all languages. If though, you were doing anything but a For i=1 to 100 loop, then the PERFORM is not more wordy than a LOOP WHILE or a LOOP UNTIL.

Now it is true that there are a few lines required at the top of a COBOL program that most other languages do not have. To borrow from my code above:

IDENTIFICATION DIVISION.
PROGRAM-ID. SOMENAME.
DATA DIVISION.
WORKING-STORAGE SECTION.
PROCEDURE DIVISION.

This is the code that most folks complain about, the required stuff that makes COBOL verbose and wordy. That's 142 characters. If all you wanted to do was write a hello world program, then I can see that the 142 characters is something to complain about, since the stuff you are really interested in is:

DISPLAY "HELLO WORLD"
or
echo "HELLO WORLD";
or
something similar in the language of your choice. So in other languages, sure the hello world would probably be smaller, but only by about 142 characters. But in any real world programs, these minor 142 characters make your code much cleaner, easier to debug, much more readable and vastly more maintainable. From a business standpoint it also ensures that real world people can verify some of the business logic you have in your code. Languages like PHP, Java, C, and Ruby cannot make that claim. I am not disrespecting these or other languages, they are fine languages and each have their strong points. COBOL's strong point is, from the ground up it is Data Centric. Most other languages, Data is an afterthought. With COBOL it is central to the entire language.

Another complaint is the size of variable names. The thing to understand that variables can be named pretty much as the coder decides. Another version of the 99 Beers done in COBOL, the coder used the variable names i, j, k & l. Depending on your compiler, COBOL variable names can be as large as 64 characters, and I believe in some compilers 128 characters. The emphasis here is they *can* be that long. You are not required to make them that long. For instance I forgo in my code the common practice of prefacing variables from the Working-Storage section with WS-.

Finally, comparing the size of my version here, with PHP versions, C or other languages, you'll find that most of the complaints about the verbosity of COBOL programs are unwarranted. Now, I'm not saying that you can't make even smaller versions in those languages, or in COBOL. What I am saying rather is, that the verbosity of a particular program often depends more on the coding style of the coder, than on the language itself.
=====

I appreciate all of the votes also. If anyone has comments about the code, or ways it could be improved, perhaps how you would do something different, I would greatly appreciate it if you would comment here. Or you can contact me directly.

>>  Mycroft said on 09/20/08 18:38:18

Mycroft The major change I would make is to use COMPUTE instead of the other verbs. The reason is that COMPUTE will do type conversion in ALL versions of COBOL, while MOVE, ADD, SUBTRACT, etc will not. That includes things like: COMPUTE var-name = 1.

Shortest Production program I ever did in COBOL was 14 lines. Longest was over 5700 lines. Most fun was a COBOL program that wrote COBOL FDs to be compiled and run without human intervention.

>>  Jörn said on 02/01/09 20:07:22

Jörn If this is a pretty short program by COBOL standards, I'd say that COBOL's reputation for verbosity is well earned.

>>  -jn- said on 04/12/09 15:04:59

-jn- To those who are defending COBOL against charges of verbosity, let me just point out one example: consider how many times the pattern "_ bottle[s] of beer[ on the wall]" occurs in the above. Every time it appears in/as a literal string, at least two things happen: (1) there's an(other) opportunity for a typo, and (2) the reasons for the variations (whether to put the "s" after "bottle", whether to include " on the wall";) are obscured.

English-speaking programmers who know the bit of doggerel that inspired this collection surely will be able to guess the reasons, but that doesn't scale up, as coding by copy-and-paste-with-variations shows WHAT is happening but not WHY its happening.

Speaking as someone who wrote COBOL for several years, this doesn't make COBOL a bad language; however, it does offer an objective indicator of where the language does (and does not) offer built-in support for certain programming practices (e.g. parameterization of all significant decisions in the code, the DRY principle, etc.)

>>  zhrinze said on 04/12/09 20:20:34

zhrinze -jn-, I don't think you're making a logical point here. The code example could be different, yes, but it does not implicate COBOL in any way. When you mention the repetition of the literals (which I found quite clear - maybe you didn't, I cannot speak to that), you miss the point. COBOL certainly has the ability to create constants for these literals that help document them better.

Remember, however, this ENTIRE website was created on the concept of a six line BASIC program. Not one well designed for readability over the long haul, not the most efficient, just a fair example of code. Criticizing COBOL for the coder's use of literals is wrong. COBOL can be coded as needed for straight-forward business calculations - or you can abuse the structure to create an awful mess. You can do that in any language.

You might have programmed using older COBOL compilers. COBOL has not stood still. COBOL is now 50 years old and still in heavy use. People argue it is because it would be too expensive to replace. A good businessman will tell you that bad computer code is too expensive not to replace when it handles your core finances. It doesn't get replaced for core work because it is efficient and solid. It works.

UIs come and go, but the core remains.

>>  Larry Pishioneri said on 04/18/09 00:10:54

Larry Pishioneri If I remember correctly (during my programming career days), Identification Division could be written as ID DIVISION. Saved some keystrokes there, huh?

I've got a beagle, you've got a bassett hound, she's got a poodle. We all like ours for one reason or another. They each make us happy, no? Don't waste too much time arguing which language is/was better.

Has anyone begun writing conversion routines for the year 10000?

>>  barry said on 04/22/09 20:46:03

barry In COBOL (rm/cobol) PIC S99 will keep the sign in right most diget.
So foe example 99, will b printed as 9I, 98-9H, etc
To solve that problem, add:
05 Bottles PIC S99 VALUE 0 SIGN TRAILING SEPARATE.
05 Remaining-Bottles PIC S99 VALUE 0 SIGN TRAILING SEPARATE.

>>  Bill Talbot said on 04/25/09 05:45:47

Bill Talbot
Happy Birthday COBOL!

Okay, I'm not at work and I don't have a COBOL compiler on my Mac, and I'm too lazy right now at 10:33pm on a Friday night to go find an online interpreter. I do however, see a problem with the PERFORM VARYING instruction. (I was also WAY too lazy tonight to read other comments, so if it's already been said, then so be it.)

I also have to throw out some serious props to the original author of this work. Anyone who actively codes in COBOL and who goes to dinner with family, friends, etc., and gets sh*t for coding in an "archaic" language like COBOL deserves a tip of the hat, IMHO.

Onward to the bug I believe I've found.

PERFORM VARYING Bottles FROM 99 BY -1 UNTIL Bottles = -1
DISPLAY SPACES
SUBTRACT 1 FROM Bottles GIVING Remaining-Bottles
.
.
.


The VARYING clause in the PERFORM instruction takes care of the under-the-hood math. There's no reason for the SUBTRACT instruction. Again, laziness on my part by not pasting it into a module and compiling and running it, but this code should only show every other bottle on the wall. The VARYING starts out at 99 and decrements "Bottles" by -1, then the SUBTRACT subtracts another (+)1 for each iteration. A 2-for-1 special, programatically, if you were :).

As for COBOL being verbose, it was totally intended to be. It's meant by it's very nature to be aligned as strongly as possible with the business-backend of companies and their IT infrastructures, long before the term "IT" was formed. Here's a GREAT article I found on www.microfocus.com just today, as a matter of fact:

http://www.guardian.co.uk/technology/2009/apr/09/cobol-internet-programming

Thanks for all of the good comments about COBOL. Anyone who dogs it has yet to dig through a complex IBM dump at 3:47am with 2 VP's standing behind them in their cube with clients on the phone chomping at the bit to collect the penalty checks if the job isn't done by 4:01am.

Not that I'm married to it or anything...still coding in PHP on the side...LOL :).

Your comments, suggestions, adoration or aberration are all welcome.

BT

>>  Jon said on 04/28/09 14:20:53

Jon Fun stuff... I agree 100% with BT on why COBOL is verbose. See an explanation here:

http://www-949.ibm.com/software/rational/cafe/docs/DOC-3101

>>  MJP said on 04/28/09 17:08:57

MJP A comment on the comment from Bill Talbot. The line of code: SUBTRACT 1 FROM Bottles GIVING Remaining-Bottles does not in any way change the value of Bottles. It is like R=B-1. So we do NOT get every other bottle as discussed.

>>  Michael said on 05/15/09 17:07:43

Michael Nice, I like the short version as LESS is always MORE... Here's the Speedware Version which is even smaller.

DCL bottles FORMAT(TYPE=INT,LENGTH=3,BYTES=4,SUBTYPE=NUMERIC);
LOOP bottles ITERATIONS(99) STEP(-1) INIT(99) DO
BEGIN
CASE bottles OF
0 : BEGIN
MSG 'No more bottles of beer on the wall, ' +
'no more bottles of beer.';
MSG 'Go to the store and buy some more, ' +
'99 bottles of beer on the wall.';
END;
1 : BEGIN
MSG '1 bottle of beer on the wall, ' +
'1 bottle of beer.';
MSG 'Take one down and pass it around, ' +
'no more bottles of beer on the wall.';
END;
OTHERWISE : BEGIN
MSG $STR(bottles) + ' bottles of beer on the wall, ' +
$STR(bottles) + ' bottles of beer.';
MSG 'Take one down and pass it around, ' +
$STR(bottles) + 'bottles of beer on the wall.';
END;
ENDCASE;
END;


Ciao!

>>  Aoirthoir An Broc (Formerly Jo said on 08/26/09 01:51:14

Aoirthoir An Broc (Formerly Jo @Mycroft, Thanks for the tip. I use OpenCobol, so I will verify that is the case there also.

@Jorn, I've compared my Cobol version to other variations in other Languages, for instance the C and PHP versions, and this one is about the same size.

A key point here folks, is that this version of the song, is the *complete* song. Several of the *short* versions in other languages are also *incomplete*. A program that does not perform as it should, cannot be properly compared to another program in a different language that does perform as required.

@JN Regarding the literals that I used in the app and their repetition being a potential for typos, you are absolutely correct. Remember though this is simply *one* way of doing this song in Cobol. I could just as well have used variables, as other Cobol versions had done. The use or lack of literals has nothing really to do with the verbosity of the program. That's a separate issue. Since Cobol supports variables, it's distracting to include that in the argument about its verbosity.

"as coding by copy-and-paste-with-variations shows WHAT is happening but not WHY its happening."

True again. The point though of the site is to show various *features* of a language. As the comments point out, that's what this version does.

As to the Don't Repeat Yourself principle, Cobol supports that just fine. Libraries, User Defined Functions, Oop, Procedures, Copybooks are just a few of the methods Cobol uses to implement DRY.

The long and short is that your comment doesn't really (at all) answer our defenses against the verbosity claim. In any case, I'm not suggesting Cobol is not verbose, merely that it is not always as verbose as so many claim, and often is not much more verbose for a specific program, than the same program in another language (especially if those programs have the required comments).

@Zhrinze, you brought up all the points I just did, as well as some other very good ones.

@larry Pishioneri, True:)

@barry Thanks will try that.

@Bill Talbot first thank you for the props.

Now regarding these lines:

PERFORM VARYING Bottles FROM 99 BY -1 UNTIL Bottles = -1
DISPLAY SPACES
SUBTRACT 1 FROM Bottles GIVING Remaining-Bottles

The code does show the bottles in the form 99, 98, 97 etc with each iteration through the perform. The GIVING in the subtract line, places the result (99 - 1, 98 - 1 etc) into the Remaining-Bottles identifier while leaving Bottles unchanged. I did this so that we could have the Remaining-Bottles be exactly one less than the bottles.

And true about the verbosity. It's just amusing for me to see a lot of folks talk about how verbose a major Cobol program is, then when I look at their code in a "less verbose" language, it's larger than my Cobol programs.

@Jon true that. See my other comments:).

@MJP, what you said...

@Michael not sure what speedway is. Nice readable code though.

>>  Aoirthoir An Broc said on 08/26/09 04:51:46

Aoirthoir An Broc Alright, did a bit of tweaking to the program. While I wanted to show Reference Modification, and used it to eliminate the 0 from 01 through 09 bottles of beer, there is an easier way. There might be shorter versions available than this, but this trims it down pretty good. Keep in mind I chose to use descriptive Variable names, rather than shorter ones. So here you go:

IDENTIFICATION DIVISION.
PROGRAM-ID. 99-Bottles-of-Beer-On-The-Wall.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Counter PIC S99.
01 Remaining-Bottles PIC Z9.
01 Bottles PIC Z9.
PROCEDURE DIVISION.
PERFORM VARYING Counter FROM 99 BY -1 UNTIL Counter = -1
MOVE Bottles to Bottles
SUBTRACT 1 FROM Counter GIVING Remaining-Bottles
DISPLAY SPACES
EVALUATE Bottles
WHEN 0
DISPLAY "No more bottles of beer on the wall, "
"no more bottles of beer."
DISPLAY "Go to the store and buy some more, "
"99 bottles of beer on the wall."
WHEN 1
DISPLAY " 1 bottle of beer on the wall, "
" 1 bottle of beer."
DISPLAY "Take one down and pass it around, "
"no more bottles of beer on the wall."
WHEN 2 Thru 99
DISPLAY Bottles
" bottles of beer on the wall, "
Bottles
" bottles of beer."
DISPLAY "Take one down and pass it around, "
Remaining-Bottles
" bottles of beer on the wall."
END-EVALUATE
END-PERFORM
GOBACK.

>>  Aoirthoir An Broc said on 08/26/09 05:39:35

Aoirthoir An Broc Alright, I lose points (and a job?) for not checking my code before posting. Here is a compilable, working version. There might be shorter versions in Cobol, but I believe this trims it up to about as short as it can go.

http://pastebin.com/f1f628db6

>>  Alex Turner said on 10/02/09 15:43:10

Alex Turner COBOL has moved on, I recently got a COBOL for .net version accepted:
http://www.99-bottles-of-beer.net/language-micro-focus-cobol-for-.net-2173.html

>>  RCook said on 11/19/09 19:52:29

RCook The best thing to do is menove all those lines of code about BEER and add this:

Add GIN to Vermouth giving MARTINI

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: