BUDGET

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Finance, Home

BUDGET is a personal finance tracking program that manages multiple named budget accounts across a 12-month calendar year. It stores account names in a two-dimensional string array and dollar figures in a two-dimensional numeric array, using a shared subroutine (lines 10–38) to format monetary values with a decimal point inserted two places from the right. The menu system offers seven options including summary views, per-account detail with running balances, data entry for spending or credits, budget figure changes, account renaming, and tape/disk save. A substring search routine (line 5000) lets users locate accounts by partial name match, scanning all positions within each stored name.


Program Structure

The program is organized into clearly delineated sections, each starting at a round line number. A GO TO 1000 at line 5 skips past the utility subroutines and data-entry initialization to the main menu after a save/reload. The initialization block (lines 100–615) runs only on first launch and collects the budget item count, names, and monthly amounts before branching to the menu.

LinesSection
10–38Currency formatting subroutine (GOSUB target stored in G)
100–615Initialization: constants, data entry, first totals display
1000–1140Main menu
1500–1920Account summary (all accounts + monthly totals)
2000–2400Per-account detail with monthly and cumulative balances
2500–2710New information entry (spending or credits)
3000–3205Change a budgeted amount
3500–3580Rename an account
4000–4050Save to tape/disk
4500–4560Exit with confirmation
5000–5130Account search subroutine (GOSUB target stored in L)
9898–9899STOP / safety net

Subroutine Address Variables

Rather than hard-coding GOSUB destinations, the program stores two subroutine line numbers in numeric variables set during initialization: G=10 (currency formatter) and L=5000 (account search). All calls throughout the program use GO SUB G and GO SUB L. Similarly, the menu return address is stored in S=1000 and used as GO TO S or GO TO S+ VAL X$. This makes the code compact and means relocating a subroutine only requires changing the initialization constant.

Currency Formatting (Lines 10–38)

The shared formatter converts a floating-point value in M to a display string in M$. It multiplies by 100, rounds with INT(M*100+.5), converts to string with STR$, then splices in a period two characters from the right end. A special case at line 14 forces M$="000" when the value is zero so the splice always finds enough characters. Negative values pass through, but lines 20–26 contain a loop that applies CHR$(CODE(M$(Z))) to each character — a no-op transformation that appears to be vestigial code intended to produce inverse video but has no effect in this context.

Data Storage Arrays

  • N$(N1,15) — account names, 15 characters each; positions 1–2 hold a zero-padded index number and position 4 onward holds the user-supplied name.
  • D(N1,13) — numeric data per account; column 1 is the monthly budget, columns 2–13 are January through December actual spending.
  • T(14) — column totals; entries 1–13 mirror the D column structure, and entry 14 accumulates the total of all monthly totals.
  • S(N1) — row sums (total spent per account) computed in the summary section.

Note that T(14) is dimensioned at line 340 during initialization and then re-dimensioned at line 1525 inside the summary routine. This re-dimensioning resets all values to zero, which is the intended way to clear totals before recalculating.

Menu Dispatch

The main menu at line 1000 uses a PAUSE F / INKEY$ idiom (F=40000, a very long pause) to wait for a keypress. Choices “1” through “7” are checked with explicit IF X$=... THEN GO TO chains. An ON ERR GO TO 1000 at line 1135 traps any errors, and line 1140 uses GO TO S+ VAL X$ as a computed jump — since S=1000, pressing “1” would jump to line 1001, but that line does not exist; the explicit checks above intercept all valid keys before reaching this line, so it only fires for unexpected input.

Account Search Subroutine (Lines 5000–5130)

The search at line 5000 performs a sliding-window substring match. It accepts a partial name from the user, then iterates over every account and every starting position within the 15-character name field, comparing a substring of length LEN Y$. On a match it sets Y=I (account index) and Y$=N$(I) (full name), clears the screen, and returns. An empty input at line 5021 redirects to line 1E3 (the menu), demonstrating use of VAL-style numeric literals in a GO TO.

Month Name Encoding

All twelve month abbreviations are packed into a single string O$="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" at line 100. Month n (1-based, where 1=January) is extracted with O$((n-1)*3+1 TO (n-1)*3+3). In the detail and summary displays, months are indexed as columns 2–13 of D, so the extraction formula typically appears as O$((I-2)*3+1 TO (I-2)*3+3).

Balance Display Logic

Throughout the summary and detail sections, balances are printed with an explicit “+” or an inverse-video “−” prefix depending on the sign of M. The currency formatter strips any leading minus sign produced by STR$ and the sign character is prepended separately, allowing consistent right-alignment of the numeric portion via TAB(N- LEN M$).

Notable Anomalies

  • Lines 22–26 loop through M$ applying CHR$(CODE(M$(Z))), which is an identity operation and has no visible effect. The original intent may have been to invert the display of negative amounts using an offset to the inverse character set, but as written it is a no-op.
  • At line 605, the monthly total T is passed to the formatter and printed as an annual figure without multiplying by 12. The label says “TOTAL REQUIRED PER YEAR” but the value displayed is the same as the monthly total computed three lines earlier — an apparent bug.
  • Line 1520 dimensions S(N1) using the variable name S, which shadows the menu return-address variable S=1000. After this point S is an array, so subsequent GO TO S calls would fail. However, GO TO S within the summary section uses the bare variable which at that stage refers to the numeric value 1000 set at line 160 — the DIM statement creates a separate array S() while leaving the scalar S intact in Spectrum BASIC, so in practice this works correctly.
  • The exit routine at line 4560 directs the user to type GOTO 1000 manually and branches to line 9898 (STOP), providing a way back into the running program without re-executing initialization.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM "BUDGET"
    5 GO TO 1000
   10 LET M= INT (M*100+.5)
   12 LET M$= STR$ M
   14 IF M=0 THEN LET M$="000"
   16 LET M$=M$( TO LEN M$-2)+"."+M$(LEN M$-1 TO )
   18 IF VAL M$ >=0 THEN GO TO 38
   20 LET M$=M$(2 TO )
   22 FOR Z=1 TO LEN M$
   24 LET M$(Z)= CHR$ (CODE M$(Z))
   26 NEXT Z
   38 RETURN 
  100 LET O$="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
  110 PRINT "\{20}\{1}ENTER THE NUMBER OF BUDGET ITEMS\{20}\{0}"
  120 INPUT N1
  130 PRINT N1
  140 LET L$="\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
  150 LET C$="                                "
  160 LET S=1E3
  170 LET G=10
  180 LET L=5E3
  190 LET F=4E4
  200 LET E=21
  210 LET D$="NEW TAPE"
  250 PRINT "\{20}\{1}ENTER THE NAME OF THIS PROGRAM  \{20}\{0}"
  260 INPUT Q$
  270 IF LEN Q$ <=32 THEN GO TO 300
  280 PRINT "THE NAME IS TOO L O N G . . ."
  290 GO TO 260
  300 PRINT Q$
  310 PRINT "NOW WE WILL ENTER THE NAMES AND AMOUNTS OF EACH BUDGET ITEM..."
  315 REM ***** NAME OF ACCTS*****
  320 DIM N$(N1,15)
  325 REM ***DOLLAR FIGURES***
  330 DIM D(N1,13)
  335 REM ***COLUMN TOTALS***
  340 DIM T(14)
  345 REM ***ROW TOTALS***
  350 FOR I=1 TO N1
  360 PRINT "NAME OF BUDGET ITEM NUMBER ";I;":"
  370 IF I<10 THEN LET N$(I, TO 2)="0"+ STR$ I
  380 IF I >=10 THEN LET N$(I, TO 2)= STR$ I
  390 INPUT N$(I,4 TO )
  410 PRINT N$(I)
  430 PRINT "ENTER MONTHLY BUDGET AMOUNT:"
  440 INPUT D(I,1)
  450 LET M=D(I,1)
  460 GO SUB G
  480 PRINT "$";M$
  500 NEXT I
  510 LET T=0
  520 FOR I=1 TO N1
  530 LET T=T+D(I,1)
  540 NEXT I
  550 CLS 
  560 PRINT "TOTAL BUDGET REQUIRED PER MONTH:"
  570 LET M=T
  575 GO SUB G
  580 PRINT "$";M$
  600 PRINT "TOTAL REQUIRED PER YEAR:"
  605 GO SUB G
  610 PRINT "$";M$
  615 PAUSE 250
 1000 REM ***MENU***
 1002 CLS 
 1005 BORDER 2
 1020 PRINT AT 1,1;Q$
 1030 PRINT TAB 1;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
 1040 PRINT AT 3,2;"1: SUMMARY OF ALL ACCOUNTS"
 1050 PRINT AT 5,2;"2: DETAILS OF ONE ACCOUNT"
 1060 PRINT AT 7,2;"3: ENTER NEW INFORMATION"
 1070 PRINT AT 9,2;"4: CHANGE A BUDGETED AMOUNT"
 1080 PRINT AT 11,2;"5: CHANGE/CORRECT THE NAME OF"; TAB 5;"ACCOUNT"
 1085 PRINT AT 14,1;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
 1090 PRINT AT 15,2;"6: SAVE THE DATA"
 1100 PRINT AT 17,2;"7: EXIT THE PROGRAM"
 1101 PRINT AT 19,1;"\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
 1105 PRINT TAB 2;"LAST UPDATE: ";D$
 1110 PAUSE F
 1120 LET X$= INKEY$
 1122 IF X$="1" THEN GO TO 1500
 1124 IF X$="2" THEN GO TO 2000
 1126 IF X$="3" THEN GO TO 2500
 1128 IF X$="4" THEN GO TO 3000
 1130 IF X$="5" THEN GO TO 3500
 1132 IF X$="6" THEN GO TO 4000
 1134 IF X$="7" THEN GO TO 4500
 1135 ON ERR GO TO 1000
 1136 CLS 
 1140 GO TO S+ VAL X$
 1500 REM ***SUMMARY***
 1502 CLS 
 1503 PRINT AT 7,12;"SUMMARY"
 1504 PRINT 
 1505 PRINT INK 2; AT 11,9;"ADDING TOTALS"
 1506 PAUSE 100
 1520 DIM S(N1)
 1525 DIM T(14)
 1530 FOR I=1 TO N1
 1535 FOR J=2 TO 13
 1540 LET S(I)=S(I)+D(I,J)
 1545 NEXT J
 1550 NEXT I
 1560 FOR I=1 TO 13
 1565 FOR J=1 TO N1
 1570 LET T(I)=T(I)+D(J,I)
 1575 NEXT J
 1580 IF I>1 THEN LET T(14)=T(14)+T(I)
 1585 NEXT I
 1587 CLS 
 1600 FOR I=1 TO N1 STEP G
 1605 FOR J=0 TO 9
 1610 IF J=0 THEN PRINT AT 0,0;"\{20}\{1}ANNUAL BUDGET    SPENT TO DATE  \{20}\{0}"
 1615 IF J+I>N1 THEN GO TO 1680
 1620 PRINT N$(J+I)
 1630 PRINT TAB 6;"$";
 1635 LET M=12*D(I+J,1)
 1640 GO SUB G
 1645 PRINT TAB (15- LEN M$);M$,"   $";
 1650 LET M=S(I+J)
 1655 GO SUB G
 1660 PRINT TAB (28- LEN M$);M$
 1670 NEXT J
 1680 PRINT AT E,0;"\{20}\{1}\{20}\{0}\{20}\{1}'Z'=COPY  'C'=CONTINUE  'M'=MENU\{20}\{0}"
 1690 PAUSE F
 1695 LET X$= INKEY$
 1700 IF CODE X$=118 OR X$="M" THEN GO TO S
 1705 IF X$="Z" THEN PRINT AT 21,0;"                                "
 1710 IF X$="Z" THEN COPY 
 1715 IF X$="Z" THEN GO TO 1680
 1720 CLS 
 1725 NEXT I
 1730 PRINT "\{20}\{1}MONTHLY  BUDGET \{20}\{0} $";
 1735 LET M=T(1)
 1740 GO SUB G
 1745 PRINT M$
 1750 PRINT 
 1755 PRINT "SPENT IN"; TAB 12;"AMOUNT"; TAB 20;"""+""=BALANCE"; TAB 0;"MONTH OF"; TAB 12;"SPENT"; TAB 20;"""\{20}\{1}-\{20}\{0}""=DEFICIT"
 1757 PRINT "\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.."
 1760 FOR I=2 TO 13
 1765 LET M=T(I)
 1770 GO SUB G
 1775 PRINT TAB 2;O$((I-2)*3+1 TO (I-2)*3+3); TAB 10;"$"; TAB (19- LEN M$);M$;
 1780 LET M=T(1)- VAL M$
 1785 GO SUB G
 1786 IF M >=0 THEN PRINT TAB 20;"+";
 1787 IF M<0 THEN PRINT TAB 20;"\{20}\{1}-\{20}\{0}";
 1790 PRINT TAB (31- LEN M$);M$
 1795 NEXT I
 1799 LET T=0
 1800 FOR I=2 TO 13
 1805 LET T=T+T(I)
 1810 NEXT I
 1820 PRINT ,,"TOTAL ANNUAL BUDGET: $";
 1825 LET M=12*T(1)
 1830 GO SUB G
 1835 PRINT TAB (31- LEN M$);M$
 1840 LET M=T
 1845 GO SUB G
 1850 PRINT "TOTAL SPENT TO DATE: $"; TAB (31- LEN M$);M$
 1855 LET M=12*T(1)-T
 1860 IF M >=0 THEN PRINT "BALANCE LEFT:",
 1865 IF M<0 THEN PRINT INK 2;"OVERSPENT ",
 1870 GO SUB G
 1875 PRINT TAB 21;"$"; TAB (31- LEN M$);M$
 1880 PRINT AT 21,0;"\{20}\{1}'Z'=COPY  'C'=CONTINUE  'M'=MENU\{20}\{0}"
 1890 PAUSE F
 1895 LET X$= INKEY$
 1900 IF CODE X$=118 OR X$="M" THEN GO TO 1000
 1905 IF X$="Z" THEN PRINT AT E,0;"                                "
 1910 IF X$="Z" THEN COPY 
 1915 IF X$="Z" THEN GO TO 1880
 1920 GO TO S
 2000 REM ***\{20}\{1}ANALYSIS\{20}\{0}***
 2002 CLS 
 2010 PRINT "\{20}\{1}DETAILS OF AN ACCOUNT\{20}\{0}"
 2020 GO SUB L
 2021 CLS 
 2030 PRINT Y$
 2040 PRINT "\{20}\{1}BUDGET/MONTH:\{20}\{0} $";
 2045 LET M=D(Y,1)
 2050 GO SUB G
 2055 PRINT M$
 2056 PRINT 
 2060 PRINT "MTH\{20}\{1} \{20}\{0}AMT SPENT\{20}\{1} \{20}\{0} BALANCE\{20}\{1} \{20}\{0}ACCUM BAL"
 2070 PRINT L$
 2075 LET T=D(Y,1)
 2076 LET J=0
 2080 FOR I=2 TO 13
 2090 PRINT O$((I-2)*3+1 TO (I-2)*3+3);
 2100 LET M=D(Y,I)
 2105 LET J=J+M
 2110 GO SUB G
 2120 PRINT TAB 12- LEN M$;M$;
 2130 LET M=T-D(Y,I)
 2140 GO SUB G
 2150 IF M >=0 THEN PRINT TAB 13;"+";
 2160 IF M<0 THEN PRINT TAB 13;"\{20}\{1}-\{20}\{0}";
 2180 PRINT TAB 22- LEN M$;M$;
 2185 LET M=T*(I-1)-J
 2190 IF M<0 THEN PRINT TAB 23;"\{20}\{1}-\{20}\{0}";
 2195 IF M >=0 THEN PRINT TAB 23;"+";
 2200 GO SUB G
 2210 PRINT TAB 32- LEN M$;M$
 2215 NEXT I
 2219 PRINT 
 2220 PRINT "ANNUAL BUDGET:","$";
 2225 LET M=T*12
 2239 GO SUB G
 2240 PRINT TAB 25- LEN M$;M$
 2250 PRINT "SPENT TO DATE:","$";
 2260 LET M=J
 2270 GO SUB G
 2280 PRINT TAB 25- LEN M$;M$
 2290 PRINT "BALANCE:",
 2300 LET M=T*12-J
 2310 IF M >=0 THEN PRINT "+";
 2320 IF M<0 THEN PRINT "\{20}\{1}-\{20}\{0}";
 2330 GO SUB G
 2340 PRINT TAB 25- LEN M$;M$
 2350 PRINT AT 21,0;"\{20}\{1}        'Z'=COPY    'M'=MENU    \{20}\{0}"
 2360 PAUSE F
 2365 LET Y$= INKEY$
 2375 IF Y$="Z" THEN COPY 
 2380 IF Y$="Z" THEN GO TO 2350
 2390 CLS 
 2400 GO TO S
 2500 REM ***\{20}\{1}NEW INFO\{20}\{0}***
 2505 CLS 
 2510 PRINT "\{20}\{1}      NEW INFORMATION ENTRY     \{20}\{0}"
 2515 GO SUB L
 2520 PRINT "\{20}\{1}      NEW INFORMATION ENTRY     \{20}\{0}"
 2525 PRINT Y$
 2530 PRINT ,,"WILL YOU ENTER . . ."
 2540 PRINT ,,"1: MONEY SPENT FROM THIS ACCOUNT"; TAB 14;" OR ","2: MONEY TO BE CREDITED TO THIS    ACCOUNT"
 2550 PRINT TAB 6;"\{20}\{1} ENTER '1'  OR  '2'  \{20}\{0}"
 2555 PAUSE F
 2560 LET X$= INKEY$
 2570 IF X$ <>"1" AND X$ <>"2" THEN GO TO 2555
 2575 LET X= VAL X$
 2580 PRINT ,,,,"WHAT MONTH IS THIS ENTRY FOR ?"
 2590 PRINT "\{20}\{1} USE THE 3 LETTER ABBREV.. \{20}\{0}"
 2600 INPUT Y$
 2605 FOR I=0 TO 11
 2610 IF Y$=O$((I*3)+1 TO (I*3)+3) THEN GO TO 2625
 2615 NEXT I
 2620 PRINT "WHAT ?"
 2621 GO TO 2590
 2625 LET I=I+2
 2630 PRINT "ENTER THE AMOUNT:"
 2640 INPUT J
 2650 IF J<0 THEN GO TO 2590
 2660 IF X=2 THEN LET J=-J
 2670 LET D(Y,I)=D(Y,I)+J
 2680 PRINT AT 21,0;"\{20}\{1}     ANOTHER ENTRY  (Y/N)       \{20}\{0}"
 2690 PAUSE F
 2700 IF INKEY$="Y" THEN GO TO 2500
 2710 GO TO S
 2990 STOP 
 3000 REM ***\{20}\{1}CHANGE A BUDGET FIGURE\{20}\{0}***
 3001 CLS 
 3010 PRINT "\{20}\{1}CHANGE A BUDGET FIGURE FOR ACCT.\{20}\{0}"
 3013 GO SUB L
 3020 PRINT Y$
 3030 PRINT ,,"WILL YOU ENTER . . ."
 3035 PRINT ,,"1: A NEW MONTHLY FIGURE", TAB 14;" OR "
 3040 PRINT "2: A CHANGE IN THE ANNUAL TOTAL"
 3050 PRINT TAB 6;"\{20}\{1} ENTER '1' OR '2' \{20}\{0}"
 3060 PAUSE F
 3070 LET X$= INKEY$
 3075 IF X$ <>"1" AND X$ <>"2" THEN GO TO 3070
 3080 LET X= VAL X$
 3090 PRINT "ENTER THE AMOUNT:"
 3100 INPUT J
 3110 IF X=1 THEN GO TO 3200
 3120 LET J=J/12
 3130 LET J= INT (J*100)/100
 3140 LET D(Y,1)=D(Y,1)+J
 3150 GO TO S
 3200 LET D(Y,1)=J
 3205 GO TO S
 3500 REM ***\{20}\{1}CHANGE NAME\{20}\{0}***
 3502 CLS 
 3505 PRINT "TO CHANGE AN ACCOUNT NAME, FIRST"
 3510 GO SUB L
 3520 PRINT "\{20}\{1}PRESENT NAME\{20}\{0} ";Y$
 3530 PRINT ,,"ENTER THE NEW NAME:"
 3540 INPUT Y$
 3550 LET N$(Y,4 TO )=Y$
 3560 PRINT ,,"\{20}\{1}NEW NAME \{20}\{0} ";N$(Y)
 3570 PAUSE 250
 3580 GO TO S
 4000 REM ***\{20}\{1}SAVE\{20}\{0}***
 4002 CLS 
 4010 PRINT "ENTER TODAY'S DATE:"
 4015 INPUT D$
 4020 PRINT AT 5,0;"PREPARE DISC OR TAPE RECORDER ."
 4025 PRINT AT 8,0;"\{20}\{1}REMEMBER TO MAKE A SPARE COPY   \{20}\{0}"
 4030 PRINT AT 21,0;"PRESS ENTER TO START"
 4035 PAUSE F
 4040 SAVE "BUDGET" LINE 1000
 4050 GO TO S
 4500 REM ***\{20}\{1}EXIT\{20}\{0}***
 4502 CLS 
 4510 PRINT "ARE YOU SURE YOU WANT TO QUIT   THE PROGRAM WITHOUT SAVING ANY  NEW INFORMATION ?"
 4520 PAUSE F
 4530 IF INKEY$="N" THEN GO TO 1000
 4550 PRINT AT 10,0;"IF YOU CHANGE YOUR MIND, ENTER...\{20}\{1}GOTO 1000\{20}\{0}...":PRINT AT 15,0;"DO \{20}\{1}NOT\{20}\{0} PRESS RUN..."
 4560 GO TO 9898
 5000 REM ***\{20}\{1}SEARCH\{20}\{0}***
 5010 PRINT "ENTER THE NAME OF THE ACCOUNT:"
 5020 INPUT Y$
 5021 IF Y$="" THEN GO TO 1E3
 5030 IF LEN Y$>15 THEN LET Y$=Y$( TO 15)
 5035 LET Y= LEN Y$-1
 5040 FOR I=1 TO N1
 5050 FOR J=1 TO 15-Y
 5060 IF Y$=N$(I,J TO J+Y) THEN GO TO 5100
 5070 NEXT J
 5080 NEXT I
 5090 PRINT "NO SUCH NAME FOUND .. TRY AGAIN"
 5095 GO TO 5020
 5100 LET Y=I
 5110 LET Y$=N$(I)
 5120 CLS 
 5130 RETURN 
 9898 STOP 
 9899 GO TO 1000

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top