Skip to content

Console I/O & embedded DATA

There are two kinds of data in a D/BASIC program:

  • values already inside the program—variables, arrays, and DATA rows; and
  • values requested from the outside world through a console, event face, or semantic data Intent.

Keeping that boundary visible is what makes the same program testable and portable.

PRINT

The smallest useful statement still deserves a good reference.

PRINT "HELLO"
PRINT 2 + 2

With no trailing separator, PRINT ends the line.

Semicolon: continue closely

PRINT "SCORE:"; Score%
PRINT "A"; "B"; "C"

A trailing semicolon suppresses the final newline:

PRINT "LOADING";
PRINT ".";
PRINT ".";
PRINT "."

Numeric printing keeps D/BASIC's canonical sign-space behavior, which can make semicolon output look padded. Use formatted text when exact presentation matters.

Comma: move to the next print zone

PRINT "NAME", "SCORE", "RANK"
PRINT Name$, Score%, Rank%

Comma-separated output is useful for quick tables and familiar listings. It is not a pixel layout system.

TAB and SPC

PRINT TAB(12); "COLUMN TWELVE"
PRINT "LEFT"; SPC(5); "RIGHT"

TAB(n) moves to an absolute console column. SPC(n) emits a count of spaces.

Use a numeric picture when the shape of the number is part of the output:

PRINT USING "###.##"; Price#

Pictures make alignment, signs, decimal places, and overflow visible in source. They use canonical D/BASIC formatting rules so the same DBC does not inherit the host language's locale or float printer.

D/BASIC deliberately closes the sprawling historical picture grammar to one portable form: exactly one literal picture, exactly one numeric field, and exactly one numeric value. The numeric field may use #, one decimal point, comma grouping, leading +, trailing -, **, $$, **$, or a terminal exponent run of exactly four or five ^ characters; _x escapes one printable literal. Computed or repeating pictures, a second field/value, and the string fields !, &, and \...\ are refused instead of varying by runner.

INPUT

INPUT Age%
INPUT "YOUR NAME"; Name$
INPUT "X AND Y", X#, Y#

A prompt followed by ; preserves the familiar console interaction by printing the prompt followed by ?. A prompt followed by , prints the prompt exactly, without adding the question mark. The input row is split into fields and converted to the target types.

LINE INPUT reads one complete line into one string:

LINE INPUT "TELL ME A STORY"; Story$

Use LINE INPUT when commas belong to the text rather than separating values.

A provider is still required

INPUT, LINE INPUT, and INKEY$ use the console-input service. A head that has no input source refuses rather than inventing one; window programs normally receive normalized keys through ON KEY instead.

INKEY$

INKEY$ observes one pending console key without a blocking prompt:

K$ = INKEY$
IF LEN(K$) > 0 THEN PRINT "KEY: "; ASC(K$)

Event-driven window code should prefer ON KEY, leaving the host in charge of event timing.

DATA, READ, and RESTORE

DATA is a compact immutable table embedded in the program:

DATA "MERCURY", 57.9
DATA "VENUS", 108.2
DATA "EARTH", 149.6

FOR I% = 1 TO 3
  READ Planet$, Distance#
  PRINT Planet$; Distance#
NEXT I%

READ consumes values in source order and converts them to its destinations.

RESTORE rewinds to the beginning or a labelled/numbered point:

InnerPlanets:
DATA "MERCURY", "VENUS", "EARTH", "MARS"

READ First$
RESTORE InnerPlanets
READ Again$

This is an excellent fit for small lookup tables, level data, palettes, and teaching examples. Large or mutable application data belongs in arrays, resources, or the database-oriented DATA Intent family.

Random sequences

RND uses the canonical Microsoft sequence and returns a SINGLE. Its argument controls the sequence:

Form Effect
RND or RND(positive) advance and return the next value
RND(0) return the previous value again
RND(negative) reseed from that value and return the resulting repeatable value

The everyday form simply advances:

Roll% = INT(RND * 6) + 1

Seed intentionally for repeatable tests or varied sessions:

RANDOMIZE 12345

Bare RANDOMIZE does not stop to prompt a human; it applies D/BASIC's fixed deterministic reseed. Use RANDOMIZE TIMER when the active runner's clock should vary the session. RANDOMIZE 0 is still a real reseed, not a no-op.

A deterministic seed is a feature when reproducing a game, simulation, or failure. Do not confuse pseudorandomness with cryptographic randomness.

Time

TIMER returns canonical timer seconds:

Started! = TIMER
' ...work...
Elapsed! = TIMER - Started!

The runner maps this to its time provider. A conformance host can use a synthetic deterministic clock; a desktop host can provide live monotonic time. Source semantics remain the same.

Errors and source location

ERROR deliberately raises a governed refusal by literal rule ID:

ERROR 2401

The operand must be one nonzero integer literal in 1..65535; an arbitrary computed expression is not accepted. The raised refusal enters the active ON REFUSAL handler, or terminates the program with that exact diagnostic when no handler is installed.

ERR reports the current error/refusal number. ERL reports the numbered source line associated with it when available:

ON REFUSAL GOTO CouldNotRead
' ...optional external operation...
END

CouldNotRead:
  PRINT "REFUSED "; ERR; " AT LINE "; ERL
  RESUME NEXT

Named diagnostics also carry real source positions; line numbers are not required for useful errors.

Files and databases continue in their own chapters

D/BASIC does not make a program portable by pretending that C:\, /home, a browser sandbox, and a D/OS volume are the same thing. It gives those two jobs explicit, portable boundaries:

  • Files & File Manipulation is for bytes at a name: mounts, directories, listing, reading, writing, copying, moving, renaming, trash, and atomic replacement.
  • Database & Data Intents is for revisions of identities: database sessions, snapshots, typed values, durable saves, publications, and receipts.

The short memory aid is: FILE is bytes at a name; DATA is a revision of an identity.

Three good boundaries

  1. Keep calculations in procedures that do not perform I/O.
  2. Translate external values into your own records or objects at the edge.
  3. Treat an external commit receipt as the moment data became durable—not the moment a button was pressed.

That discipline is useful on a tiny machine, a desktop, and a browser for exactly the same reason: it separates what your program knows from what its environment promises.


Next: Errors, Refusals & Diagnostics →