I'm making the "99 Bottles" program, but with user input on how many to take down. I'm very new to COBOL and I'm definitely overlooking something simple or just completely thinking about this the wrong way.
The following is what I currently have:
IDENTIFICATION DIVISION.
PROGRAM-ID. HW.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 COUNTER PIC S99.
01 BOTTLES PIC Z9.
01 BOTTLES-REMAINING PIC Z9.
01 NUM PIC s9(02) VALUE 0.
PROCEDURE DIVISION.
PERFORM VARYING COUNTER FROM 99 BY NUM UNTIL COUNTER = 0
DISPLAY "How many bottles would you like to take down?"
ACCEPT NUM
MOVE COUNTER to Bottles
subtract NUM FROM COUNTER GIVING BOTTLES-REMAINING
DISPLAY SPACES
EVALUATE COUNTER
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, "
BOTTLES-REMAINING
" bottles of beer on the wall."
END-EVALUATE
END-PERFORM
GOBACK.
I need to make the NUM clause negative in the following statement (or the data division) so it will subtract from the counter:
PERFORM VARYING COUNTER FROM 99 BY NUM UNTIL COUNTER = 0
I see a few issues here.
First, and this is from admittedly faded memory, but I seem to recall that the VARYING
clause required a constant value for the delta. I don't think you can use an actual changing NUM
to do this.
So your loop would be better off not using the VARYING
clause and instead be something like (code here may not be syntactically correct COBOL, it's meant more to show intent and/or method):
set counter to 99
perform until counter = 0
blah blah blah then change counter
end perform
Second, your little ditty doesn't make sense any more if you're allowed to remove more than one bottle at a time. The statements for the third stanza of the rhyme should be modified similarly to the bottles-left stanza:
evaluate num
when 1
display "Take one down and pass it around, "
when 2 thru 99
display "Take ", num, " down and pass them around, "
end evaluate
And, finally, you probably want to avoid the situation where you remove more bottles than you have available (or less than one, for that matter). That can be done by silently enforcing those limits (clamping) immediately after getting the user input:
accept num
if num is less than one
set num to one
end if
if num is greater than counter
set num to counter
end if
You could also complain and require the user to enter a valid quantity but the easiest solution is probably just to clamp it.