Check is a checkbook management program that tracks debits, credits, check fees, and tax-deductible entries across a user-configurable file of 100 to 500 records. It stores transaction data in parallel arrays: date strings in D$(), check numbers in c(), payee/payer names in N$(), amounts in s(), and tax-deductibility flags in Z(). The statement routine displays up to five transactions at a time centered on the most recent entry, calculates a running balance, and flags overdrafts with an “OD” marker. When the file fills completely, a compaction routine retains the last 10 entries, carries forward the accumulated balance into a reset variable, and renumbers from entry 11 onward. Printer output is handled via OPEN #2,"p" and CLOSE #2 stream I/O, printing a formatted statement with balance and optional tax-deductible totals.
Program Structure
The program is organized into clearly labeled sections separated by REM statements. Control flow is largely handled by a central menu dispatcher at line 280, stored in the variable menu and reached via GO TO menu throughout. The main sections are:
- Lines 10–150: Initialization — dimension arrays, set defaults, branch to menu
- Lines 160–210: Date print subroutine
- Lines 220–270: Dollar/cents formatting subroutine
- Lines 280–490: Menu and dispatch loop
- Lines 500–760: Debit entry routine
- Lines 770–980: Credit entry routine
- Lines 990–1390: On-screen statement and review
- Lines 1400–1610: File-full compaction routine
- Lines 1620–2030: LPRINT (printer) statement routine
- Line 2040: Final
CLEAR/SAVE(never reached during normal execution)
Data Storage
All transaction data is held in parallel arrays dimensioned at startup based on user-supplied cx (100–500):
| Array | Type | Content |
|---|---|---|
D$(cx,4) | String | Date as 4-character string (MMDD) |
c(cx) | Numeric | Check number (0 = credit) |
N$(cx,15) | String | Payee or payer name (up to 15 chars) |
s(cx) | Numeric | Amount (negative = debit) |
Z(cx) | Numeric | Tax-deductible flag (0 or 1) |
The variable i tracks the current number of entries; j is used as the working index into all arrays for a given transaction.
Date Formatting
Dates are stored as 4-character strings in MMDD format (e.g., "0819" for August 19). The print date subroutine at lines 160–210 suppresses leading zeros by checking whether the first or third character is "0" before printing it. The year is stored globally in a$ (e.g., "/85") and appended at line 200, so changing the year via the “yr” menu option updates all subsequently printed dates without touching stored data.
Dollar/Cents Formatting
The subroutine at lines 220–270 uses INT ABS s(j) for the whole-dollar part and computes cents as INT(100 * ABS s(j) - 100 * INT ABS s(j) + 0.5), adding 0.5 before truncating to round correctly. A leading zero is printed for cent values of 9 or less (lines 250–260). This subroutine is reused for both screen display and printer output, as well as for the balance line and tax-deductible total.
Check Fee Handling
An optional per-check fee (cf) is subtracted from each debit entry at line 670. The fee is stored as a dollar amount and its cent value is reconstructed inline using cf*100 fed into the GO SUB 250 zero-padding test. The fee is also excluded when computing tax-deductible totals: line 1220 subtracts cf from the absolute amount before accumulating into tax.
Statement and Review
The on-screen statement (lines 990–1390) finds the highest populated entry by scanning backward from cx to the first non-zero s(k) value (lines 1040–1060), then displays a window of five entries from q-4 to q (lines 1070–1170). The user can jump to any entry by typing a number; line 1380 limits direct navigation to entries 1–200. The balance line (lines 1240–1280) uses a separately computed t$ string for alignment, with cents extracted from a fresh ABS total calculation.
File Compaction
When the file reaches capacity (i=cx), the compaction routine at lines 1460–1610 copies the last 10 entries to positions 1–10 in all five arrays, clears entries 11 through cx, and stores the accumulated balance of the dropped entries in reset. Subsequently, the total routine initializes total=reset (line 1190) so the balance carries forward correctly across compactions.
Printer Output
The LPRINT routine (lines 1620–2030) uses OPEN #2,"p" and CLOSE #2 for stream-based printer output. The current value of j is saved into p at line 1730 and restored at line 1880 so the shared subroutines at lines 160 and 220 (which use j) do not corrupt the caller’s loop state. The printer routine recalculates total and tax independently from scratch rather than relying on previously computed values.
Notable Techniques and Idioms
LET reset=Iat line40initializesresetto zero using the already-set variablei, saving a literal.- The menu target is stored in
LET menu=280(line110), allowingGO TO menuthroughout — a common BASIC idiom for maintainability. f$= CHR$ 18+ CHR$ 1(line40) builds a flash-attribute control sequence used repeatedly to highlight labels on screen.- Line
400usesINPUT ... LINE y$for case-sensitive string input, with a special check for"STOP "(with trailing space) to allow graceful termination. - Correction handling in both debit (line
730) and credit (line950) routines simply re-enters the entry loop at the PRINT header, reusing the samej=iindex — effectively overwriting the current slot. - Line
2040(CLEAR :SAVE "CHECK" LINE 10) exists outside normal program flow and acts as a development/reset utility line.
Bugs and Anomalies
- Line
730: The correction branch (y$="cor") goes to line520(PRINT header) without decrementingi, soiwas already incremented at line510. Re-entering via520reuses the samej, so data is overwritten correctly, butiis not re-incremented — this works only becausej=iwas set at line510andjis not reset on the correction path. - Line
1380: Navigation is capped at entry 200 regardless ofcx, so if the user setcxabove 200, entries 201 onward cannot be directly accessed via the review input. - Lines
1280and2000: The\\{16}\\{0}token precedingtaxsuggests anINK 0attribute control code has been embedded before the variable name, likely a display artifact that may interfere with the conditional evaluation depending on interpreter handling. - The credit entry routine (lines 770–980) does not set
z(j)=0or prompt for tax-deductibility, so credit entries always have whatever value was previously inZ(j)— likely zero from array initialization, but potentially non-zero after a compaction that reused the slot.
Source Code
10 REM \{20}\{1}"check" by James DuPuy\{20}\{0}
20 REM \{20}\{1}10/21/84 Version 1.3 \{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}
30 INK 0:PAPER 7:BORDER 1:CLS
40 LET i=0:LET reset=I:LET cf=I:LET f$= CHR$ 18+ CHR$ 1
50 PRINT "Enter number of total files to be kept in this program."''"You must enter 100-500 and it should be about what you would use in a year or a given time orperiod of use. Also bear in mind that the more files there are, the longer it will take to save and load.":INPUT cx
60 IF cx<100 OR cx>500 THEN INPUT F$;"Enter 100-500 only! ";cx:GO TO 60
70 DIM D$(CX,4):DIM c(cx)
80 DIM N$(CX,15):DIM s(cx)
90 DIM Z(cx)
100 LET tax=0
110 LET menu=280
120 LET total=0
130 LET a$="/85"
140 LET k=0
150 GO TO menu
160 REM \{20}\{1}PRINT DATE ROUTINE\{20}\{0}
170 IF d$(j,1) <>"0" THEN PRINT D$(J,1);
180 PRINT d$(j,2);"/";
190 IF d$(j,3) <>"0" THEN PRINT D$(J,3);
200 PRINT d$(j,4);a$
210 RETURN
220 REM \{20}\{1}DOLLARS/CENTS ROUTINE\{20}\{0}
230 PRINT "$"; INT ABS s(j);".";
240 LET cents= INT (100* ABS s(j)-100* INT ABS s(j)+.5)
250 IF cents <=9 THEN PRINT "0";
260 PRINT cents;
270 RETURN
280 REM \{20}\{1}MENU ROUTINE\{20}\{1}\{20}\{0}
290 BORDER 6:BRIGHT 1:POKE 23609,20
300 CLS
310 PRINT AT 1,7;F$;"CHECK BOOK PROGRAM"
320 PRINT
330 PRINT TAB 9;"for the year 19";a$(2 TO 3)
340 PRINT AT 5,2;"CR - FOR CREDIT ENTRY"''" DB - FOR DEBIT ENTRY"
350 IF I <>0 THEN PRINT AT 9,2;"ST - FOR STATEMENT"''" PR - TO LPRINT STATEMENT"''" SV - TO SAVE PROGRAM & DATA"; AT 14,7;"BACK ON TO TAPE"
360 PRINT AT 16,2;"YR - TO CHANGE YEAR"
370 IF i=cx-1 THEN PRINT AT 18,2;F$;"LAST ENTRY BEFORE FULL FILE!"
380 PRINT AT 18,2;"CF - TO ENTER CHECK FEE.(";cf;")"
390 PLOT 0,0:DRAW 255,0:DRAW 0,175:DRAW -255,0:DRAW 0,-175
400 INPUT "Enter choice in lower case:"; LINE Y$:IF y$="STOP " THEN STOP
410 CLS
420 IF Y$="yr" THEN INPUT "Enter new year as (84):"; LINE a$:LET a$="/"+a$
430 IF y$="cf" THEN INPUT "Enter check fee:";cf
440 IF y$="pr" THEN GO SUB 1620
450 IF y$="cr" THEN GO TO 770
460 IF y$="db" THEN GO TO 500
470 IF y$="st" THEN GO TO 990
480 IF y$="sv" THEN SAVE "check" LINE 280
490 GO TO 280
500 REM \{20}\{1}DEBIT ENTRY\{20}\{0}
510 LET i=i+1:LET j=i
520 PRINT AT 2,6;F$;"*** DEBIT ENTRY ***"
530 PRINT AT 5,0;"DATE: ";
540 INPUT "DATE? (0819)no \{20}\{1}/\{20}\{0} or year:"; LINE z$:IF LEN z$ <>4 THEN GO TO 540
550 LET d$(j)=z$
560 GO SUB 160
570 PRINT
580 PRINT AT 7,0;"CHECK NUMBER: ";
590 INPUT "\{20}\{0}Enter CHECK # :";c(j):PRINT c(j)
600 PRINT AT 9,0;"PAYEE: ";
610 INPUT "Name?:"; LINE z$:IF z$="" THEN GO TO 610
620 LET n$(j)=z$
630 PRINT n$(j)
640 PRINT AT 11,0;"AMOUNT: ";
650 INPUT "Amount? :";s(j)
660 LET s(j)=-s(j):GO SUB 220
670 IF cf>0 THEN LET s(j)=s(j)-cf:PRINT :PRINT "+ .";:LET cents=cf*100:GO SUB 250:PRINT " Fee= ";:GO SUB 220:PRINT " TOTAL"
680 LET z(j)=0:INPUT F$;"Tax Deductable?(Y/\{20}\{1}ENT\{20}\{0}) :";y$:IF y$="y" OR y$="Y" THEN LET Z(j)=1:PRINT AT 14,10;F$;"TAX DEDUCTABLE"
690 FOR n=1 TO 60:NEXT n
700 PRINT AT 18,0;"ENTER (DB) FOR ANOTHER DEBIT,","ENTER (COR) FOR CORRECTION,","PRESS \{20}\{1}ENTER\{20}\{0} FOR MENU."
710 INPUT "Enter in lower case:"; LINE y$:IF y$="c" THEN COPY
720 CLS
730 IF y$="cor" THEN GO TO 520
740 IF i=cx THEN GO TO 990
750 IF y$="db" THEN GO TO 500
760 GO TO menu
770 REM \{20}\{1}CREDIT ENTRY\{20}\{0}
780 LET i=i+1:LET j=i
790 PRINT AT 2,6;F$;"*** CREDIT ENTRY ***"
800 PRINT AT 5,0;"DATE: ";
810 INPUT "DATE? (0819)no \{20}\{1}/\{20}\{0} or year:"; LINE z$:IF LEN z$ <>4 THEN GO TO 810
820 LET d$(j)=z$
830 GO SUB 160
840 PRINT
850 PRINT AT 7,0;"PAYER: ";
860 INPUT "Name?:"; LINE z$:IF z$="" THEN GO TO 860
870 LET n$(j)=z$
880 PRINT n$(j)
890 PRINT AT 9,0;"AMOUNT: ";
900 INPUT "Amount? ";s(j)
910 GO SUB 220
920 PRINT AT 18,0;"ENTER (COR) FOR CORRECTION","ENTER (CR) FOR ANOTHER CREDIT","PRESS \{20}\{1}ENTER\{20}\{0} FOR MENU"
930 INPUT "Enter in lower case:"; LINE y$:IF y$="c" THEN COPY
940 CLS
950 IF y$="cor" THEN GO TO 790
960 IF i=cx THEN GO TO 990
970 IF y$="cr" THEN GO TO 770
980 GO TO menu
990 REM \{20}\{1}STATEMENT ROUTINE\{20}\{0}
1000 CLS
1010 PRINT AT 0,7;F$;"**** STATEMENT****"
1020 IF cf>0 THEN PRINT "Check fee is included in amount.":GO TO 1040
1030 PRINT
1040 FOR k=cx TO 1 STEP -1
1050 IF s(k)=0 THEN NEXT k
1060 LET q=k
1070 FOR j=q-4 TO q
1080 IF j<1 THEN NEXT j
1090 GO SUB 160
1100 IF c(j)=0 THEN PRINT :GO TO 1130
1110 IF z(j) THEN PRINT TAB 10;"CHECK #: ";c(j);" ";F$;"\{20}\{1}TD\{20}\{0}":GO TO 1130
1120 PRINT TAB 10;"CHECK #: ";C(J)
1130 PRINT " ";n$(j); TAB (24- LEN STR$ INT ABS s(j));
1140 GO SUB 220
1150 IF S(J)>0 THEN PRINT "CR";
1160 PRINT
1170 NEXT J
1180 REM \{20}\{1}TOTAL ROUTINE\{20}\{0}
1190 LET total=reset:LET tax=reset
1200 FOR t=1 TO k
1210 LET total=total+s(t)
1220 IF z(t) THEN LET tax=tax+(ABS s(t))-cf
1230 NEXT t
1240 LET cents= INT (100*(ABS total- INT ABS total)+.5)
1250 LET t$= STR$ INT (ABS total)
1260 PRINT AT 18,0;"\{20}\{1}BALANCE:\{20}\{0}$";T$;".";:GO SUB 250
1270 IF total<0 THEN PRINT "\{20}\{1}*OD\{20}\{0}";
1280 IF \{16}\{0}tax <>0 THEN LET t$= STR$ INT (tax):LET cents= INT (100*(tax- INT tax)+.5):PRINT ":\{20}\{1}TD:\{20}\{0}$";t$;".";:GO SUB 250
1290 PRINT AT 19,0;"LAST ENTRY:";q
1300 IF i=cx-1 THEN PAUSE 100:PRINT AT 19,0;F$;"FINAL ENTRY BEFORE FULL FILE"
1310 PRINT AT 20,0;"Enter number to review, ENTER"; AT 21,0;"for menu, C to copy."
1320 IF i=cx THEN PAUSE 100:PRINT AT 21,0;F$;"File Full:\{20}\{1}ENTER\{20}\{0} to Renumber"
1330 INPUT "Enter in lower case(#,C):";y$
1340 IF y$="c" THEN COPY :GO TO 1330
1350 CLS
1360 IF y$="" AND i=cx THEN GO TO 1400
1370 IF CODE y$<48 OR CODE y$>57 THEN GO TO menu
1380 IF VAL y$ >=1 AND VAL y$<201 THEN LET q= VAL y$:GO TO 1070
1390 CLS :GO TO menu
1400 PRINT F$;"FILE IS NOW FULL."
1410 PRINT AT 6,0;"\{20}\{1}ENTER\{20}\{0} - to dump all but last"'"10 entries."
1420 PRINT AT 9,0;"MU - for menu"; AT 11,0;"PR - to print out all ";cx;" checks"
1430 INPUT y$:IF y$="" THEN PAUSE 60:INPUT "Are you sure?(Y/N):"; LINE y$:IF y$="n" THEN GO TO 1430
1440 IF y$="mu" THEN GO TO menu
1450 IF y$="pr" THEN LET u=1:GO SUB 1730:CLS :GO TO 1400
1460 LET t2=0
1470 FOR j=cx-9 TO cx
1480 LET d$(j-(cx-10))=d$(j)
1490 LET c(j-(cx-10))=c(j)
1500 LET n$(j-(cx-10))=n$(j)
1510 LET s(j-(cx-10))=s(j)
1520 LET t2=t2+s(j)
1530 NEXT j
1540 LET reset=total-t2
1550 FOR j=11 TO cx
1560 LET d$(j)=""
1570 LET c(j)=0
1580 LET n$(j)=""
1590 LET s(j)=0
1600 NEXT j
1610 LET i=10:CLS :GO TO 990
1620 REM \{20}\{1}\{20}\{1}LPRINT ROUTINE\{20}\{0}
1630 CLS
1640 PRINT F$;" STATEMENT TO PRINTER",
1650 PRINT AT 3,0;"MU - for menu"; AT 5,0;"ALL - to print entire file."; AT 7,0;"1-";cx;" - to print out from that number to present."
1660 PRINT AT 18,0;"Enter choice in lower case."
1670 INPUT y$:IF y$="" THEN GO TO 1620
1680 IF y$="mu" THEN GO TO menu
1690 IF y$="all" THEN LET u=1:GO TO 1730
1700 IF CODE y$<48 OR CODE y$>57 THEN GO TO 1620
1710 LET u= VAL y$
1720 IF s(u)=0 THEN PRINT AT 20,0;"There are no files at ";u'"Please reenter.":PAUSE 120:GO TO 1620
1730 LET p=j:OPEN #2,"p"
1740 PRINT "\{20}\{1}********** STATEMENT ***********\{20}\{0}":PRINT
1750 IF cf>0 THEN PRINT "Check fee is included in amount.":PRINT
1760 FOR j=u TO i
1770 IF s(j)=0 THEN GO TO 1860
1780 GO SUB 160
1790 IF c(j)=0 THEN PRINT :GO TO 1820
1800 IF z(j) THEN PRINT TAB 10;"CHECK #: ";c(j);" ";"\{20}\{1}TD\{20}\{0}":GO TO 1820
1810 PRINT TAB 10;"CHECK #: ";c(j)
1820 PRINT " ";n$(j); TAB (24- LEN STR$ INT ABS s(j));
1830 GO SUB 220
1840 IF s(j)>0 THEN PRINT "CR";
1850 PRINT
1860 NEXT j
1870 PRINT :PRINT
1880 LET j=p
1890 LET total=0
1900 LET tax=0
1910 FOR t=1 TO i
1920 IF s(t)=0 THEN GO TO 1950
1930 IF z(t) THEN LET tax=tax+(ABS s(t))-cf
1940 LET total=total+s(t)
1950 NEXT t
1960 LET cents= INT (100*(ABS total- INT ABS total)+.5)
1970 LET t$= STR$ ABS INT total
1980 PRINT "\{20}\{1}\{20}\{0}\{20}\{0}\{20}\{1}BALANCE :\{20}\{0} $\{20}\{0}";T$;".";:GO SUB 250
1990 IF TOTAL<0 THEN PRINT "\{20}\{1}*OD\{20}\{0}"
2000 IF \{16}\{0}tax <>0 THEN LET t$= STR$ INT (tax):LET cents= INT (100*(tax- INT tax)+.5):PRINT "\{20}\{1}TAX DEDUCTABLE \{20}\{0} $";t$;".";:GO SUB 250
2010 PRINT '''''
2020 CLOSE #2
2030 RETURN
2040 CLEAR :SAVE "CHECK" LINE 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

