Qbasic Tutorial : Learn Qbasic in a fast, simple,short, and intuitive way. Honest Effort Required.

--- Qbasic ---

# CHAPTER 9

## Data Types, Record, and RANDOM ACCESS FILE

### DATA TYPES

There are many data types in Qbasic :

1. integer
An integer occupies 16 bits (1 bit may store 0 or 1, and 8 bits = 1 byte), Hence maximum value an integer can hold = 2^16 = 65536, or +/- 32767.
2. long
long = long interger, it occupies 32 bits. Hence its maximum value is 2^32 or +/- 2^31 - 1
3. single
single = single precision real number, it occupies 32 bits, and it can represent a real number to 7 significant figures.
4. double
double = double precision real number, it occupies 64 bits, and it can represent a real number up to 16 significant figures.
5. string
String consists of several bytes. String must be enclosed within quotation marks, e.g. a\$ = "Hong Kong and Kowloon".

### If we do not declare what data type a variable takes, Qbasic would assume that it is a single precision number.

Exercise : How many bytes are there in integer, long, single, double ? ( 1 byte = 8 bits)

Ans : integer 2 bytes ; long 4 bytes; single 4 bytes; double 8 bytes.

### DECLARATION OF DATA TYPES

There are 3 ways to declare data type of variables :

1. By the first letter of the variable name :
defint i-n
Here defint (=define integer) is a Qbasic keyword. It means that if that variable name begins with letters {i,j,k,l,n}, that variable is to be regarded as integer. Hence variables "icount, linecount, mpage, nrow ... " would all be treated as integers.

defdbl a-h,o-z
Here defdbl (= define double) is also a Qbasic keyword. Here all variables whose name begin with a to h, or o to z are to be regarded as double precision numbers. e.g. xmean, std, .... are regarded by Qbasic as double precision numbers.

defstr (=define string), deflng (=define long), defsng (=define single) have similar usage as above.

2. With a special character at the end of the variable name.
1. count%, row%, column% ....
% informs the computer that they are integers, hence count%, row%, column% .... are all integer.
2. count&, row&, column& ....
& informs the computer that they are long integer, hence count&, row&, column& ... are all long integers.
3. mean!, std!, deviation! ......
! informs the computer that they are single precision real number, hence mean!, std!, deviation! ... are all single precision numbers.
4. mean#, std#, deviation# .....
# that they are double precision real number, hence mean#, std#, deviation# .... are all double precision numbers.
5. name\$, telephone\$, mark\$ .....
\$ stands for string. Hence name\$, telephone\$, mark\$ ... are all string.

3. With the use of dimension statement. Previously, we use " dim " to declare arrays. But dimension statement may also be used to declare variable types, e.g.
dim n as integer
dim a(4,5,3) as long
dim xmean as single
dim b(3,4) as double
dim name as string
dim icount as integer, linecount as integer, nrow as integer
Note : it is rather clumsy to declare variables in Qbasic. Pascal and C are better in this aspect, e.g.

in C
int icount, linecount, nrow;
or in Pascal
var
icount, linecount, nrow : integer;
If someone would implement in Qbasic
dim icount, linecount, nrow as integer
to mean icount, linecount, nrow are all integers, then that would be more convenient. In reality, if we declare in this way, Qbasic would only regard nrow as integer, the rest ( icount, linecount ) would all be regarded as single.

## RECORD

Suppose we wish to create a master file for the students. We wish to record down their name, age, sex, tel (=telephone number). First we define RECORD type :

type strecord
sname as string*30
age as integer
sex as string*1
tel as string*10
activeflag as integer
end type
dim ss as strecord

Note :

1. Because "name" is a Qbasic keyword, therefore we have used "sname" instead.

2. TYPE ....
.... as ...
.... as ...
END TYPE
TYPE statement "TYPE ...... END TYPE" is used to define new data types, apart from the usual integer, long, single, double, string.
After the "type statement", we use "dimension statement to declare which variables are of this type, e.g.
dim ss as strecord
dim tt as strecord
then both ss, tt are of the record type defined above.

3. Exercise : Find out how many bytes the variable "ss" defined above will take.
Ans : 30 + 2 + 1 + 10 + 2 = 45 bytes.

4. Suppose we now have
TYPE stockrecord
sname as string*100
location as string*50
price as double
supplier as long
quantity as long
reorder as long
END TYPE
DIM st as stockrecord

Exercise : compute how many bytes "st" will take.
Ans : 100 + 50 + 8 + 4 + 4 + 4 = 170 bytes.

5. len(..) is a Qbasic built-in function. Its main use is to find out the length of strings, e.g.
print len("Hong Kong")
then the computer will print : 9 ( as "Hong Kong" is 9 bytes long).
But len(..) may also be used on record variables. It will print out the number of bytes that variable will occupy, e.g.
print len(st)
Then computer will print : 170 ( the record variable "st" is 170 bytes long).

6. Exercise : Find out the meaning of the following Qbasic built-in string functions, with the help of online manual (Shift + F1) :
1. mid\$(a\$,n,m)
2. left\$(a\$,n)
3. right\$(a\$,n)
4. lcase\$(a\$)
5. ucase\$(a\$)
6. instr(a\$, b\$)

7. Exercise : suppose you have a random files of 1000 records, and the length of one record is 170 bytes. As the file is a "random file" we may access the records randomly (the Qbasic statements to do that will be explained later). Now suppose you find that one record is no longer used, and you want to delete it, how would you do that?
Ans : It is not easy to delete a record from a random file. Hence the usual practice is to define another variable within the record, e.g. in the "strecord", we have
activeflag as integer
When the record is active, we set activeflag to 1. When it is no longer needed, and we wish to delete it, we set activeflag to 0. Hence a check of this variable will show whether it has been deleted or not.

Here is a program to create a master file.

```
DEFLNG I-N
DEFDBL A-H, O-Z

TYPE strecord
sname AS STRING * 30
age AS INTEGER
sex AS STRING * 1
tel AS STRING * 10
activeflag AS INTEGER
END TYPE

DIM ss AS strecord

CLS 0
mrecordlength = LEN(ss)
PRINT "Record Length = "; mrecordlength

OPEN "c:\test\q9_mas" FOR RANDOM AS #1 LEN = mrecordlength

irecord = 1

L20:
PRINT
INPUT "Name "; ss.sname

IF LEFT\$(ss.sname, 4) = "****" THEN        (NOTE : because sname is 30 bytes long,
CLOSE 1                                        we compare only the leftmost
END                                            4 bytes.  Qbasic would reqard
END IF                                             2 strings of different lengths unequal,
even if their non-blank parts are
L40:                                                   equal.)
INPUT "Age"; ss.age
IF ss.age > 1000 OR ss.age < 0 THEN        (NOTE : this is for data validation.
SOUND 2000, 5                                 Data Validation must be carried
GOTO L40                                      out to make the program ROBUST.
END IF                                             There is a saying
"Garbage in, Garbage out" )
L60:
INPUT "Sex"; ss.sex

ss.sex = LEFT\$(ss.sex, 1)                  (NOTE : we only use 1 character for sex. )

IF ss.sex = "m" THEN                       (NOTE : we change all lower case to upper
ss.sex = "M"                                   case, hence M=male, F=female, and
ELSEIF ss.sex = "f" THEN                           m, f would not be used.)
ss.sex = "F"
END IF

IF NOT (ss.sex = "M" OR ss.sex = "F") THEN     (NOTE :  data validation procedure.)
SOUND 2000, 5
GOTO L60
END IF

L80:
INPUT "Telephone number "; ss.tel

ss.activeflag = 1                         (NOTE : this means the record has not been
deleted.)
PUT 1, irecord, ss
irecord = irecord + 1
GOTO L20

```

Here is a program to read the above master file.

```DEFLNG I-N
DEFDBL A-H, O-Z

TYPE strecord
sname AS STRING * 30
age AS INTEGER
sex AS STRING * 1
tel AS STRING * 10
activeflag AS INTEGER
END TYPE

DIM ss AS strecord

PRINT LEN(ss)

OPEN "c:\test\q9_mas" FOR RANDOM AS #1 LEN = 45
(NOTE : it is advisable to put LEN=LEN(ss)
CLS 0
mrecord = LOF(1) / 45                      (NOTE : LOF(1) = length of file of file 1
PRINT "Number of records = "; mrecord            LOF(n) is a Qbasic built-in function.
no. of records in random file =
LOF(1) / LEN(ss) )
L20:
INPUT "Enter record number (-999 = end) "; i

IF i = -999 THEN
CLOSE 1
END
END IF

IF NOT (i >= 1 AND i <= mrecord) THEN      (NOTE : record number starts from 1
SOUND 1500, 5                                 to mrecord, hence we check
PRINT "Non-existent record"                   for  1 <= i <= mrecord.)
GOTO L20
END IF

GET 1, i, ss
PRINT
PRINT USING "Name           : \         \"; ss.sname     (NOTE: \   \ length
PRINT USING "Age            : ##"; ss.age                  of string to be printed.
PRINT USING "Sex            : !"; ss.sex                   ! = print only 1 c
PRINT USING "Tel. No.       : \         \"; ss.tel             character for that
PRINT USING "Active flag    : #"; ss.activeflag                string.)
PRINT
GOTO L20
CLOSE 1
END

``` Note :

1. Suppose we have two record variables, ss and tt , e.g.
TYPE strecord
... as ...
... as ...
END TYPE
dim ss as strecord
dim tt as strecord
then "ss.sname, ss.sex, ss.tel, ss.activeflag" would distinguish them from
"tt.sname, tt.sex, tt.tel, tt.activeflag"

2. Exercise : write a program that prints out all students aged between 17 and 19.

Ans :

```
DEFLNG I-N
DEFDBL A-H, O-Z

TYPE strecord
sname AS STRING * 30
age AS INTEGER
sex AS STRING * 1
tel AS STRING * 10
activeflag AS INTEGER
END TYPE

DIM ss AS strecord

OPEN "c:\test\q9_mas" FOR RANDOM AS #1 LEN = LEN(ss)
OPEN "c:\test\q9_out.txt" FOR OUTPUT AS #2

CLS 0
mrecord = LOF(1) / LEN(ss)
PRINT "Number of records = "; mrecord

PRINT #2, "THOSE STUDENTS WHO ARE MALE AND AGED BETWEEN 17 AND 19"
PRINT #2, " "

FOR i = 1 TO mrecord
GET 1, i, ss
IF LEFT\$(ss.sex, 1) = "M" AND ss.age >= 17 AND ss.age <= 19 THEN
PRINT #2, USING " \         \   ##  !  \      \"; ss.sname; ss.age; ss.sex; ss.tel
END IF
NEXT i

CLOSE 1
CLOSE 2
END

```

Exercise : we input the name of a student, (or part of the name), and ask the computer to print out those records that match the name (or part of the name).

Ans :

```
DEFLNG I-N
DEFDBL A-H, O-Z

TYPE strecord
sname AS STRING * 30
age AS INTEGER
sex AS STRING * 1
tel AS STRING * 10
activeflag AS INTEGER
END TYPE

DIM ss AS strecord

OPEN "c:\test\q9_mas" FOR RANDOM AS #1 LEN = LEN(ss)

CLS 0
mrecord = LOF(1) / LEN(ss)
PRINT "Number of records = "; mrecord

L20:
INPUT "Name to search "; dummy\$
IF dummy\$ = "" THEN
CLOSE
END
END IF
dumb\$ = UCASE\$(dummy\$)

FOR i = 1 TO mrecord

GET 1, i, ss
duma\$ = UCASE\$(ss.sname)

IF INSTR(duma\$, dumb\$) <> 0 THEN
PRINT
PRINT USING "Name      : \         \"; ss.sname
PRINT USING "Age       : ##"; ss.age
PRINT USING "Sex       : !"; ss.sex
PRINT USING "Tel.      : \         \"; ss.tel
PRINT
END IF

NEXT i
PRINT
GOTO L20

```