Stamp Collector

Products: Stamp Collector
Date: 1983
Type: Program
Platform(s): TS 1000
Tags: Hobby

Stamp Collector is a philatelic inventory management program that allows users to track postage stamp collections by Scott catalog number and condition category. It uses a two-dimensional string array, `F$`, dimensioned at 600 rows by 15 characters, where each record packs a 5-character Scott number, a 1-character condition code, a 6-character quantity field, and a 1-character want-list flag. The program supports 18 stamp categories (singles, blocks, plate blocks, coils, imperforate, first day covers, and strips in mint or used conditions) encoded as alphanumeric codes 1–9 and A–H. Options include adjusting inventory quantities with positive or negative values, searching records by number and type, listing wanted stamps, and saving the entire array to tape.


Program Analysis

Program Structure

The program is organized as a menu-driven application anchored at line 70, which calls the main menu subroutine at 1000 and dispatches to one of five branches based on the value of O$. The structure is as follows:

  • Lines 50–80: Initialization — sets SLOW mode, dimensions the master array, and enters the menu loop.
  • Lines 1000–1099: Main menu display and input subroutine.
  • Lines 1500–1599: Code-to-description translation subroutine (maps C$ to human-readable J$).
  • Lines 2000–2022: Quit confirmation handler.
  • Lines 2500–2999: Option 1 — Adjust inventory (add/remove a stamp record or update quantity).
  • Lines 3000–3320: Option 2 — Search inventory by Scott number and/or category.
  • Lines 3500–3710: Option 3 — List all stamps flagged on the want list.
  • Lines 4000–4020: Option 4 — Save the inventory array to tape.
  • Lines 5000–5999: Classification input subroutine (displays category table, reads code into C$).

Data Storage Layout

All data is held in the two-dimensional string array F$(600,15). Each row encodes one inventory record using a fixed-width field layout:

ColumnsWidthContents
1–55Scott catalog number (left-justified, space-padded)
61Condition/type code (1–9, A–H)
7–126Quantity as a string (STR$ of numeric value)
131Want-list flag (“Y” or “N”)
14–152Unused

The 6-character key K$ formed by concatenating the padded Scott number and the type code (columns 1–6) serves as a composite primary key for searching and insertion.

Menu Input Idiom

The main menu uses a polling loop rather than INPUT for single-keypress capture. Line 1028 waits until INKEY$ is non-empty, then line 1029 captures the character into O$. Line 1030 validates the key and re-loops on invalid input. The same pattern is repeated in the classification subroutine at lines 50725075 and in the quit confirmation at lines 20162022. This approach avoids the cursor and input-buffer overhead of INPUT for menu navigation.

Inventory Adjustment Logic

Option 1 (lines 2500–2990) performs a linear scan of F$ from row 1 to 800 — notably exceeding the declared dimension of 600, which would cause a subscript error if the file is full and the loop reaches row 601. When a blank row is found (line 2556), a new record is inserted; when a matching key is found (line 2558), the existing record is updated. The quantity is read back with VAL F$(N,7 TO 12), adjusted by the signed input Q, and written back via STR$ (P+Q). Line 2811 guards against negative resulting quantities by looping back to re-enter the adjustment.

Search Logic

The search routine (lines 3000–3320) accepts an optional Scott number. If left blank, E$ becomes all spaces after padding, and the condition at line 3044IF K$(1 TO 5)=" " AND C$=F$(N,6 TO 6) — matches all records of the selected type across the entire file, effectively doing a type-only scan. The display subroutine at 3300 uses a counter G to suppress clearing the screen after the first match, allowing multiple results to accumulate on screen before prompting for the user to press Enter at end-of-file.

Category Code Translation

The subroutine at lines 1500–1599 maps the single-character C$ to a descriptive string J$ using 18 sequential IF tests. Codes 1–9 cover numeric ASCII characters and codes A–H cover uppercase letters, giving 18 distinct stamp categories. The validation in the classification subroutine (line 5082) checks C$<"1" OR C$>"H", which in ASCII order accepts all characters from “1” (ASCII 49) through “H” (ASCII 72), inadvertently including characters like the colon, letters A–G, and digits 1–9 — the intended valid range — but also characters such as “:”, “;”, “<“, “=”, “>”, “?”, “@” which fall between “9” and “A” in ASCII. These intermediate codes would produce the default J$="?????????" translation but are otherwise harmless.

Want List

Option 3 (lines 3500–3710) iterates all 600 rows and prints entries where column 13 equals “Y”. The want-list flag is set during inventory adjustment (lines 2840–2842) via a Y/N prompt. The listing routine at line 3600 reads the type code from F$(N,6 TO 6) back into C$ before calling the translation subroutine, correctly recovering the stored category description.

Tape Save

Option 4 prompts the user to ready the tape recorder and then executes SAVE "STAM%P" at line 4016. The %P notation represents an inverse-video “P” character in the filename.

Notable Bugs and Anomalies

  • The inventory adjustment loop at line 2552 iterates FOR N=1 TO 800, but F$ is only dimensioned to 600 rows. Accessing F$(N,...) for N > 600 will cause a subscript error if the file fills up and no match or blank is found within the first 600 entries.
  • The quit confirmation at lines 20162022 reads INKEY$ twice in sequence without looping between the “Y” and “N” checks, meaning the second INKEY$ call at line 2018 may capture a different (or empty) value than the one that satisfied line 2016. This can cause neither branch to fire, falling through to the unconditional GOTO 70 at line 2022.
  • Line 2516 prints an error for Scott numbers longer than 5 characters but does not loop back to re-prompt; the program continues to the GOSUB 5000 at line 2520 regardless.
  • The search loop at line 3038 iterates FOR N=1 TO 600, consistent with the array size, unlike the adjustment loop. However, blank-row detection at line 3040 terminates the scan early, so stamps entered after a gap of blank rows would never be found.

Content

Appears On

Related Products

Inventory up to 600 Scott numbers in a single session showing quantity on hand, by major classification. Program is completely...

Related Articles

Related Content

Image Gallery

Stamp Collector

Source Code

  50 REM "STAMP"
  52 SLOW 
  54 DIM F$(600,15)
  70 GOSUB 1000
  72 IF O$="Q" THEN GOTO 2000
  74 IF O$="1" THEN GOTO 2500
  76 IF O$="2" THEN GOTO 3000
  78 IF O$="3" THEN GOTO 3500
  80 IF O$="4" THEN GOTO 4000
 999 STOP 
 1000 CLS 
 1010 PRINT AT 2,12;"%S%T%A%M%P"
 1012 PRINT AT 3,10;"ACCOUNTING"
 1014 PRINT AT 5,4;"WHICH OPTION DO YOU DESIRE ?"
 1016 PRINT AT 8,4;"%O%P%T%I%O%N";AT 8,15;"%D%E%S%C%R%I%P%T%I%O%N"
 1018 PRINT AT 10,6;"1";AT 10,15;"ADJUST INVENTORY"
 1020 PRINT AT 12,6;"2";AT 12,15;"SEARCH INVENTORY"
 1021 PRINT AT 14,6;"3";AT 14,15;"LIST WANTED NO.S"
 1022 PRINT AT 16,6;"4";AT 16,15;"SAVE INVENTORY"
 1024 PRINT AT 18,6;"Q";AT 18,15;"QUIT"
 1026 PRINT AT 21,0;"%E%N%T%E%R OPTION NUMBER OR Q"
 1028 IF INKEY$="" THEN GOTO 1026
 1029 LET O$=INKEY$
 1030 IF O$<>"Q" AND O$<>"1" AND O$<>"2" AND O$<>"3" AND O$<>"4" THEN GOTO 1026
 1099 RETURN 
 1500 REM 
 1501 LET J$="?????????"
 1502 IF C$="1" THEN LET J$="MINT SINGLE"
 1504 IF C$="2" THEN LET J$="USED SINGLE"
 1506 IF C$="3" THEN LET J$="MINT BLOCK"
 1508 IF C$="4" THEN LET J$="USED BLOCK"
 1510 IF C$="5" THEN LET J$="MINT PLATE"
 1512 IF C$="6" THEN LET J$="USED PLATE"
 1514 IF C$="7" THEN LET J$="MINT SHEET"
 1516 IF C$="8" THEN LET J$="MINT COIL"
 1518 IF C$="9" THEN LET J$="USED COIL"
 1520 IF C$="A" THEN LET J$="MINT COIL PAIR"
 1522 IF C$="B" THEN LET J$="USED COIL PAIR"
 1524 IF C$="C" THEN LET J$="MINT LINE PAIR"
 1526 IF C$="D" THEN LET J$="USED LINE PAIR"
 1528 IF C$="E" THEN LET J$="MINT IMPERF"
 1530 IF C$="F" THEN LET J$="USED IMPERF"
 1532 IF C$="G" THEN LET J$="USED FIRST DAY"
 1534 IF C$="H" THEN LET J$="MINT STRIP"
 1599 RETURN 
 2000 REM 
 2010 CLS 
 2012 PRINT AT 1,0;"ARE YOU SURE YOU WANT TO QUIT ?"
 2014 PRINT "Y/N"
 2016 IF INKEY$="" THEN GOTO 2012
 2018 IF INKEY$="Y" THEN STOP 
 2020 IF INKEY$="N" THEN GOTO 70
 2022 GOTO 70
 2500 CLS 
 2510 PRINT "ENTER SCOTT NO. (MAX IS 5 LONG)"
 2511 PRINT "IF NO NUMBER THEN ENTER YOUR NO."
 2512 INPUT S$
 2514 PRINT S$
 2516 IF LEN S$>5 THEN PRINT "TOO BIG - RE-ENTER 5 OR LESS"
 2518 IF LEN S$=0 THEN GOTO 2510
 2520 GOSUB 5000
 2530 CLS 
 2535 GOSUB 1500
 2540 PRINT "NUMBER ";S$;"  ";J$
 2541 PRINT "ENTER THE QUANTITY(+ OR -)"
 2545 INPUT Q
 2547 PRINT Q
 2548 LET S$=S$+"       "
 2549 LET S$=S$(1 TO 5)
 2550 LET K$=S$+C$
 2552 FOR N=1 TO 800
 2554 LET X$=F$(N,1 TO 6)
 2556 IF X$="      " THEN GOTO 2600
 2558 IF X$=K$ THEN GOTO 2700
 2560 NEXT N
 2600 LET P=0
 2610 LET F$(N,1 TO 6)=K$
 2699 GOTO 2710
 2700 LET P=VAL F$(N,7 TO 12)
 2710 PRINT 
 2712 PRINT "OLD QUANTITY WAS ";P
 2800 REM 
 2810 PRINT "NEW QUANTITY IS ";P+Q
 2811 IF P+Q<0 THEN GOTO 2535
 2812 LET F$(N,7 TO 12)=STR$ (P+Q)
 2820 PRINT 
 2825 PRINT AT 18,0;"PLACE THIS STAMP ON WANT LIST ?"
 2830 PRINT "Y/N"
 2832 IF INKEY$="" THEN GOTO 2825
 2840 IF INKEY$="Y" THEN LET F$(N,13 TO 13)="Y"
 2842 IF INKEY$="N" THEN LET F$(N,13 TO 13)="N"
 2990 GOTO 70
 2999 STOP 
 3000 CLS 
 3005 LET G=0
 3010 CLS 
 3020 PRINT "ENTER SCOTT NUMBER OR HIT ENTER"
 3030 PRINT "IF NUMBER IS BLANK ENTIRE FILE"
 3032 PRINT "WILL BE SCANNED"
 3034 INPUT E$
 3035 GOSUB 5000
 3036 LET E$=E$+"     "
 3037 LET K$=E$(1 TO 5)+C$
 3038 FOR N=1 TO 600
 3040 IF F$(N,1 TO 6)="      " THEN GOTO 3200
 3042 IF F$(N,1 TO 6)=K$ THEN GOSUB 3300
 3044 IF K$(1 TO 5)="     " AND C$=F$(N,6 TO 6) THEN GOSUB 3300
 3046 NEXT N
 3050 FOR N=1 TO 100
 3052 NEXT N
 3055 GOTO 70
 3200 IF G>0 THEN GOTO 3240
 3201 CLS 
 3202 GOSUB 1500
 3203 PRINT K$(1 TO 5);" ";J$
 3205 PRINT "NO STAMPS OF THIS TYPE ON FILE"
 3220 FOR N=1 TO 150
 3225 NEXT N
 3230 GOTO 70
 3240 PRINT "FILE AT END--PRESS ENTER"
 3242 INPUT Y$
 3244 GOTO 70
 3300 IF G>0 THEN GOTO 3302
 3301 CLS 
 3302 LET G=G+1
 3304 GOSUB 1500
 3306 PRINT F$(N,1 TO 5);" ";J$;" ";"QUAN= ";F$(N,7 TO 12)
 3320 RETURN 
 3500 REM 
 3510 CLS 
 3512 PRINT "WANT LIST"
 3514 FOR N=1 TO 600
 3520 IF F$(N,1 TO 5)="     " THEN GOTO 3700
 3525 IF F$(N,13 TO 13)="Y" THEN GOSUB 3600
 3530 NEXT N
 3600 LET C$=F$(N,6 TO 6)
 3610 GOSUB 1500
 3612 PRINT F$(N,1 TO 5);" ";J$
 3699 RETURN 
 3700 PRINT "FILE AT END-PRESS ENTER"
 3705 INPUT Y$
 3710 GOTO 70
 3999 STOP 
 4000 CLS 
 4010 PRINT "SET TAPE RECORDER FOR RECORD "
 4012 PRINT "MODE--START RECORDER"
 4014 PRINT "PRESS ENTER WHEN READY"
 4015 INPUT Y$
 4016 SAVE "STAM%P"
 4018 CLS 
 4020 GOTO 70
 5000 REM 
 5010 CLS 
 5012 PRINT "CLASSIFY YOUR REQUEST BY CODE "
 5014 PRINT AT 2,0;"%D%E%S%C%R%I%P%T%I%O%N";AT 2,18;"%M%I%N%T   %U%S%E%D"
 5016 PRINT AT 3,0;"SINGLE";AT 3,19;"1      2"
 5018 PRINT AT 4,0;"BLOCK OF FOUR";AT 4,19;"3      4"
 5020 PRINT AT 5,0;"PLATE BLOCK";AT 5,19;"5      6"
 5022 PRINT AT 6,0;"SHEET";AT 6,19;"7      "
 5024 PRINT AT 7,0;"COIL";AT 7,19;"8      9"
 5026 PRINT AT 8,0;"COIL PAIR";AT 8,19;"A      B"
 5028 PRINT AT 9,0;"LINE PAIR";AT 9,19;"C      D"
 5030 PRINT AT 10,0;"IMPERFORATE";AT 10,19;"E      F"
 5032 PRINT AT 11,0;"FIRST DAY";AT 11,19;"       G"
 5034 PRINT AT 12,0;"STRIP";AT 12,19;"H      "
 5070 PRINT AT 20,0;"%E%N%T%E%R THE APPLICABLE CODE"
 5072 IF INKEY$="" THEN GOTO 5070
 5075 LET C$=INKEY$
 5082 IF C$<"1" OR C$>"H" THEN GOTO 5070
 5083 PRINT C$
 5999 RETURN 

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

People

No people associated with this content.

Scroll to Top