Gewone variabelen
Arnout van Kempen over rommelen in een digitale wereld.
We hebben vorige keer al gebruik van normale variabelen gezien, in een voorbeeld om de werking van bestanden te tonen. Daarbij gebruikten we een wel heel specifieke soort, de level 88 variabele. Laten we nu wat grondiger kijken naar de WORKING-STORAGE SECTION.
Iedere variabele wordt in de DATA DIVISION gedefinieerd met dezelfde structuur:
Level nummer - variabele/record/veld naam - picture/type - startwaarde
Het level nummer geeft de mogelijkheid variabelen te structureren in groepen, ongeveer zoals een struct in C, of zoals records in een bestand geordend zijn. Daarvoor kunnen de levels 1 tot 49 worden gebruikt, maar in de praktijk gebruikt iedereen 1 en daarna veelvouden van 5. Een voorbeeld:
WORKING-STORAGE SECTION.
01 EMPLOYEE-RECORD.
05 EMPLOYEE-ID PIC 9(5).
05 EMPLOYEE-NAME.
10 FIRST-NAME PIC X(20).
10 LAST-NAME PIC X(20).
05 SALARY PIC 9(7)V99.
Groepsnamen die zelf geen waarde hebben, krijgen geen picture clause en ook de startwaarde is optioneel. De structuur lijkt me redelijk voor de hand liggend. Door in te springen wordt visueel duidelijker wat de samenhang is, maar de levels zorgen daar ook al netjes voor.
COBOL kent nog drie specifieke levels. Vorige week zagen we level 88 al, waarmee een waarde automatisch naar TRUE of FALSE gaat als de bovenliggende variabele een aangegeven waarde aanneemt. Level 66 wordt gebruikt om een nieuwe naam aan een al gedeclareerde variabele of groep variabelen te geven. Als je in bovenstaand voorbeeld een variabele NAAM zou willen toevoegen die bestaat uit de voornaam en de achternaam, dan zou je dat kunnen doen met
66 NAAM RENAMES FIRST-NAME THRU LAST-NAME.
Ten slotte hebben we nog het speciale level 77. Dit is niet veel in gebruik, omdat het eenvoudig kan worden vervangen door level 01. Alleen, een 01 variabele kan onderliggende levels hebben en 77 niet. Dus sommige programmeurs gebruiken 77 om daar duidelijk over te zijn.
De naam van een variabele kan bestaan uit hoofdletters, een - en een _, en als het computersysteem het aan kan (dus alle moderne computers) ook uit kleine letters. Zelf hou ik voor COBOL graag hoofdletters met - aan, maar wie liever de vormen uit C of Rust gebruikt, kan dat ook doen.
De picture clause is een beetje vreemd voor C of Rust programmeurs en eigenlijk zie je deze vorm in vrijwel geen enkele andere taal zo terug. Voor de liefhebbers, de picture clause lijkt een beetje op PRINT USING in Basic, of op de coderingen die je bij printf of println! gebruikt in C of Rust. Maar daar formatteert het alleen de output, terwijl in COBOL het hele type zo wordt vastgelegd. COBOL is daarbij niet lastig als types verschillen, zolang het ene type maar in het andere past, werkt COBOL wel mee.
De type definitie, ofwel de picture clause, is behoorlijk complex. COBOL kent floating point getallen, allerlei vrij exotische formaten en voor de echte liefhebber zelfs pointers. Maar ik zal me beperken tot de 'normale' getallen en strings. Deze hebben de volgende vorm:
PIC, gevolgd door een beschrijving van het uiterlijk van de mogelijke waarde van de variabele. Dit doe je met:
9 voor cijfers, maximaal 18. Niet voor getallen, maar voor cijfers!
X voor alfanumerieke tekens, dus letters en cijfers, maximaal 255.
A voor letters, ook weer maximaal 255.
Na deze tekens kan je tussen haakjes aangeven hoeveel tekens de variabele kan bevatten, maar je mag de tekens ook na elkaar zetten. Verder kan je een picture beginnen met S voor een plus- of min-teken. Je kan daarbij kiezen of een minteken voor of na het getal komt met SIGN LEADING of SIGN TRAILING. Een PIC S9(4) SIGN TRAILING kan dus een waarde van 1234- bevatten.
Wil je decimalen achter de komma gebruiken, dan doe je dat met V of P. In beide gevallen wordt intern geen punt opgeslagen, maar bij invoer en uitvoer wordt die wel gebruikt. Het gaat hier dus om een vaste komma (punt), zoals administratief gebruikelijk is, en geen drijvende komma zoals wiskundig gebruikelijk is. Het grootste verschil tussen P en V is dat de V een positie aangeeft, terwijl P cijfers 0 toevoegt om tot het gewenste formaat te komen. In de praktijk hebben beide opties zo hun voor- en nadelen. Met de value clause kan je tenslotte een startwaarde meegeven. Een variabele die een bedrag zal bevatten met als startwaarde 100 en dat ook negatief kan zijn, met minteken achter het getal, ziet er dan bijvoorbeeld zo uit: PIC S9(7)V99 SIGN TRAILING VALUE 100.00
Let op, had ik VALUE 100 gebruikt, dan was de startwaarde 1.00 geweest. COBOL wil immers de twee cijfers achter de komma gebruiken en intern bestaat de komma niet. Nu die niet expliciet is opgegeven, plaatst COBOL die zelf.
Is dit systeem al raar in vergelijking met C of Rust, het lijkt wel sterk op wat Excel doet met het formatteren van cellen. Weliswaar is daar de interne representatie niet anders, maar als je in Excel een cel definieert met een soort picture, dan is dat wel wat je zal zien; wat je er ook mee doet.
COBOL geeft nog een interessante, ietwat vreemde mogelijkheid. Omdat je teken voor teken een picture beschrijft, kan dat best bestaan uit tekens die op het eerste gezicht niet samen gaan. Cijfers en letters in één "getal". Toch kennen we dat wel, bijvoorbeeld in een postcode. Dat zou zo kunnen:
01 POSTCODE PIC 9(4)X(1)A(2)
Hierin past precies een Nederlandse postcode: 4 cijfers, een spatie, twee letters. Overigens zal je in je procedure moeten regelen dat het vijfde teken altijd een spatie is, bijvoorbeeld met
IF POSTCODE (5:1) NOT = SPACE
MOVE SPACE TO POSTCODE (5:1)
END-IF.
En als je het net als ik slordig vindt als de postcode kleine letters bevat, dan los je dat simpel op met
MOVE FUNCTION UPPER-CASE(POSTCODE) TO POSTCODE.
We zagen eerder dat de DATA DIVISION vier secties kent die allemaal op deze manier werken, maar met verschil in waar data wordt gebruikt en hoe. Files, working storage, lokale variabelen en linken van variabelen naar andere programma-modules zijn verschillend, maar ze werken alle vier met deze types, picture clauses en value clauses.
Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op github.com en zoek naar Abmvk/kmc. Het account Abmvk volgen kan ook. Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren.
Gerelateerd
En arrays dan?
Arnout van Kempen over rommelen in een digitale wereld.
Typecasting in COBOL
Arnout van Kempen over rommelen in een digitale wereld.
Bestanden in soorten en maten
Arnout van Kempen over rommelen in een digitale wereld.
Alles draait om data
Arnout van Kempen over rommelen in een digitale wereld.
Omgeving: input-output
Arnout van Kempen over rommelen in een digitale wereld.