An interpreted computer language is a high-level language that is translated into binary machine code each time it is read from a source file. Disadvantages of interpreted languages are mainly that there is a translation time penalty each time the program is run, and the language interpreter must be present on each computer that will run the program. However, as a development tool interpreted languages are useful because a program prototype can be written and tested quickly, and since most interpreters step through the program line by line errors are easily localized and identified. Since most assemblers and compilers have a steep learning curve just to master the development environment interpreters are also ideal as learning tools.
CIS 120 is about computer concepts in general, not about programming in particular. With that in mind only the very essential QBasic statements, functions, and operators will be used. Recall that, as a minimum, we want a program to organize data, calculate results, and present the results. We will be looking at ways QBasic can get user input, manipulate the input (data), control program flow as needed, and produce output useful to the user. Consult QBasic Help for more details of all commands discussed.
QBasic supports the basic data types discussed in the text book: integers, real numbers (floating point), characters, and Boolean as well as character strings, arrays, and records. We will only be working with the basic, sometimes called "primitive," types. In QBasic the character string is considered a basic type rather than a data structure. Data types are specified by a special character appended to the end of the variable name:
count% ' an integer type balance! ' a single precision real number nationalDebt# ' a double precision real number lastName$ ' a character string ch$ ' single characters are just 1-character strings
QBasic uses mostly familiar or intuitive operators, such as +, -, *,and / for addition, subtraction, multiplication, and division. An operator that may be new to you that is supported in virtually all programming languages is the Modulus division operator. Modulus division returns the remainder rather than the quotient. In QBasic the modulus operator is MOD. This differs from the "C Family" of languages that use % for modulus division. For example 19 MOD 4 is 3: 19 divided by 4 is 4 with a remainder of 3. Modulus division is very useful for many problems in computers; think back to our procedure for converting a decimal number to binary or hexadecimal. We started with the highest power of the base that could be divided into our decimal number, then kept working down by dividing the remainder by each successive lower power of the base.
Boolean conditions (named after George Boole) are tested with the familiar < and > symbols used in mathematics for "less than" and "greater than". "Less than or equal to" and "greater than or equal to" use the <= and >= operators respectively. Equality is tested with the = operator and inequality ( "not equal to" ) is tested with the <> operator. This differs from the "C Family" of languages that use -= for equality and != for inequality. Look at QBasic Help Contents under the topic "Basic Character Set." Note that the BASIC language uses the same operator ( = ) for assignment and equality; the interpreter knows the difference from context.
We will use the INPUT statement for program input and the PRINT statement for program output. The following QBasic statements will prompt the user for a name and then issue a greeting:
REM input1.bas CLS ' clear the screen INPUT "Enter your name: ", name$ ' get user name PRINT "Hello "; name$; ", welcome to CIS 120!" ' say hello
Enter your name: Mike Hello Mike, welcome to CIS 120!
The INPUT statement takes an optional prompt string in quotation marks followed by a comma separated variable list. It is generally best to only fill one input variable for each INPUT statement. Notice how any extra spaces must be included inside the quoted strings in the PRINT statement, the semi-colons separating the PRINT arguments cause the arguments to run together.
You can use a semi-colon following the prompt string to have QBasic automatically add a question mark and a space, but I suggest you only use one form and explicitly write it as a question when desired. The following 2 INPUT statements are identical:
REM input2.bas INPUT "What is your name"; name$ ' prompt is a question INPUT "What is your name? ", name$ ' so is this one
REM input2.bas What is your name? Fred What is your name? Fred
Note that the name variable had the "$" character appended to identify name as a string variable; use the "% " character for integer variables, "! " for single-precision variables, and "#" for double- precision variables. For the little programs we will write in this class you can just use single-precision for all numeric data types. Note also that the "'" character is the comment delimiter.
The QBasic control statement that allows a program to branch to different areas based on some condition is IF . . . THEN . . . ELSE.
REM if1.bas CLS ' clear the screen INPUT "What is your total order? ", order! ' how much did customer spend IF order! < 100! THEN ' check for first condition discount! = order! * .1 END IF IF order! >= 100 THEN ' check for second condition discount! = order * .15 END IF PRINT "Your discount is $"; discount! ' display results
What is your total order? 50 Your discount is $ 5 What is your total order? 120 Your discount is $ 18Another way to write the test condition would be using IF . . . THEN . . . ELSEIF:
REM ifelse1.bas CLS ' clear the screen INPUT "What is your total order? ", order! ' how much did customer spend IF order! < 100! THEN discount! = order! * .1 ELSEIF order! >= 100 THEN ' better, clearer that we are discount! = order * .15 ' doing an "either - or" test END IF PRINT "Your discount is $"; discount! ' display results
REM ifelse2.bas CLS ' clear the screen INPUT "What is your total order? ", order! ' how much did customer spend IF order! < 100! THEN discount! = order! * .1 ELSEIF order! > 500 THEN ' better, clearer that we are discount! = order * .15 ' doing an "either - or" test ELSE ' easy to add 3rd test discount! = order * .2 ' big spender gets big discount END IF PRINT "Your discount is $"; discount! ' display results
What is your total order? 80 Your discount is $ 8 What is your total order? 200 Your discount is $ 30 What is your total order? 600 Your discount is $ 120
The QBasic control structures that allows a program to repeat a certain section of code more than once based on the value of a condition are DO . . . LOOP and FOR . . . NEXT. All loops can be written with one basic form even if that one form is not always the clearest or most efficient. However, when the number of repetitions is known in advance, the FOR . . . NEXT loop is generally preferred. QBasic also supports the older WHILE . . . WEND loop construct.
Here is a simple QBasic loop using both forms:
REM loop1.bas
REM simple loop using DO . . . WHILE
CLS
i% = 0 ' loop index counter
maxCount% = 10 ' number of times to repeat
DO WHILE i% < maxCount%
PRINT i%; ' display value of loop index
i% = i% + 1 ' IMPORTANT! increment the index so
LOOP ' we don't have an infinite loop
REM simple loop using FOR ... NEXT
PRINT ' blank line for spacing
FOR i = 0 TO 9 ' when the number or iterations are
PRINT i; ' known in advance this form is
NEXT i ' "self-documenting
PRINT
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
This next loop is a bit more involved; it prompts the user for a number and saves it in a variable called sum, then enters a loop where it prompts for another number to add to sum. Note how, before entering the loop, the answer variable is pre-loaded to force at least one pass through the loop. At the end of each loop the user is asked if she wants to continue. Note also how the response is converted to upper case to simplify the test for a no answer.
REM loop2.bas
REM add numbers until user says no
CLS
INPUT "Enter first number: ", sum! ' get first number to get started
answer$ = "Y" ' assume user wants to continue
DO WHILE answer$ <> "N" ' loop until user answers no
INPUT "Enter next number: "; n! ' get next number
sum! = sum! + n! ' add next number to sum
PRINT "Sum = "; sum! ' display the sum
INPUT "Continue? "; answer$ ' add another number?
answer$ = UCASE$(answer$) ' convert to upper case so only
LOOP ' one char is tested
Enter first number: 3 Enter next number: ? 5.5 Sum = 8.5 Continue? ? y Enter next number: ? 1.2 Sum = 9.7 Continue? ? y Enter next number: ? 10 Sum = 19.7 Continue? ? n
Read the QBasic Help topic on the DO . . . LOOP. What other ways could this loop be written? Is another way more "logical" or more readable?
QBasic has some interesting and useful string manipulation functions. Research the LEN, MID$, ASC, and HEX$ functions in QBasic Help. Here is an example of how you might extract various pieces of a data record to build a string for a report:
REM string1.bas CLS name$ = "John Paul Jones" PRINT "Name (First, Middle, Last): "; name$ first$ = MID$(name$, 1, 4) ' start at pos 1, get 4 characters middle$ = MID$(name$, 6, 4) ' start at pos 6, get 4 characters last$ = MID$(name$, 11, 5) ' start at pos 11, get 5 characters PRINT "Name (Last, First, Middle): "; PRINT last$; ", "; first$; " "; middle$ ' print last name first
Name (First, Middle, Last): John Paul Jones Name (Last, First, Middle): Jones, John Paul
Here is a way to handle extracting pieces of a string when you don't know where or how long the individual pieces are. Note how the string length function LEN is used as a loop upper bound control; then the MID$ extracts one character at a time, checking for a blank space. Each character is then concatenated (look it up in a dictionary!) to a new string.
REM string2.bas
CLS
name$ = "John Paul Jones"
i% = 1
DO WHILE i% < LEN(name$)
ch$ = MID$(name$, i%, 1) ' get character at index i
IF ch$ = " " THEN EXIT DO ' look for first space
first$ = first$ + ch$ ' build first name from characters
i% = i% + 1 ' increment loop counter
LOOP
PRINT first$ ' display the first name
Recall the discussion of ASCII character codes and the need to frequently know how to represent numbers in hexadecimal as well as decimal:
REM asc_code.bas CLS ch$ = "A" ' assign "A" to 1-character string code% = ASC(ch$) ' get ASCII character code of ch$ ' display ASCII code in decimal and hex PRINT "ASCII "; ch$; " = "; code%; " Decimal", HEX$(code%); " Hexadecimal"
ASCII A = 65 Decimal 41 Hexadecimal
Now if we were to modify the above example to take input from the keyboard inside a loop it might actually be useful from time to time. Hmmm...
Your best source of additional QBasic information is the QBasic Help system. Spend some time looking at the various topics in the Contents, in particular look at "Keywords by Programming Task" then go to the Index and select various keywords. Note that most keyword topics in the Index also show example code snippets. Copy the examples in this document into QBasic then experiment with modifications. You can "View Source," then copy and paste to QBasic. All example code is delimited by <PRE> and </PRE> tags.
Put a copy of qbasic.exe and qbasic.hlp (about 317 Kb for both files) in your working directory, or put them in a directory that is in your PATH. You can download the source files from the links below, or you can copy the code from the examples into a text editor and save them as BASIC source files (the usual extension for BASIC source files is .BAS). Execute a BASIC program in QBasic from the command line as follows:
The best way to learn a language, like learning to play a musical instrument, is to jump in and practice. Look at some examples in the Help topics for various keywords and try to put a few together to do something useful. However, unlike learning a new musical instrument, at least you won't annoy the neighbors or make the dog howl...
Download example source code.
Source files are listed in the order presented above: