Fancy input

The typical INPUT statement looks like this:

INPUT "What is your name"; n$

It makes the computer ask "What is your name?" then wait for you to answer the question. So when you run the program, the conversation looks like this:

What is your name? Maria

Notice that the computer automatically adds a question mark at the end of the question, and leaves a blank space after the question mark.

Omitting the question mark

If you want to omit the question mark and the blank space, replace the semicolon by a comma:

INPUT "What is your name", n$

The comma makes the computer omit the question mark and the blank space, so the conversation will look like this:

What is your nameMaria

Here’s a prettier example of how to use the comma:

INPUT "Please type your name...", n$

The conversation will look like this:

Please type your name...Maria

Here’s an even prettier example:

INPUT "To become a movie star, type your name next to the stars***", n$

The conversation will look like this:

To become a movie star, type your name next to the stars***Maria

Omitting the prompt

The typical INPUT statement contains a question, such as "What is your name". The question is called the prompt. If you wish, you can omit the prompt, like this:

INPUT n$

That line doesn’t include a question, but the computer still prints a question mark followed by a blank space, so the conversation looks like this:

? Maria

To make that INPUT line more practical, put a PRINT line above it, like this:

PRINT "Please type your name after the question mark"

INPUT N$

That makes the conversation look like this:

Please type your name after the question mark

? Maria

Adjacent printing

Here’s a simple program:

CLS

INPUT "What is your name"; n$

PRINT "!!!What a wonderful name!!!"

It produces this conversation:

What is your name? MARIA

!!!What a wonderful name!!!

To have more fun, insert a semicolon immediately after the word INPUT, like this:

CLS

INPUT ; "What is your name"; n$

PRINT "!!!What a wonderful name!!!"

The conversation will begin normally:

What is your name? Maria

But when you press the ENTER key after Maria, the extra semicolon makes the computer do the PRINTing next to Maria, like this:

What is your name? Maria!!!What a wonderful name!!!

To surprise your friends, run this program:

CLS

INPUT ; "What is your name"; n$

PRINT n$; n$; n$

The program begins by asking:

What is your name?

Suppose the person says Maria, like this:

What is your name? Maria

When the person presses the ENTER key after Maria, the PRINT line automatically prints Maria three more times afterwards, like this:

What is your name? MariaMariaMariaMaria

This program asks for your first name, then your last name:

CLS

INPUT ; "What is your first name"; first.name$

INPUT " What is your last name"; last.name$

The first INPUT line makes the conversation begin like this:

What is your first name? Maria

When you press the ENTER key after Maria, that INPUT’s extra semicolon makes makes the next INPUT appear on the same line, like this:

What is your first name? Maria What is your last name?

If you answer Yee, the whole conversation looks like this:

What is your first name? Maria What is your last name? Yee

Multiple input

This program asks for your name, age, and weight:

CLS

INPUT "Name, age, weight"; n$, a, w

When you run the program, the computer asks:

Name, age, weight?

The computer waits for you to type your name, age, and weight. When you type them, put commas between them, like this:

Name, age, weight? John,25,148

If your name is "John Smith, Jr.", and you want to input all that instead of just John, you must put quotation marks around your name:

Name, age, weight? "John Smith, Jr.",25,148

Here’s the rule: you must put quotation marks around any INPUT string that contains a comma.

LINE INPUT

If you say —

LINE INPUT "Please type your name..."; n$

the computer will say:

Please type your name...

Then the computer will wait for you to type your name. You do not have to put quotation marks around your name, even if your name contains a comma. LINE INPUT means: the entire line that the person inputs will become the string, even if the line contains a comma.

Notice that the LINE INPUT statement does not make the computer automatically print a question mark. And notice that the variable must be a string (such as n$), not a number.

INPUT$

This program reveals private information about Mary:

CLS

PRINT "Mary secretly wishes to kiss a cow!"

Here’s how to protect that program, so only people who know the "secret password" can run it.…

First, invent a secret password. Let’s make it be "tuna".

Here’s the program:

CLS

INPUT "What's the secret password"; a$

IF a$ = "tuna" THEN

PRINT "Mary secretly wishes to kiss a cow!"

ELSE

PRINT "You are an unauthorized user!"

END IF

The INPUT line asks the person to type the secret password. Whatever the person types is called a$. If the person types "tuna", the computer will say:

Mary secretly wishes to kiss a cow!

But if the person does not type "tuna", the computer says "You are an unauthorized user!" and refuses to reveal Mary’s secret desire.

This program’s better:

CLS

PRINT "Please type the secret password."

a$ = INPUT$(4)

IF a$ = "tuna" THEN

PRINT "Mary secretly wishes to kiss a cow!"

ELSE

PRINT "You are an unauthorized user!"

END IF

Line 2 makes the computer say:

Please type the secret password.

Line 3 waits for the person to input 4 characters. The characters that the person inputs will become a$. For example, suppose the person types t, then u, then n, then a; then a$ will become "tuna" and the computer will reveal Mary’s secret.

While the person inputs the 4 characters, they won’t appear on the screen; they’ll be invisible. That’s to prevent other people in the room from peeking at the screen and noticing the password.

After typing the 4 characters, the person does not have to press the ENTER key. As soon as the person types the 4th character, the computer makes a$ be the 4 characters that the person typed.

Broken computer This devilish program makes your computer pretend to be broken, so that whenever you press the w key your screen shows an f instead:

CLS

DO

a$ = INPUT$(1)

IF a$ = "w" THEN PRINT "f"; ELSE PRINT a$;

LOOP

Line 3 waits for you to type 1 character. The IF line says: if the character you typed was "w", print an "f" on the screen instead; otherwise, print the character you typed. Since that routine is in a DO loop, the computer will repeat the routine forever. For example, if you try to type "the weather is wonderful", you’ll see this on the screen instead:

the feather is fonderful

For an even wilder time, tell the computer to change each "e" to "ooga", by changing the IF line to this:

IF a$ = "e" THEN PRINT "ooga"; ELSE PRINT a$;

Then if you try to type "We are here", you’ll see this on the screen instead:

wooga arooga hoogarooga

Abridged literature This program gives you a choice of literature:

CLS

PRINT "Welcome to the world's great literature, abridged."

PRINT "Which kind of literature would you like?"

PRINT "n: novel"

PRINT "p: poem"

10 PRINT "Please press n or p."

SELECT CASE INPUT$(1)

CASE "n"

PRINT "He: I love you."

PRINT "She: I'm pregnant."

PRINT "He: Let's get married."

PRINT "She: Let's get divorced."

PRINT "He: Let's get back together."

PRINT "She: Too bad you died in the war, but I'll never forget you!"

CASE "p"

PRINT "Noses"

PRINT "Blowses"

CASE ELSE

GOTO 10

END SELECT

The program begins by printing:

Welcome to the world's great literature, abridged.

Which kind of literature would you like?

n: novel

p: poem

Please press n or p.

The SELECT CASE line makes the computer wait for you to press a key. You do not have to press the ENTER key afterwards.

If you press the n key, the computer does the lines indented under CASE "n". Those lines print an abridged novel.

If you press the p key instead, the computer does the lines indented under CASE "p". Those lines print an abridged poem.

If you press neither n nor p, the computer does the line indented under CASE ELSE. That line makes the computer GO back TO line 10, which reminds you to press n or p.

SWAP

The computer understands the word SWAP:

CLS

x = 4

y = 9

SWAP x, y

PRINT x; y

Lines 2 & 3 say x is 4, and y is 9. The SWAP line swaps x with y; so x becomes 9, and y becomes 4. The bottom line prints:

9 4

That example swapped numbers. You can also swap strings:

CLS

a$ = "horse"

b$ = "cart"

SWAP a$, b$

PRINT a$; " "; b$

Lines 2 & 3 say a$ is "horse" and b$ is "cart". The SWAP line swaps a$ with b$; so a$ becomes "cart", and b$ becomes "horse". The bottom line puts the cart before the horse:

cart horse

 

Shuffling

Here are some cards:

queen of hearts

jack of diamonds

ace of spades

joker

king of clubs

Let’s shuffle them, to put them into a random order.

To begin, put the list of cards into a DATA statement:

CLS

DATA queen of hearts,jack of diamonds,ace of spades,joker,king of clubs

We have 5 cards. Let the queen of hearts be called card$(1), the jack of diamonds be called card$(2), the ace of spades be called card$(3), the joker be called card$(4), and the king of clubs be called card$(5):

n = 5

DIM card$(n)

FOR i = 1 TO n

READ card$(i)

NEXT

Shuffle the cards, by using the following strategy.…

Swap card n with a random card before it (or with itself); then swap card n-1 with a random card before it (or with itself); then swap card n-2 with a random card before it (or with itself); etc. Keep doing that, until you finally reach card 2, which you swap with a random card before it (or with itself). Here’s the code:

RANDOMIZE TIMER

FOR i = n TO 2 STEP -1

SWAP card$(i), card$(1 + INT(RND * i))

NEXT

Finally, print the shuffled deck:

FOR i = 1 TO n

PRINT card$(i)

NEXT

So altogether, here’s the entire program:

CLS

DATA queen of hearts,jack of diamonds,ace of spades,joker,king of clubs

n = 5

DIM card$(n)

FOR i = 1 TO n

READ card$(i)

NEXT

RANDOMIZE TIMER

FOR i = n TO 2 STEP -1

SWAP card$(i), card$(1 + INT(RND * i))

NEXT

FOR i = 1 TO n

PRINT card$(i)

NEXT

The computer will print something like this:

king of clubs

joker

jack of diamonds

queen of hearts

ace of spades

To shuffle a larger deck, change just the DATA and the line saying n=5.

Sorting

Putting words in alphabetical order — or putting numbers in numerical order — is called sorting.

Three-Line Sort Here are a dozen names: Sue, Ann, Joe, Alice, Ted, Jill, Fred, Al, Sam, Pat, Sally, Moe. Let’s make the computer alphabetize them (sort them).

Begin by clearing the screen:

CLS

To make the program run faster, tell the computer that all numbers in the program will be short integers:

DEFINT A-Z

Put the list of names in a DATA statement:

DATA Sue,Ann,Joe,Alice,Ted,Jill,Fred,Al,Sam,Pat,Sally,Moe

We have 12 names:

n = 12

Let Sue by called x$(1), Ann be called x$(2), Joe be called x$(3), etc. Here’s how:

DIM X$(n)

FOR i = 1 TO n

READ x$(i)

NEXT

Alphabetize the names, by using the following strategy.…

Compare the first name against the second; if they’re not in alphabetical order, swap them. Compare the second name against the third; if they’re not in alphabetical order, swap them. Compare the third name against the fourth; if they’re not in alphabetical order, swap them. Continue that process, until you finally compare the last two names. But each time you swap, you must start the whole process over again, to make sure the preceding names are still in alphabetical order. Here’s the code:

10 FOR i = 1 TO n - 1

IF x$(i) > x$(i + 1) THEN SWAP x$(i), x$(i + 1): GOTO 10

NEXT

Finally, print the alphabetized list:

FOR I = 1 TO n

PRINT x$(i)

NEXT

So altogether, the program looks like this:

CLS

DEFINT A-Z

DATA Sue,Ann,Joe,Alice,Ted,Jill,Fred,Al,Sam,Pat,Sally,Moe

n = 12

DIM x$(n)

FOR i = 1 TO n

READ x$(i)

NEXT

10 FOR i = 1 TO n - 1

IF x$(i) > x$(i + 1) THEN SWAP x$(i), x$(i + 1): GOTO 10

NEXT

FOR i = 1 TO n

PRINT x$(i)

NEXT

The computer will print:

Al

Alice

Ann

Fred

Jill

Joe

Moe

Pat

Sally

Sam

Sue

Ted

In that program, the sorting occurs in the FOR loop that begins at line 10. Those three lines are called the Three-Line Sort.

Those three lines form a loop. The part of the loop that the computer encounters the most often is the phrase "IF x$(i) > x$(i + 1)". In fact, if you tell the computer to alphabetize a list of names that’s long (several hundred names), the computer spends the majority of its time repeatedly handling "IF x$(i) > x$(i + 1)".

How long will the computer take to handle a long list of names? The length of time depends mainly on how often the computer encounters the phrase "IF x$(i) > x$(i + 1)".

If the list contains n names, the number of times that the computer encounters the phrase "IF x$(i) > x$(i + 1)" is approximately n3/8. Here are some examples:

n (number of names) n3 / 8 (approximate number of encounters)

10 125

12 216

20 1,000

40 8,000

100 125,000

1,000 125,000,000

For example, the chart says that a list of 12 names requires approximately 216 encounters.

The 216 is just an approximation: the exact number of encounters depends on which list of names you’re trying to alphabetize. If the list is nearly in alphabetical order already, the number of encounters will be less than 216; if the list is in reverse alphabetical order, the number of encounters will be more than 216; but if the list is typical (not yet in any particular order), the number of encounters will be about 216. For the list that we tried (Sue, Ann, Joe, Alice, Ted, Jill, Fred, Al, Sam, Pat, Sally, Moe), the exact number of encounters happens to be 189, which is close to 216.

How long will your computer take to finish sorting? The length of time depends on which computer you have, how many names are in the list, and how long each name is. A typical 486DX-66 computer (handling a list of typical names) requires about .00002 seconds per encounter. Multiplying the number of encounters by .00002 seconds, you get:

Number of names Encounters (n3 / 8) Time___

10 125 .0025 secs

12 216 .00432 secs

20 1,000 .02 secs

40 8,000 .16 secs

100 125,000 2.5 secs

1,000 125,000,000 2500 secs = about 7 hours

Five-Line Sort To make the program run faster, use the Five-Line Sort instead, which uses this strategy.… Compare the first name against the second (that comparison is called i=1), then compare the second name against the third (that comparison is called i=2), then compare the third name against the fourth (that comparison is called i=3), etc. If you find a pair of names that are out of order, swap them and then recheck the pairs that came before. To "recheck the pairs that came before", start with the most recent pairs and work back toward the first name (FOR j = i TO 1 STEP -1), swapping whenever necessary, until you come to a pair that doesn’t need to be swapped. When you come to a pair that doesn’t need to be swapped, stop the rechecking and proceed to the next i.

Here’s the code:

FOR i = 1 TO n - 1

FOR j = i TO 1 STEP -1

IF x$(j) > x$(j + 1) THEN SWAP x$(j), x$(j + 1) ELSE GOTO 10

NEXT

10 NEXT

The IF line says: if x$(j) and x$(j + 1) are out of order, SWAP them; but if they’re not out of order, get out of the j loop and GOTO the NEXT i instead.

Even though that Five-Line Sort is longer to type than the Three-Line Sort, the computer handles the Five-Line Sort faster, because its "GOTO 10" lets the computer hop ahead to the NEXT i instead of forcing the computer to go back to the "FOR i = 1".

For the Five-Line Sort, the number of times the computer encounters the phrase "IF x$(j) > x$(j + 1)" is just n2/4:

Number of names Encounters (n2 / 4) Time__

10 25 .0005 secs

12 36 .00072 secs

20 100 .002 secs

40 400 .008 secs

100 2,500 .05 secs

1,000 250,000 5 secs

Eight-Line Sort The Five-Line Sort compares just adjacent pairs: x$(j) and x$(j+1). The Eight-Line Sort compares pairs that are farther apart: x$(j) and x$(j+d), where d is a big distance. So the Eight-Line Sort resembles the Five-Line Sort but says +d instead of +1, and says -d instead of -1:

FOR i = 1 TO n - d

FOR j = i TO 1 STEP -d

IF x$(j) > x$(j + d) THEN SWAP x$(j), x$(j + d) ELSE GOTO 10

NEXT

10 NEXT

But how big is d?

Begin by making d be a big number, about 1/3 as big as n, and perform those five lines. Then divide by 3 again, so d becomes about 1/9 as big as n, and perform those five lines again. Then divide by 3 again, so d becomes about 1/27 as big as n, and perform those five lines again. Keep dividing by 3, until d finally becomes 1, which makes those five lines act exactly the same as the Five-Line Sort. But during that last pass through the data, when d is 1, the computer performs the five lines very quickly, since the earlier passes already put the names into roughly alphabetical order by comparing pairs that were far apart.

Moreover, those early passes consumed very little time, since during those passes the computer did the FOR j loop very few times. (It did that loop few times because it said to "STEP -d", where d was a big number.)

Here’s the complete Eight-Line Sort:

d = n

2 d = d \ 3 + 1

FOR i = 1 TO n - d

FOR j = i TO 1 STEP -d

IF x$(j) > x$(j + d) THEN SWAP x$(j), x$(j + d) ELSE GOTO 10

NEXT

10 NEXT

IF d > 1 THEN GOTO 2

In line 2, the symbol "\" says to do integer division, so the computer will divide by 3 but ignore all digits after the decimal point. Altogether, line 2 says this: to get the new d, divide the old d by 3 (ignoring all digits after the decimal point) and then add 1. That "+ 1" makes the new d be slightly more than the old d divided by 3.

For the Eight-Line Sort, the number of times the computer encounters the phrase "IF x$(j) > x$(j + d)" is just 1.5*(n-1)^(4/3):

Number of names Encounters Time__

10 28 .00056 secs

12 37 .00074 secs

20 76 .00152 secs

40 198 .00396 secs

100 687 .01374 secs

1,000 14,980 .2996 secs

Notice that the Eight-Line Sort handles 1,000 names in .2996 seconds. That’s much faster than the Five-Line Sort, which takes 5 seconds. But to handle just 10 names, the Eight-Line Sort does not run faster than the Five-Line Sort. So use the Eight-Line Sort just for handling long lists of names.

We’ve sure come a long way! To alphabetize 1,000 names, the Three-Line Sort took about 7 hours; the Five-Line Sort took 5 seconds; the Eight-Line Sort took about .3 seconds.

If you try running those sorting methods on your computer, you’ll find the timings are different, since the exact timings depend on which computer you have, the length of each name, and how badly the names are out of order.

Famous sorts Though I "invented" all those sorting methods, most of them just improve a little on methods developed by others. For example, the Five-Line Sort improves slightly on the Shuttle Sort, which was invented by Shaw & Trimble in 1983. The Eight-Line Sort improves slightly on the Shell Sort, which was invented by Donald Shell in 1959 and further developed by Hibbard & Boothroyd in 1963, Peterson & Russell in 1971, and Knuth in 1973.

Phone directory Suppose you want to alphabetize this phone directory:

Name Phone number

Mary Smith 277-8139

John Doe 513-9134

Russ Walter 666-2666

Information 555-1212

Just use one of the alphabetizing programs I showed you! Type the DATA like this:

DATA Smith Mary 277-8139,Doe John 513-9134

DATA Walter Russ 666-2666,Information 555-1212

The computer will print:

Doe John 513-9134

Information 555-1212

Smith Mary 277-8139

Walter Russ 666-2666

Sorting numbers Suppose you want to put a list of numbers into increasing order. For example, if the numbers are 51, 4.257, -814, 62, and .2, let’s make the computer print:

-814

.2

4.257

51

62

To do that, just use one of the alphabetizing programs I showed you — but in the DATA statement, put the numbers instead of strings, and say "x!" instead of "x$".

To put a list of numbers into decreasing order, begin by writing a program that puts them into increasing order, and then change each "> x" to "< x".

Sequential data files

Here’s a simple program:

CLS

PRINT "eat"

PRINT 2 + 2

PRINT "eggs"

It makes the computer print this message onto your screen:

eat

4

eggs

Instead of printing that message onto your screen, let’s make the computer print the message onto your disk. Here’s how.…

OPEN FOR OUTPUT

This program prints the message onto your disk, instead of onto your screen:

CLS

OPEN "joan" FOR OUTPUT AS 1

PRINT #1, "eat"

PRINT #1, 2 + 2

PRINT #1, "eggs"

CLOSE

Those PRINT lines make the computer print the message onto your disk instead of onto your screen. Each line says PRINT #1, which means: print onto the disk.

The OPEN line is an introductory line that tells the computer where on the disk to print the message. The OPEN line says: find a blank place on the disk, call it JOAN, and make JOAN be file #1. So PRINT #1 will mean: print onto file #1, which is JOAN.

Any program that says OPEN should also say CLOSE, so the bottom line says CLOSE. The CLOSE line makes the computer put some "finishing touches" on JOAN, so that JOAN becomes a perfect, finished file.

When you run that program, the computer will automatically put onto the disk a file called JOAN that contains this message:

eat

4

eggs

After running that program, try this experiment.… Exit from QBASIC (by choosing Exit from the File menu), so the computer says:

C:\>

After that C prompt, type "dir", so the screen looks like this:

C:\>dir

When you press the ENTER key at the end of that line, the computer will print the names of all the disk’s files — and one of the names it prints will be JOAN.

After the C prompt, try saying "type joan", like this:

C:\>type joan

That makes the computer show you what’s in JOAN; the computer will say:

eat

4

eggs

 

OPEN FOR INPUT

To see the message that’s in JOAN, run this program, which inputs from JOAN and prints onto your screen:

CLS

OPEN "joan" FOR INPUT AS 1

INPUT #1, a$

PRINT a$

INPUT #1, b

PRINT b

INPUT #1, c$

PRINT c$

CLOSE

The OPEN line prepares the computer to input from JOAN.

The next line inputs a$ from JOAN, so a$ is "eat". The next line prints "eat" onto your screen.

The next pair of lines input b from JOAN (so b is 4) and print 4 onto your screen. The next pair of lines input c$ from JOAN (so c$ is "eggs") and print "eggs" onto your screen. So altogether, on your screen you’ll see:

eat

4

eggs

The CLOSE line tells the computer that you’re done using JOAN for a while (until you say OPEN again).

OPEN FOR APPEND

After you’ve put JOAN onto the disk, so that JOAN consists of "eat" and 4 and "eggs", try running this program:

CLS

OPEN "joan" FOR APPEND AS 1

PRINT #1, "good morning!"

CLOSE

In the OPEN line, the word APPEND tells the computer to keep adding onto JOAN. So when the computer comes to the PRINT line, it adds "good morning" onto JOAN, and JOAN becomes this:

eat

4

eggs

good morning!

Erasing

For your next experiment, try running this program:

CLS

OPEN "joan" FOR OUTPUT AS 1

PRINT #1, "pickles are pleasant"

CLOSE

Since the OPEN line does not say APPEND, the computer will not keep adding onto JOAN. Instead, the computer erases everything that’s been in JOAN. So when the computer finishes processing line 10, JOAN’s become blank.

The PRINT line puts "pickles are pleasant" into JOAN. So at the end of the program, JOAN includes "pickles are pleasant"; but JOAN does not include "eat" and 4 and "eggs" and "good morning", which have all been erased.

OUTPUT or INPUT or APPEND?

In the OPEN line, you can say OUTPUT or INPUT or APPEND. Here’s how they differ:

If the OPEN line says FOR INPUT, the program can say INPUT #1 but cannot say PRINT #1.

If the OPEN line says FOR OUTPUT, the program can say PRINT #1 but cannot say INPUT #1.

If the OPEN line says FOR APPEND, the program can say PRINT #1 but usually not INPUT #1.

Here’s what happens if you say OPEN "joan" and the file JOAN exists already:

FOR INPUT makes the computer use JOAN without changing JOAN.

FOR APPEND makes the computer use JOAN and lengthen it (by appending extra lines to its end).

FOR OUTPUT makes the computer erase JOAN and then create a totally new JOAN.

Here’s what happens if you say OPEN "joan" when JOAN doesn’t exist yet:

FOR OUTPUT or FOR APPEND makes the computer create JOAN.

FOR INPUT makes the computer gripe and say "File not found".

The following program plays a trick: if JOAN doesn’t exist yet, the program creates JOAN; if JOAN exists already, the program leaves JOAN alone.

CLS

OPEN "joan" FOR APPEND AS 1

CLOSE

Loops

This program lets you put the names of all your friends onto the disk:

CLS

OPEN "friends" FOR OUTPUT AS 1

DO

PRINT "Please type a friend's name (or the word 'end')"

INPUT friend$: IF friend$ = "end" THEN EXIT DO

PRINT #1, friend$

LOOP

CLOSE

The OPEN line makes the computer find a blank space on the disk and call it FRIENDS. The first PRINT line makes the computer print:

Please type a friend's name (or the word 'end')

The INPUT line prints a question mark and waits for you to type something; whatever you type will be called friend$. For example, if you type Mary Williams, then friends$ will be Mary Williams, and the next line prints the name Mary Williams onto the disk.

The lines are in a DO loop, so that you can type as many names as you wish. (Remember to press the ENTER key after each name.)

When you’ve finished typing the names of all your friends, type the word "end". Then the last part of the INPUT line will make the computer EXIT from the DO loop and CLOSE the file.

This program makes the computer look at the FRIENDS file and copy all its names to your screen:

CLS

OPEN "friends" FOR INPUT AS 1

DO UNTIL EOF(1)

INPUT #1, friend$

PRINT friend$

LOOP

CLOSE

PRINT "Those are all the friends."

The OPEN line prepares the computer to input from the FRIENDS file. The lines DO and LOOP make the computer do the indented lines repeatedly. The first indented line makes the computer input a string from the file and call the string friend$; so friend$ becomes the name of one of your friends. The next indented line prints that friend’s name onto your screen. Since those indented lines are in a loop, the names of all your friends are printed on the screen.

Eventually, the computer will reach the end of the file, and there won’t be any more names to input from the file. In the DO line, the "UNTIL EOF(1)" means: if the computer reaches the End Of the File and can’t input any more names from it, the computer should stop looping and proceed to the line underneath LOOP. That line makes the computer CLOSE the file. Then the computer will print on your screen, "Those are all the friends."

As that program illustrates, to read from a file you create a DO loop. Above the loop, say OPEN FOR INPUT; below the loop, say CLOSE; in the loop, say INPUT #1; next to the DO, say UNTIL EOF(1).

LOF

In the middle of your program, if you say PRINT LOF(1), the computer will tell you the Length Of the File: it will tell you how many bytes are in the file.

Multiple files

If you want the computer to handle two files simultaneously, use two OPEN statements. At the end of the first OPEN statement, say "AS 1"; at the end of the second OPEN statement, say "AS 2".

For the second file, say PRINT #2 instead of PRINT #1, say INPUT #2 instead of INPUT #1, say EOF(2) instead of EOF(1), and say LOF(2) instead of LOF(1).

How to CLOSE

The CLOSE statement closes all files. To be more specific, you can say CLOSE 1 (which closes just the first file) or CLOSE 2 (which closes just the second).

Whenever you’re done using a file, CLOSE it immediately. When you say CLOSE, the computer puts finishing touches on the file that protect the file against damage.

Suppose that halfway through your program, you finish using file 2 but want to continue using file 1. Say CLOSE 2 there, and delay saying CLOSE 1 until later.

Random access

On a disk, you can store two popular kinds of data files. The simple kind is called a sequential-access data file; the complicated kind is called a random-access data file. You’ve already learned how to create and retrieve a sequential-access file. Now let’s look at random-access.

Though more complicated than sequential-access data files, random-access data files have an advantage: they let you skip around. In a sequential-access data file, you must look at the first item of data, then the second, then the third, etc. In a random-access data file, you can look at the seventh item of data, then skip directly to the tenth, then hop back to the third, then skip directly to the sixth, etc.

Each item is called a record. The number of characters (bytes) in the record is called the record’s length. For example, if a record contains 20 characters, the record’s length is 20. In a random-access file, all records must have the same length as each other.

PUT

Here’s how to write a program that creates a random-access file.

Begin the program by saying:

CLS

Let’s make each record be a string containing 20 characters:

DIM record AS STRING * 20

Let’s make the file’s name be JIM:

OPEN "jim" FOR RANDOM AS 1 LEN = LEN(record)

Let’s make JIM’s 7th record be "Love makes me giggle" (which contains 20 characters):

record = "Love makes me giggle"

PUT 1, 7, record

Let’s make JIM’s 9th record be "Please hold my hand":

record = "Please hold my hand"

PUT 1, 9, record

Since JIM’s record length is supposed to be 20 characters but "Please hold my hand" contains just 19 characters, the computer will automatically add a blank to the end of "Please hold my hand".

Let’s make JIM’s 4th record be "I love Lucy":

record = "I love Lucy"

PUT 1, 4, record

The computer will automatically add blanks to the end of "I love Lucy".

To finish the program, say:

CLOSE

So altogether, the program looks like this:

CLS

DIM record AS STRING * 20

OPEN "jim" FOR RANDOM AS 1 LEN = LEN(record)

record = "Love makes me giggle"

PUT 1, 7, record

record = "Please hold my hand"

PUT 1, 9, record

record = "I love Lucy"

PUT 1, 4, record

CLOSE

 

When you run that program, the computer will automatically put onto the disk a file called JIM in which each record is a 20-character string.

After running that program, try this experiment.… Exit from QBASIC (by choosing Exit from the File menu), so the computer says:

C:\>

After that C prompt, type "dir". The computer will print the names of all the disk’s files — and one of the names it prints will be JIM.

After the C prompt, try saying "copy jim con /b". The computer will show you what’s in JIM. You’ll see that JIM includes "I love Lucy" (in the 4th record), "Love makes me giggle" (in the 7th record), and "Please hold my hand" (in the 9th record). Since the program didn’t say what to put into the other records, those other records still contain garbage (whatever data was sitting on that part of the hard disk before the program ran).

GET

This program makes the computer tell you JIM’s 7th item:

CLS

DIM record AS STRING * 20

OPEN "jim" FOR RANDOM AS 1 LEN = LEN(record)

GET 1, 7, record

PRINT record

CLOSE

Multi-field records

Let’s write a program that creates a fancier random-access file.

As usual, begin by saying:

CLS

Let’s make each record be a combination of two parts:

The record’s first part, called "part a", will be a string of 20 characters.

The record’s second part, called "part b", will be a string of 5 characters.

Here’s how:

TYPE combination

a AS STRING * 20

b AS STRING * 5

END TYPE

DIM record AS combination

Let’s make the file be called JACK:

OPEN "jack" FOR RANDOM AS 1 LEN = LEN(record)

Let’s make the 6th record’s first part be "I want turkey on rye" and the second part be "yummy":

record.a = "I want turkey on rye"

record.b = "yummy"

PUT 1, 6, record

To finish the program, say:

CLOSE

 

So altogether, here’s the program:

CLS

TYPE combination

a AS STRING * 20

b AS STRING * 5

END TYPE

DIM record AS combination

OPEN "jack" FOR RANDOM AS 1 LEN = LEN(record)

record.a = "I want turkey on rye"

record.b = "yummy"

PUT 1, 6, record

CLOSE

Go ahead: run that program!

Then run the following program, which makes the computer tell you JACK’s 6th record:

CLS

TYPE combination

a AS STRING * 20

b AS STRING * 5

END TYPE

DIM record AS combination

OPEN "jack" FOR RANDOM AS 1 LEN = LEN(record)

GET 1, 6, record

PRINT record.a

PRINT record.b

CLOSE

Lengths

If you say PRINT LOF(1), the computer will tell you the Length Of the File (how many bytes are in the file). If you say PRINT LEN(record), the computer will tell you the LENgth of a record (how many bytes are in a record).

Since LOF(1) is the length of the file, and LEN(record) is the length of a record, this line makes the computer tell you how many records are in the file:

PRINT LOF(1) \ LEN(record)

End of the file

The EOF function doesn’t work well for random-access files. To deal with the end of the file, use the following trick instead.

Since the number of records in the file is LOF(1) \ LEN(record), these lines print all the records:

FOR i = 1 TO LOF(1) \ LEN(record)

GET 1, i, record

PRINT record.a

PRINT record.b

NEXT

Numeric data

To make each record consist of a 20-character string followed by a 5-character string, you learned to say this:

TYPE combination

a AS STRING * 20

b AS STRING * 5

END TYPE

DIM record AS combination

 

Here’s how to make each record consist of a 20-character string followed by a short INTEGER followed by a LONG integer followed by a SINGLE-precision real number followed by a DOUBLE-precision real number:

TYPE combination

a AS STRING * 20

b AS INTEGER

c AS LONG

d AS SINGLE

e AS DOUBLE

END TYPE

DIM record AS combination

A short INTEGER consumes 2 bytes, a LONG integer consumes 4 bytes, a SINGLE-precision real number consumes 4 bytes, and a DOUBLE-precision real number consumes 8 bytes; so in that example, the record’s length is 20 + 2 + 4 + 4 + 8, which is 38 bytes.

Descriptive variables

Instead of talking about "part a" and "part b" of a record, you can pick names that are more descriptive. For example, if a record consists of a person’s nickname and age, you can say:

TYPE combination

nickname AS STRING * 10

age AS integer

END TYPE

DIM record AS combination

To make the 6th record contain my nickname (Russy-poo) and age (48), say:

record.nickname = "Russy-poo"

record.age = 48

PUT 1, 6, record

LOC

If you say PRINT LOC(1), the computer tells you which record it just dealt with. It tells you the record’s LOCation.

For example, if you say "PUT 1, 7, record" or "GET 1, 7, record" and then say PRINT LOC(1), the computer prints the number 7.

Instead of saying "PUT 1, 7, record" or "PUT 1, 8, record", you can leave the record’s number blank and say just:

PUT 1, , record

That makes the computer PUT the next record. For example, it will PUT the 9th record if the previous PUT or GET mentioned the 8th. Saying "PUT 1, , record" has the same effect as saying "PUT 1, LOC(1) + 1, record".

If you say —

GET 1, , record

the computer will GET the next record. For example, it will GET the 9th record if the previous PUT or GET mentioned the 8th.

Multiple files

If you want the computer to handle two random-access files simultaneously, use two OPEN statements. In the first OPEN statement, say "AS 1 LEN = LEN(record)"; in the second OPEN statement, say "AS 2 LEN = LEN(record2)".

For the second file, say 2 instead of 1 (in the OPEN, PUT, and GET statements and in the LOF and LOC functions); say combination2 instead of combination; and say record2 instead of record.

Create a database

I’m going to show you how to write a program that creates a database, in which you can store information about your friends & enemies, your business & bills, birthdays & appointments, desires & dreads, and whatever else bothers you.

Here’s how the program works.…

When you run the program, the computer begins by asking, "What topic interests you?" If you type a topic the computer knows about, the computer will tell you what data it knows about that topic; then the computer will let you change that data. If you type a topic that the computer doesn’t know anything about, the computer will admit ignorance then let you teach the computer about that topic.

After dealing with the topic you requested, the computer will let you request additional topics.

If you type a question mark, the computer will print a list of all the topics in its database so far. If you type an x, the computer will exit from the program.

Simple chronological database

The simplest way to write the program is to write a main procedure and seven SUB procedures:

Allow 3000 topics & data about them. Share with SUBs. DIM SHARED topic$(3000), data$(3000)

Share these variables with the SUBs. COMMON SHARED topic.desired$, data.inputted$, n, i

Make n (the number of topics) start at 0. n = 0

Do the following loop repeatedly: DO

Clear the screen. CLS

Ask the human, "What topic interests you?" PRINT "What topic interests you? ";

Remind the human to type "?" if unsure, "x" to exit. PRINT "(If unsure, type a question mark. To exit, type an x.)"

Make the human’s response be called topic.desired$. 10 LINE INPUT topic.desired$

If human confused, list all topics & ask human again. IF topic.desired$ = "?" THEN list.all.topics: GOTO 10

If the human’s response is "x", exit from the program. IF topic.desired$ = "x" THEN END

Otherwise, capitalize the response & delete extra blanks. topic.desired$ = UCASE$(LTRIM$(RTRIM$(topic.desired$)))

Search for the topic that the human requested. search.for.topic

Repeat that loop until the human types "x". LOOP

Here’s how to list all topics: SUB list.all.topics

Clear the screen. CLS

If there are no topics yet, do this: IF n = 0 THEN

Say "I don’t know any topics yet." PRINT "I don't know any topics yet. My mind is still blank. ";

Say "Please teach me a new topic." PRINT "Please teach me a new topic."

If some topics exist, do this: ELSE

Say "I know about these topics". PRINT "I know about these topics:"

Leave a blank line underneath that heading. PRINT

For every individual topic in the database, FOR i = 1 TO n

print that topic, then hop to the next zone. PRINT topic$(i),

When you finish printing all the topics, NEXT

return to the screen’s left margin PRINT

and leave a blank line PRINT

then say "Pick one of those or teach me a new one." PRINT "Pick one of those topics, or teach me a new one."

At the end of all that, END IF

ask the human again, "What topic interests you?" PRINT "What topic interests you? (To exit, type an x.)"

END SUB

Here’s how to search for the topic the human requested: SUB search.for.topic

Start to look at every individual topic in the database. FOR i = 1 TO n

If a topic’s the one desired, just do "found.the.topic". IF topic$(i) = topic.desired$ THEN found.the.topic: EXIT SUB

If the desired topic is not in the database, NEXT

the topic is missing, so do "missing.topic". missing.topic

END SUB

Here’s how to act when situation is "found.the.topic": SUB found.the.topic

Clear the screen. CLS

Say "Here’s what I know about" the topic. PRINT "Here's what I know about "; topic.desired$; ":"

Print the data that’s in the database about that topic. PRINT data$(i)

Leave a blank line. PRINT

Ask "Do you want to change that information?" INPUT "Do you want to change that information"; response$

If the human says "yes" or "y", change the info. IF response$ = "yes" OR response$ = "y" THEN change.the.info

END SUB

Here’s how to change the info: SUB change.the.info

Say that the computer’s erased old info about the topic. PRINT "Okay. I've erased that information about "; topic.desired$; "."

Leave a blank line. PRINT

Tell the human to input new info about the topic. PRINT "Type what you want me to know about "; topic.desired$; "."

Say that typing an x will delete the topic. PRINT "(If you want me to forget about "; topic.desired$; ", type an x.)"

Wait for the human’s response. LINE INPUT data.inputted$

If response is x, delete the topic; if not x, use new data. IF data.inputted$ = "x" THEN delete.the.topic ELSE data$(i) = data.inputted$

END SUB

Here’s how to delete the topic: SUB delete.the.topic

Replace that topic by the last topic (topic #n). topic$(i) = topic$(n)

Replace that topic’s data by the last topic’s data. data$(i) = data$(n)

Decrease the number of topics, by subtracting 1. n = n - 1

END SUB

Here’s how to act when situation is "missing.topic": SUB missing.topic

Clear the screen. CLS

Say "I don’t know anything about" that topic. PRINT "I don't know anything about "; topic.desired$; "."

Say "Please tell me about" that topic. PRINT "Please tell me about "; topic.desired$; "."

Say "If you don’t want to tell me, type an x." PRINT "(If you don't want to tell me, type an x.)"

Wait for the human’s response. LINE INPUT data.inputted$

If the human didn’t type an x, insert the topic. IF data.inputted$ <> "x" THEN insert.the.topic

END SUB

Here’s how to insert the topic: SUB insert.the.topic

Increase the number of topics, by adding 1. n = n + 1

Append the new topic. Make it topic #n. topic$(n) = topic.desired$

Also append the new topic’s data. Make it data #n. data$(n) = data.inputted$

END SUB

The program stores the topics in chronological order: if you begin by feeding it information about SUE and then information about CAROL, it will let topic$(1) be "SUE" and let topic$(2) be "CAROL".

Copy to disk

That program stores the data just in the RAM — not on a disk. When you turn off the power, the RAM forgets all the data!

Let’s write a fancier version that copies the data onto the hard disk before the program ends.

To write the fancier version, just change the main procedure; the seven SUB procedures remain the same! Here’s how to write the main procedure:

Allow 3000 topics & data about them. Share with SUBs. DIM SHARED topic$(3000), data$(3000)

Share these variables with the SUBs. COMMON SHARED topic.desired$, data.inputted$, n, i

If the database file doesn’t exist yet, create it OPEN "database" FOR APPEND AS 1

and polish it up. CLOSE

Prepare to copy from hard disk’s database file to RAM. OPEN "database" FOR INPUT AS 1

Make n (the number of topics) start at 0. n = 0

Repeat the following, until reaching end of database file: DO UNTIL EOF(1)

Increase the number of topics n = n + 1

becausee inputting another topic from the database file LINE INPUT #1, topic$(n)

and inputting the topic’s data. LINE INPUT #1, data$(n)

Do that repeatedly until the database is done, LOOP

then close the database file. CLOSE

Do the following loop repeatedly: DO

Clear the screen. CLS

Ask the human, "What topic interests you?" PRINT "What topic interests you? ";

Remind the human to type "?" if unsure, "x" to exit. PRINT "(If unsure, type a question mark. To exit, type an x.)"

Make the human’s response be called topic.desired$. 10 LINE INPUT topic.desired$

If human confused, list all topics & ask human again. IF topic.desired$ = "?" THEN list.all.topics: GOTO 10

If the human’s response is "x", exit from the loop. IF topic.desired$ = "x" THEN EXIT DO

Otherwise, capitalize the response & delete extra blanks. topic.desired$ = UCASE$(LTRIM$(RTRIM$(topic.desired$)))

Search for the topic that the human requested. search.for.topic

Repeat that loop until the human types "x". LOOP

Prepare to copy from RAM to hard disk’s database file. OPEN "database" FOR OUTPUT AS 1

For all the topics, FOR i = 1 TO n

copy topic from the RAM to the hard disk’s database file PRINT #1, topic$(i)

and also copy the topic’s data. PRINT #1, data$(i)

Do that repeatedly, until all the topics are done, NEXT

then close the database file. CLOSE

Alphabetical database

Instead of chronological order, you might prefer alphabetical order.

For example, suppose you feed the computer information about SUE then CAROL then ZELDA then ALICE then JANE. Here’s what the computer’s memory would look like, in each kind of order:

Chronological order Alphabetical order

SUE ALICE

CAROL CAROL

ZELDA JANE

ALICE SUE

JANE ZELDA

Which is better: chronological order or alphabetical order?

Chronological order lets you quickly add a new name (just add it at the end of the list), but finding a name in the list is slow (since the list looks disorganized). Alphabetical order lets you find a name faster (since the list is alphabetized), but adding a new name to the alphabetized list is slow (since the only way to insert the new name is to make room for it by shoving other names out of the way).

So which is better?

Chronological order is the simplest to program and the fastest for inserting.

Alphabetical order is the fastest for finding information.

If you want to store the names in alphabetical order instead of chronological order, use these new versions of three SUB procedures:

Here’s how to search for the topic the human requested: SUB search.for.topic

What’s the topic’s position in database? 0 is "too low", too.low = 0

but n + 1 is "too high". too.high = n + 1

Try guesses in between, as follows: DO

Find average (rounded up) of "too low" & "too high". i = (too.low + too.high + 1) \ 2

If average is too high, just do "missing.topic". IF i = too.high THEN missing.topic: EXIT SUB

If the topic is found, just do "found.the.topic". IF topic$(i) = topic.desired$ THEN found.the.topic: EXIT SUB

Otherwise, adjust "too high" or "too low", IF topic$(i) > topic.desired$ THEN too.high = i ELSE too.low = i

then try another guess. LOOP

END SUB

Here’s how to delete the topic: SUB delete.the.topic

Decrease the number of topics. n = n - 1

Close the gap from the deleted topic, FOR j = i TO n

by moving topics topic$(j) = topic$(j + 1)

and their data. data$(j) = data$(j + 1)

NEXT

END SUB

Here’s how to insert the topic: SUB insert.the.topic

Increase the number of topics. n = n + 1

To make room for the new topic, FOR j = n TO i + 1 STEP -1

move other topics out of the way topic$(j) = topic$(j - 1)

and move their data. data$(j) = data$(j - 1)

When the moving is done, NEXT

insert the new topic topic$(i) = topic.desired$

and its data. data$(i) = data.inputted$

END SUB

That new version of search.for.topic runs faster than the chronological version, because searching through an alphabetical list is faster than searching through a chronological list. (To search through the alphabetical list super-quickly, the new version of search.for.topic uses a trick called binary search.)

Unfortunately, the new versions of delete.the.topic and insert.the.topic run slower than the chronological versions. To get the high speed of the new search method, you must accept the slowness of the new delete & insert methods.

You’ve seen that chronological order is fast for inserting and deleting but slow for searching, whereas alphabetical order is exactly the opposite: it’s fast for searching but slow for inserting or deleting.

Tree-structured database

Instead of using chronological order or alphabetical order, advanced programmers use a tree. Like chronological order, a tree lets you insert and delete quickly. Like alphabetical order, a tree lets you search quickly also.

Poets say, "only God can make a tree." Does that mean advanced programmers are God?

To learn how to make a tree, begin by sketching a picture of a tree on paper. Since N is the alphabet’s middle letter, begin by writing the letter N, and put two arrows underneath it:

N

The left arrow is called the before-arrow; it will point to the names that come alphabetically before N. The right arrow is called the after-arrow; it will point to the names that come alphabetically after N.

For example, suppose your first topic is SUE. Since SUE comes alphabetically after N, put SUE at the tip of N’s after-arrow:

N

SUE

Suppose your next topic is CAROL. Since CAROL comes alphabetically before N, put CAROL at the tip of N’s before-arrow:

N

CAROL SUE

Suppose your next topic is ZELDA. Since ZELDA comes after N, we’d like to put ZELDA at the tip of N’s after-arrow; but SUE’s already stolen that position. So compare ZELDA against SUE. Since ZELDA comes after SUE, put ZELDA at the tip of SUE’s after-arrow:

N

CAROL SUE

ZELDA

Suppose your next topic is ALICE. Since ALICE comes before N, look at the tip of N’s before-arrow. Since CAROL’s stolen that position, compare ALICE against CAROL; since ALICE comes before CAROL, put ALICE at the tip of CAROL’s before-arrow:

N

CAROL SUE

ALICE ZELDA

 

Suppose your next topic is JANE. Since JANE comes before N, look at the tip of N’s before-arrow. Since CAROL’s stolen that position, compare JANE against CAROL; since JANE comes after CAROL, put JANE at the tip of CAROL’s after-arrow:

N

CAROL SUE

ALICE JANE ZELDA

If the next few topics are FRED, then LOU, then RON, then BOB, the tree looks like this:

N

CAROL SUE

ALICE JANE RON ZELDA

BOB FRED LOU

Look at the arrows that point down from N. N’s before-arrow points to the group of names that come alphabetically before N (such as CAROL, ALICE, JANE, BOB, FRED, and LOU); N’s after-arrow points to the group of names that come alphabetically after N (such as SUE, RON, and ZELDA). Similarly, CAROL’s before-arrow points to the group of names that come alphabetically before CAROL (such as ALICE and BOB); CAROL’s after-arrow points to the group of names that come alphabetically after CAROL (such as JANE, FRED, and LOU).

Programmers treat the tree as if it were a "family tree". CAROL is called the parent of ALICE and JANE, who are therefore called CAROL’s children. CAROL is called the ancestor of ALICE, JANE, BOB, FRED, and LOU, who are therefore called CAROL’s descendants. The arrows are called pointers.

To make the tree more useful, begin with "N !" instead of "N" (so you can choose "N" as a topic later), and number the topics in the order they appeared: since SUE was the first topic, put "1" in front of SUE; since CAROL was the second topic, put "2" in front of CAROL; since ZELDA was the third topic, put "3" in front of ZELDA, like this:

N !

2CAROL 1SUE

4ALICE 5JANE 8RON 3ZELDA

9BOB 6FRED7LOU

To describe the tree to the computer, store this table in the computer’s memory:

Topic Where the before-arrow points Where the after-arrow points

0 N ! 2 1

1 SUE 8 3

2 CAROL 4 5

3 ZELDA 0 0

4 ALICE 0 9

5 JANE 6 7

6 FRED 0 0

7 LOU 0 0

8 RON 0 0

9 BOB 0 0

That table represents the tree and is called the tree’s representation.

The table’s left column is in chronological order, but the other columns give information about alphabetizing. So a tree combines chronological order with alphabetical order: it combines the advantages of both. Adding a new topic to the tree is quick and easy (as in chronological order): just add the name to the bottom of the list, and adjust a few arrows. Using the tree to search for a topic is quick and easy (as in alphabetical order): just follow the arrows.

Editions 11-20 of this book contained a program that created a tree in a random-access data file. Phone me at 617-666-2666 to find out which editions are still available and their prices. But the best way to create a big, sophisticated database is to buy a database program such as Q&A (which I explained in the database chapter) or use a database programming language such as DBASE (which I’ll explain in the next chapter).

SHELL

In the middle of your program, you can make the computer perform a DOS command! Just say SHELL, and put the DOS command in quotation marks.

For example, this program tells you which version of DOS you’re using:

CLS

SHELL "ver"

This program displays a directory of all your files:

CLS

SHELL "dir /w"

This program changes the name JOE.BAS to FRED.BAS:

CLS

SHELL "rename joe.bas fred.bas"

This program deletes JOE.BAS from your hard disk:

CLS

SHELL "del joe.bas"

This program makes the computer run Windows:

CLS

SHELL "win"

Short cuts

Here are some short cuts:

To see what files are on your hard disk,

you can say FILES (instead of SHELL "dir /w").

To delete JOE.BAS from your hard disk,

you can say KILL "joe.bas" (instead of SHELL "del joe.bas").

To change the name JOE.BAS to FRED.BAS,

you can say NAME "joe.bas" AS "fred.bas" (instead of SHELL "rename joe.bas fred.bas").

ON ERROR GOTO

You can improve the way that the computer handles errors.

Errors in a simple program

Here’s a simple program that divides two numbers and prints their quotient:

CLS

INPUT "What's your favorite number"; a

INPUT "What's another favorite number"; b

PRINT "The first number divided by the second is"; a / b

The program works for most numbers. But when the computer tries to divide, the computer will gripe if b is 0 (since you can’t divide by 0) or if the quotient’s too big to be a single-precision real number. (For example, if you try dividing 1E38 by .1, the answer is supposed to be 1E39; but the computer will gripe that the answer is too big for the computer to handle, since the biggest permissible single-precision real number is 3.402823E38.)

If b is 0, the computer will print this error message:

Division by zero

If the quotient’s too big to be a single-precision real number, the computer will print this error message:

Overflow

When the computer prints one of those error messages, the computer stops running the program and shows you the blue screen.

That confuses beginners! If a beginner tries to run your program and sees the computer say "Division by zero" or "Overflow" on a blue screen, the beginner might not understand what the computer means and might not understand what to do next.

Improved error-handling

Instead of letting the computer say "Division by zero" or "Overflow", let’s make the computer print this easier-to-understand message —

I can't handle that pair of numbers.

Please pick a different pair of numbers instead.

and then let the human type a new pair of numbers.

To do that, put these lines at the bottom of your program —

PRINT "I can't handle that pair of numbers."

PRINT "Please pick a different pair of numbers instead."

and tell the computer to do those lines whenever an error occurs in computing the quotient.

Here’s how:

CLS

10 INPUT "What's your favorite number"; a

INPUT "What's another favorite number"; b

ON ERROR GOTO 1000

quotient = a / b

ON ERROR GOTO 0

PRINT "The first number divided by the second is"; quotient

END

1000 PRINT "I can't handle that pair of numbers."

PRINT "Please pick a different pair of numbers instead."

PRINT

RESUME 10

In that program, the source of the error (a / b) is isolated: it’s made into a separate line (quotient = a / b). Above that line, say ON ERROR GOTO 1000; below that line, say ON ERROR GOTO 0. The ON ERROR GOTO 1000 means: if an error occurs in the indented line underneath, go to line 1000. Line 1000 is the beginning of the error-handling routine. The error-handling routine says that when an error occurs, print this —

I can't handle that pair of numbers.

Please pick a different pair of numbers instead.

then print a blank line and then RESUME the program at line 10, which makes the computer ask again "What’s your favorite number?"

Remember:

The bottom line of the error-handling routine should say RESUME.

The bottom line of the rest of the program should say END.

"ON ERROR GOTO 1000" should be paired with "ON ERROR GOTO 0".

"ON ERROR GOTO 1000" means "Henceforth, if an error ever occurs, GOTO line 1000."

"ON ERROR GOTO 0" means "Henceforth, if an error ever occurs, go nowhere; just process the error normally."

In that program, the bottom four lines are called the error-handling routine or error handler or error trap. Making the computer go to the error trap is called trapping the error.

Error numbers

Besides "Division by zero" and "Overflow", there are many other errors that a program can make. Each error has a code number:

Code # Message

1 NEXT without FOR

2 Syntax error

3 RETURN without GOSUB

4 Out of DATA

5 Illegal function call

6 Overflow

7 Out of memory

8 Label not defined

9 Subscript out of range

10 Duplicate definition

11 Division by zero

12 Illegal in direct mode

13 Type mismatch

14 Out of string space

16 String formula too complex

17 Cannot continue

18 Function not defined

19 No RESUME

20 RESUME without error

24 Device timeout

25 Device fault

26 FOR without NEXT

27 Out of paper

29 WHILE without WEND

30 WEND without WHILE

33 Duplicate label

35 Subprogram not defined

37 Argument-count mismatch

38 Array not defined

40 Variable required

50 FIELD overflow

51 Internal error

52 Bad file name or number

53 File not found

54 Bad file mode

55 File already open

56 FIELD statement active

57 Device I/O error

58 File already exists

59 Bad record length

61 Disk full

62 Input past end of file

63 Bad record number

64 Bad file name

67 Too many files

68 Device unavailable

69 Communication-buffer overflow

70 Permission denied

71 Disk not ready

72 Disk-media error

73 Advanced feature unavailable

74 Rename across disks

75 Path/File access error

76 Path not found

Whenever the computer detects an error, the computer makes ERR be the error-code number. For example, when the computer detects an Overflow error, the computer makes ERR be 6. If you say —

PRINT ERR

the computer will print 6.

You can use ERR in the error-handling routine. For example, here’s how to say "if the error was Overflow":

IF ERR = 6 THEN

At the bottom of the error-handling routine, the RESUME line automatically makes the computer reset ERR to 0, so the computer is prepared to handle future errors.

Here’s the sophisticated way to divide two numbers:

CLS

10 INPUT "What's your favorite number"; a

INPUT "What's another favorite number"; b

ON ERROR GOTO 1000

quotient = a / b

ON ERROR GOTO 0

PRINT "The first number divided by the second is"; quotient

END

1000 SELECT CASE ERR

CASE 11

PRINT "I can't divide by zero."

CASE 6

PRINT "The answer is too big for me to handle."

CASE ELSE

PRINT "I'm having difficulty."

END SELECT

PRINT "Please pick a different pair of numbers instead."

PRINT

RESUME 10

In that program, the error-handling routine says:

If the error-code number is 11 (which means "Division by zero"), print "I can’t divide by zero."

If the error-code number is 6 ("Overflow"), print "The answer is too big for me to handle."

If the error-code number is otherwise, print "I’m having difficulty."

After printing one of those error messages, the computer will print "Please pick a different pair of numbers instead". Then the computer will do RESUME 10, which goes back to line 10 and also resets ERR to 0.

Unnumbered RESUME

If you don’t put any number after RESUME, the computer will go back to the line that contained the error.

If you say RESUME NEXT, the computer will go to the line underneath the line that contained the error. To make RESUME NEXT work properly, the line that contained the error should consists of just one statement (instead of statements separated by colons).

Memory cells

The computer’s memory chips consist of many memory cells. Each cell holds an integer from 0 to 255. For example, cell #49837 might hold the integer 139.

Segments

The first 65536 cells (cell #0 through cell #65535) form segment 0. The next 65536 cells are in the next segment, which is called segment 16. The next 65536 cells are in segment 32; the next 65536 cells are in segment 48; the next 65536 cells are in segment 64; the next 65536 cells are in segment 80; etc. Notice that the segment numbers are multiples of 16.

Within each segment, the cells are numbered from 0 to 65535. For example, the first cell in segment 16 is called "cell #0 of segment 16"; the next cell in segment 16 is called "cell #1 of segment 16"; the last cell in segment 16 is called "cell #65535 of segment 16".

PEEK

This program finds out what number’s in cell #49837 of segment 0:

CLS

DEF SEG = 0

PRINT PEEK(49837)

The "DEF SEG = 0" tells the computer to use the memory’s main SEGment, which is SEGment 0. The bottom line makes the computer PEEK at cell #49837, find the number in that cell, and print that number on your screen. The number it prints will be an integer from 0 to 255. For example, it might be 139.

When dealing with memory cells, make sure your program begins with a DEF SEG line, to tell the computer which segment to look in. If you forget to say DEF SEG, the computer will look in its "favorite" segment, which is not segment 0.

Cell #1047

In cell #1047 of segment 0, the computer puts a number that describes the state of your keyboard. The computer computes that number by using this chart:

Start at 0.

Add 1 if the right SHIFT key is being pressed now.

Add 2 if the left SHIFT key is being pressed now.

Add 4 if either Ctrl key is being pressed now.

Add 8 if either Alt key is being pressed now.

Add 16 if the SCROLL LOCK is turned on (by an earlier keypress).

Add 32 if the NUM LOCK is turned on (by an earlier keypress).

Add 64 if the CAPS LOCK is turned on (by an earlier keypress).

Add 128 if the INSERT is turned on (by an earlier keypress).

For example, if NUM LOCK and INSERT are turned on, that cell contains 32+128, which is 160.

This program shows you what’s in that cell:

CLS

DEF SEG = 0

PRINT PEEK(1047)

For example, if NUM LOCK and INSERT are turned on, the computer will print 160.

 

Loop This program peeks at cell #1047 repeatedly:

CLS

DEF SEG = 0

DO

PRINT PEEK(1047)

LOOP

If the NUM LOCK and INSERT keys are turned on, the computer will repeatedly print 160, like this:

160

160

160

etc.

While that program keeps running, try pressing the SHIFT, Ctrl, Alt, SCROLL LOCK, NUM LOCK, CAPS LOCK, and INSERT keys. Each time you press any of those keys, the number 160 will change to a different number.

Cell #1048

In cell #1048 of segment 0, the computer puts a supplementary number describing your keyboard’s state. That number is computed as follows:

Start at 0.

Add 1 if the left Ctrl key is being pressed now.

Add 2 if the left Alt key is being pressed now.

Add 16 if the SCROLL LOCK key is being pressed now.

Add 32 if the NUM LOCK key is being pressed now.

Add 64 if the CAPS LOCK key is being pressed now.

Add 128 if the INSERT key is being pressed now.

This program shows you what’s in both of the keyboard-state cells:

CLS

DEF SEG = 0

DO

PRINT PEEK(1047), PEEK(1048)

LOOP

While running that program, try pressing the Ctrl, Alt, SCROLL LOCK, NUM LOCK, CAPS LOCK, and INSERT keys. Watch how the numbers on the screen change!

That’s how computers work: in memory cells, the computer stores code numbers that represent what you and the computer are doing.

POKE

Let’s make the computer turn on the CAPS LOCK (so all your typing will be capitalized), NUM LOCK (so typing on the numeric keypad will create numbers instead of arrows), and INSERT (so typing in the middle of a document will make the other words move out of the way).

In cell #1047, the code number for NUM LOCK is 32, CAPS LOCK is 64, and INSERT is 128, so the code number for their combination is 32+64+128, which is 224. To turn on CAPS LOCK, NUM LOCK, and INSERT, just put the code number 224 into cell #1047. Here’s how:

CLS

DEF SEG = 0

POKE 1047, 224

In that program, "POKE 1047, 224" means "put, into cell #1047, the number 224".

Danger Poking into cell 1047 or 1048 is safe (if you say DEF SEG = 0), but poking into other cells can be dangerous, since some of those cells are where the computer stores notes about your program, operating system, disks, and other devices. Poking wrong info into those cells can wreck your program, operating system, and the info on your disks.