Console I/O & embedded DATA¶
This page covers the everyday ways a d/BASIC program talks to a person and carries its own small tables of data: printing text and numbers, formatting numbers, reading what someone types, DATA tables built into the program, random numbers, the clock, and the ERROR, ERR and ERL statements. By the end you can write a complete console program that prints, prompts, reads and formats.
There are two kinds of data in a d/BASIC program:
- values that already live inside the program: variables, arrays and
DATArows; and - values asked for from the outside world: typed at a console, delivered to a window program as an event, or fetched through an intent (an intent is a named request, such as "fill this rectangle" or "read this record", that the machine carries out however it can).
Keeping that boundary visible is what lets the same program be tested, and run on very different machines.
PRINT¶
Even the smallest statement deserves a good reference.
With no separator at the end, PRINT ends the line.
Semicolon: continue closely¶
A semicolon at the end keeps the line open, so the next PRINT continues it:
d/BASIC prints every number by one fixed rule, including the space that stands in for the sign, and that rule can make semicolon output look padded. Use PRINT USING, below, when the exact look matters.
Comma: move to the next print zone¶
Comma-separated output lines items up in fixed columns, which is handy for quick tables and the listings you remember. It is not a way to lay out pixels.
TAB and SPC¶
TAB(n) moves to column n of the console. SPC(n) prints n spaces.
PRINT USING¶
Use a numeric picture, a template such as "###.##", when the shape of the number is part of the output:
A picture shows the alignment, sign, decimal places and overflow behavior right there in the source. d/BASIC formats it by its own fixed rules, so the compiled program file, .dbc, prints the same thing on every machine and never picks up the host's locale or floating-point printer.
Classic BASICs grew a sprawling picture grammar; d/BASIC deliberately narrows it 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, a leading +, a trailing -, **, $$, **$, or a closing run of exactly four or five ^ characters; _x puts one literal printable character into the output. Computed or repeating pictures, a second field or value, and the string fields !, & and \...\ are not accepted; the compiler stops and says so, rather than letting the result differ from one machine to the next.
INPUT¶
A prompt followed by ; behaves the way classic BASIC did: it prints the prompt and then ?. A prompt followed by , prints the prompt exactly, with no question mark. The line the user types is split at commas into fields, and each field is converted to the type of its target variable.
LINE INPUT reads one whole line into one string:
Use LINE INPUT when commas are part of the text rather than separators between values.
Somewhere to read from is still required
INPUT, LINE INPUT and INKEY$ read from the console input service, the part of the host that supplies keystrokes. On a display with no source of input, they stop and say so rather than inventing keystrokes. Window programs normally receive keys through ON KEY instead.
INKEY$¶
INKEY$ looks at one pending console key without stopping to prompt:
Window programs driven by events should prefer ON KEY, which leaves the host in charge of when events arrive.
DATA, READ, and RESTORE¶
DATA builds a small read-only table right into 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 takes the values in the order they appear in the source and converts each one to the type of its target variable.
RESTORE rewinds to the beginning, or to a labelled or numbered line:
This is an excellent fit for small lookup tables, level data, palettes and teaching examples. Large or changing application data belongs in arrays, in resources, or in the database side of the language, described in Database & Data Intents.
Random sequences¶
RND returns a SINGLE drawn from the same pseudo-random sequence Microsoft BASIC used, so old listings behave as they did. 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:
Seed the sequence on purpose, for repeatable tests or for sessions that differ:
RANDOMIZE with no argument does not stop to ask a person for a seed; it reseeds with d/BASIC's fixed, repeatable value. Use RANDOMIZE TIMER when the clock of whatever machine is running the program should vary the session. RANDOMIZE 0 is a real reseed, not a no-op.
A seed you choose is a feature when you need to reproduce a game, a simulation or a bug. Do not mistake this kind of randomness for the cryptographic kind.
Time¶
TIMER returns the time in seconds, counted the same way on every machine:
The d/OS runtime, the program that runs your compiled code, maps TIMER onto whatever clock its host provides. (d/OS is the operating system that brings modern software to 8-bit home computers such as the Atari 800, the Commodore 64 and the Apple II.) A test host can supply a synthetic clock that ticks predictably; a desktop supplies real, steadily increasing time. Your source means the same thing either way.
Errors and source location¶
ERROR raises an error on purpose, by its error code:
The operand must be a single nonzero integer literal from 1 through 65535; a computed expression is not accepted. In d/BASIC, an operation that cannot go ahead is said to be refused: it stops and says exactly why. The error raised here goes to the active ON REFUSAL handler, the statement that names where such errors are handled; with no handler installed, the program stops and reports that exact error code.
ERR reports the code of the current error. ERL reports the numbered source line it happened on, when there is one:
ON REFUSAL GOTO CouldNotRead
' ...optional external operation...
END
CouldNotRead:
PRINT "REFUSED "; ERR; " AT LINE "; ERL
RESUME NEXT
Errors reported by name carry real source positions too; you do not need line numbers to get 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 disk on d/OS are the same thing. Instead it gives two different jobs two explicit, portable boundaries:
- Files & File Manipulation is about bytes stored under a name: mounts, directories, listing, reading, writing, copying, moving, renaming, the trash, and replacing a file all at once.
- Database & Data Intents is about revisions of a thing with an identity: database sessions, snapshots, typed values, durable saves, publications, and the confirmation a save returns once the data is really stored.
The short memory aid is: FILE is bytes at a name; DATA is a revision of an identity.
Three good boundaries¶
- Keep calculations in procedures that do no input or output.
- Convert values from outside into your own records or objects at the edge of the program, as soon as they arrive.
- Treat the confirmation that an external save committed as the moment the data became durable, not the moment a button was pressed.
That discipline pays off 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.