CONTINUED FROM "MC-QB-1.TXT" A Guide to QBASIC for Beginners. By Michael Calkins Floresville, Texas, United States E-mail: "mcalkins0@hotmail.com" Please contact me with any corrections, questions specific to this tutorial, or comments. Post general QBASIC questions on: Jack's QBASIC ("http://www.geocities.com/jacksqbasic/") Updates and revisions of this guide will be posted on Jack's QBASIC thanks to Jack Davies. I tried to make sure the examples in this guide perform as described and that the text is factually accurate. If you find errors, please let me know. I wrote most of it quite late at night. And I have been known to make wildly inaccurate assumtions any time of day. 06-07-2005 PART 2: CHAPTER 5 TO CHAPTER 8. (MC-QB-2.TXT) --- 5. Variable assignment, and text/number conversion. Remember variables? We discussed them briefly in the chapter about data types, but I didn't really demonstrate them well. It is time to change that. Variables store values. They are like containers: they hold what you put in them. If you assign a value to a variable, the variable holds and, in a way, becomes that value. How do you assign a value to a variable? You put the variable name, followed by an equals sign (=), followed by an expression. The value of the expression is assigned to and stored in the variable. Number% = 7 The variable is Number%, the value of the expression is 7. The variable, Number%, takes on the value of 7. Until a new value is assigned to Number%, Number% will stand for 7. Also, since we know that "%" is the data type suffix for INTEGER, we know that Number% is an INTEGER Of course the whole line looks like it could be an expression. Isn't the equals sign a relational operator. Yes, but that is not all it can be. You see, an expression has a value. What is the point of having an expression if you don't do anything with the value? That is why expressions can never stand alone. Their value must always be passed to something, anything, that will accept it. If the above line, Number% = 7, were an expression, with the equals sign being a relational operator, to what is the resulting value passed? It can't be, because expressions cannot stand alone. In this case, the equals sign takes on a new meaning. It is an assignment symbol, not a math operator at all. The syntax for assignment is Variablename = Expression. (LET is an obsolete statement that can be used, but why?) Ultimately, the variable is stored in RAM (Random-Access Memory.) Every byte of RAM has a specific address, about which you will learn more later (not necessarily in this guide though). With the above example line (Number% = 7), at the exact location of the variable Number%, 2 bytes of data will be written as an INTEGER: 0000 0000 0000 0111. That is how variables are physically stored. Of course, the QBASIC interpreter must have a mechanism, also in RAM, to remember what your variables' names are, and where exactly in RAM they are. None of this is really relevant to you now, but it is good to know anyway. Let's do some more demonstration: CLS a% = 100 'an INTEGER b% = 20 'an INTEGER c! = 2.5 'a SINGLE PRINT (a% + b%) * c! a% = 31415 'recycling a% and b%, assigning them new values. b% = 10 c% = -4 'new variable, an INTEGER. Not the same as c!. PRINT a% * b% ^ c% c! = a% * b% ^ c% 'recycling c! PRINT c! Screen output: 300 3.1415 3.1415 If you haven't already, definitely by now you will be seeing practical uses for QBASIC programs. They can be your own custom scientific calculators! This will become even more apparent as you progress. When I recycled the variables a%, b%, and c!, I was first of all showing that it can be done, but there are practical reasons to do it too. The more variables you have, the more likely you are to confuse yourself. (For that reason, it is a good idea to give variables descriptive names.) But also, the more variables you have, the more RAM your program requires to store them. It is a good idea to recycle old variables when you can, instead of creating new ones for every part of your program. Here is a more practical demonstration: CLS pi# = 3.141592653589793# 'the "#" after the constant is 'something QBASIC automatically added. 'pi# is a DOUBLE radius! = 10 'SINGLE circum# = pi# * radius! * 2 'more DOUBLEs. area# = pi# * radius! ^ 2 unit$ = "inches" 'a variable-length STRING containing text. PRINT "For a circle with the radius of"; radius!; unit$; ":" PRINT "Circumference:"; circum#; unit$; "." PRINT "Area:"; area#; "square "; unit$; "." Screen output: For a circle with the radius of 10 inches: Circumference: 62.83185307179586 inches. Area: 314.1592653589793 square inches. In fact, nothing prevents us from using a variable in an expression whose value will be assigned to that same variable. Watch: CLS a% = 5 'initial assignment. PRINT a% a% = a% + 10 '2nd assignment. The value from the 1st assignment is 'used in calculating the value to reassign with. PRINT a% a% = a% + 1 '3rd assignment. PRINT a% Screen output: 5 15 16 Now imagine this line of code: a% = "7" Do you see a problem? If you try executing that, QBASIC will step in and tell you "Type mismatch". You are trying to assign a text value to a numeric variable. They are of incompatible data types. Fortunately, QBASIC provides tools for conversion. Please hold that thought. So far, the QBASIC commands you have learned, like DIM, CLS, and PRINT, are all statements. They all stand alone and have no value. They cannot be part of an expression. What is the value of CLS? It has no value. But statements aren't the only QBASIC commands. Functions are commands, that is, they do something, or carry out some action. The difference is that functions always have values. Anything with a value can be part of an expression. Furthermore, functions cannot stand alone. Their value must be passed to something. The value a function becomes is said to be a value it returns. What value does a function return? Each function has its own way of determining its value. It is almost always determined using input parameters. Parameters to functions are enclosed in parentheses. For information on specific functions, see the Help. Now that you know what a function is, we can resume our discussion of data conversion. There is a specific function that converts text into numeric data. It is VAL. To use it we will give it the input STRING as a parameter. a% = VAL("7") Unlike a% = "7", which was impossible, a% = VAL("7") is fine. The VAL function always returns a numeric value, in this case 7. So a% will become 7. What about vice versa? Can we convert numeric values into text? Yes. That is what the STR$ function is for. The parameter to the STR function is a numeric value. STR$ returns a text STRING. STR$ converts the number into text and adds a space character (" ") to the beginning. CLS text$ = STR$(3.14) PRINT "Text: '"; text$; "'" Screen output: Text: ' 3.14' For kicks, let's go conversion crazy: CLS txt$ = "1911" PRINT "'"; txt$; "'" 'original text num% = VAL(txt$) PRINT "("; num%; ")" 'number txt$ = STR$(num%) PRINT "'"; txt$; "'" 'back to text PRINT txt$ = "&hFF" 'what about hexadecimal? PRINT "'"; txt$; "'" num% = VAL(txt$) PRINT "("; num%; ")" 'it works! Screen output: '1911' ( 1911 ) ' 1911' '&hFF' ( 255 ) But not even all numeric data types are the same. Consider: a% = 2.9 'INTEGER variable, floating point expression. Since the INTEGER variable cannot hold a floating point value, the number will be rounded. a% will become 3. But what about this: a% = 100000 b& = 10000 * a% Remember the range of an INTEGER? -32768 to 32767. 100000 is outside that range. The line of code in this example will generate an "Overflow" error. One quick note about Overflow errors. If you are getting them when you think you shouldn't, like here: a% = 10 b& = 10000 * a% 'b& is a LONG, so why does this Overflow? Here is why: a% is an INTEGER. 10000 is an INTEGER. So QBASIC assumes that the whole expression will be an INTEGER. Even though you are assigning it to a LONG, this generates an error. The way to get around that is to include a LONG in the expression. Where the LONG is included also makes a difference because of the order of operations. a& = 10 'a& is LONG b& = 10000 * a& 'no error. or, better yet a% = 10 a& = 10000& * a% 'we force 10000 to LONG, no error. Review: 1. How do you assign a value to a variable? 2. What is the 2nd meaning of the equals sign? 3. Can you assign new values to previously used variables? 4. Can you use a variable in an expression whose value will be assigned to that same variable? 5. Can you use a text value when a numeric value is called for or a numeric value when a text value is called for? What will happen if you do? 6. Do statements stand alone? Can they have values? 7. Can functions stand alone? do they have values? 8. What function can you use to convert from text to number? 9. What function can you use to convert form number to text? 10. What happens when you assign a floating point number to an integer variable? 11. What happens when you exceed a data type's range? 12. Why might you get "Overflow" errors when you think you shouldn't? --- 6. Introduction to keyboard input. Now, another big step forward. You learned about screen output, but that is only half of an interface. Now it is time to learn about keyboard input. There are actually several methods that QBASIC provides for keyboard input. The INPUT statement, the LINE INPUT statement, and the INKEY$ function all have their advantages and disadvantages. You will eventually use all three of them. But one of the simplest to learn is the LINE INPUT statement. LINE INPUT can be used for keyboard input as well as file/device input, depending on its parameters. However, for now, we will stick to keyboard input. The best usage for you to learn now is this: LINE INPUT, followed by a text constant which will be displayed on the screen as a prompt, followed by a semicolon, followed by a STRING variable that will hold the input text. Note that the variable in this case isn't an expression. LINE INPUT "What is your name? "; name$ In the above example, "What is your name? " is the prompt that is displayed on the screen, just as if it were displayed with the PRINT statement. The program then waits for the user to type a value up to 255 characters long. The user can backspace, delete, and move with the arrow keys until he gets what he wants. When the user presses ENTER, then the text value is stored in the variable, in this case, name$. Here is a demonstration. CLS LINE INPUT "What is your name? "; name$ PRINT "Welcome Mr. "; name$; "." Screen output (assuming user typed Michael): What is your name? Michael Welcome Mr. Michael. Actually, the prompt is optional. This will have the same effect, but without using the prompt deal on the LINE INPUT statement: CLS PRINT "What is your name? "; 'semicolon keeps cursor on same line. LINE INPUT name$ PRINT "Welcome Mr. "; name$; "." Screen output (assuming user typed Dennis): What is your name? Dennis Welcome Mr. Dennis. Here is a more practical demonstration: CLS PRINT "Exponential calculator." PRINT "To find a root, use the reciprocal of the root as an exponent." LINE INPUT "Base? "; text$ bas# = VAL(text$) 'convert text to number. LINE INPUT "Exponent? "; text$ expo# = VAL(text$) 'convert text to number. result# = bas# ^ expo# PRINT bas#; "to the power of"; expo#; "is"; result# Screen output: Exponential calculator. To find a root, use the reciprocal of the root as an exponent. Base? 9 Exponent? 2 9 to the power of 2 is 81 Screen output: Exponential calculator. To find a root, use the reciprocal of the root as an exponent. Base? 256 Exponent? .5 256 to the power of .5 is 16 Screen output: Exponential calculator. To find a root, use the reciprocal of the root as an exponent. Base? 9 Exponent? .5 9 to the power of .5 is 3 Here is a demonstration of relational operators: CLS PRINT "Number comparator." LINE INPUT "1st number? "; t$ num1% = VAL(t$) LINE INPUT "2nd number? "; t$ num2% = VAL(t$) PRINT PRINT "0 means false, -1 means true." PRINT num1%; "<"; num2%; "is"; num1% < num2% PRINT num1%; "="; num2%; "is"; num1% = num2% PRINT num1%; ">"; num2%; "is"; num1% > num2% Screen output: Number comparator. 1st number? -3 2nd number? 10 0 means false, -1 means true. -3 < 10 is-1 -3 = 10 is 0 -3 > 10 is 0 screen output: Number comparator. 1st number? 9 2nd number? 9 0 means false, -1 means true. 9 < 9 is 0 9 = 9 is-1 9 > 9 is 0 Here is a binary demonstration: CLS PRINT "INTEGER in binary." LINE INPUT "Any whole number in the range of -32768 to 32767? "; i$ i% = VAL(i$) PRINT ' the number AND 2 ^ the digit position gives us the digit value. ' the digit value \ 2 ^ the digit position gives us the numeral. PRINT i%; "in binary is:" PRINT "digit position: "; PRINT "15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0" PRINT "numeral: "; PRINT (i% AND 2 ^ 15) \ 2 ^ 15; 'semicolons keep cursor on 'line. PRINT (i% AND 2 ^ 14) \ 2 ^ 14; PRINT (i% AND 2 ^ 13) \ 2 ^ 13; PRINT (i% AND 2 ^ 12) \ 2 ^ 12; PRINT (i% AND 2 ^ 11) \ 2 ^ 11; PRINT (i% AND 2 ^ 10) \ 2 ^ 10; PRINT (i% AND 2 ^ 9) \ 2 ^ 9; PRINT (i% AND 2 ^ 8) \ 2 ^ 8; PRINT (i% AND 2 ^ 7) \ 2 ^ 7; PRINT (i% AND 2 ^ 6) \ 2 ^ 6; PRINT (i% AND 2 ^ 5) \ 2 ^ 5; PRINT (i% AND 2 ^ 4) \ 2 ^ 4; PRINT (i% AND 2 ^ 3) \ 2 ^ 3; PRINT (i% AND 2 ^ 2) \ 2 ^ 2; PRINT (i% AND 2 ^ 1) \ 2 ^ 1; PRINT (i% AND 2 ^ 0) \ 2 ^ 0 'last one, no semicolon. Screen output: INTEGER in binary. Any whole number in the range of -32768 to 32767? 96 96 in binary: digit position: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 numeral: 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 Screen output: INTEGER in binary. Any whole number in the range of -32768 to 32767? -96 -96 in binary: digit position: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 numeral: 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 Screen output: INTEGER in binary. Any whole number in the range of -32768 to 32767? 2 2 in binary: digit position: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 numeral: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 Screen output: INTEGER in binary. Any whole number in the range of -32768 to 32767? -2 -2 in binary: digit position: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 numeral: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 Do you see the advantage to having keyboard input? When you want to change values, you don't have to actually modify your program, you just execute the same program, and type different input. This is evidence of versatility. Also of note: you can pause program execution by pressing CTRL + C at either an INPUT or LINE INPUT prompt. At that point you get kicked back into QBASIC's editor. The line where execution will resume is highlighted. This also happens if your program causes a run-time error. You can make changes to the program then if necessary. To resume, press F5. To restart your program from scratch, press SHIFT + F5. In the last example, your keyboard input was converted into a number and stored as an INTEGER. If you had typed 32768, which would cause an overflow error, QBASIC would have popped you back into the editor and told you "Overflow" in a dialog box. To restart, clear the dialog box and press SHIFT + F5. Review: 1. What simple statement can you use to get keyboard input? 2. Where is the input text stored? 3. What key combination can you press at an INPUT or LINE INPUT prompt to suspend execution? 4. What happens when your program has a run-time error? 5. If that happens, what key can you press to resume execution? What key combination could you press to restart execution at the beginning? --- 7. Math functions. By now, with you experimentation, you must be really enjoying QBASIC. If you like math, here is a chapter that should liven up your day. You have already seen the math operators (arithmetic, Boolean, and relational). But there is more to math than that. What about absolute value, logarithms, and trig functions? Fear not, QBASIC has you covered. Throughout this discussion, refer to the QBASIC help for details, as I will not necessarily cover all the details. ABS() SGN() ABS() returns the absolute value of a number. ABS(5) returns 5. ABS(-5) returns 5. SGN() returns the sign of a number. CINT() CLNG() CSNG() CDBL() CINT() and CDBL() round numbers to integers. CINT() is for short INTEGERS. CLNG() is for LONG integers. CSNG(), CDBL() are used to force numeric expressions to be treated as SINGLEs or DOUBLEs respectively. I actually don't use any of these 4 functions very often. FIX() INT() FIX() and INT() are quite similar, but are slightly different. FIX() truncates a number its integer portion. FIX(5.9) returns 5. FIX(-5.9) returns -5. INT() returns the largest whole number less than or equal to the number. INT(5.9) returns 5. INT(-5.9) returns -6. INT(-5.1) returns -6. INT does not round. CINT and CLNG can do that. However, you can use INT to round by adding .5 to the input number. INT(5.9 + .5) returns 6. SQR() Returns the square root. SQR(9) returns 3. I don't use this much, because you can do the same thing by raising a number to the power of .5. For example: 9 ^ .5 is 3. Using this latter method can be used for other roots too, and is therefore more versatile. HEX$() OCT$() As the STRING data type suffix indicates, both of these functions return text values. HEX$() returns a STRING representation of a hexadecimal number, making it an extremely useful function. OCT$() returns a STRING representation of a base 8 number. I personally have no use for the base 8 counting system, so I don't use OCT$(). Example: CLS LINE INPUT "Please type a LONG: "; txt$ dn& = VAL(txt$) '& means LONG PRINT dn&; "decimal is the same as:" hn$ = HEX$(dn&) 'STRING PRINT hn$; " hexadecimal, which when converted back, is:" PRINT VAL("&h" + hn$)"decimal." Screen output: Please type a LONG: 96 96 decimal is the same as: 60 hexadecimal, which when converted back, is: 96 decimal. Screen output: Please type a LONG: -96 -96 decimal is the same as: FFFFFFA0 hexadecimal, which when converted back, is: -96 decimal. Screen output: Please type a LONG: 2 2 decimal is the same as: 2 hexadecimal, which when converted back, is: 2 decimal. Screen output: Please type a LONG: -2 -2 decimal is the same as: FFFFFFFE hexadecimal, which when converted back, is: -2 decimal. As shown before, to convert a hexadecimal number in text STRING form back to a numeric data type, use the VAL() function with "&h" being at the beginning of the STRING. VAL("&h60") is 96. text$ = "60" num% = VAL("&h" + text$) ' same as VAL("&h60"), ie, 96 decimal When working with hexadecimal numeric literal constants in your program, as was demonstrated in chapter 4, just use &h at the beginning of the number. num% = &h60 ' 96 decimal LOG() EXP() I don't use logarithms much, but if you ever have use for them, here is how. LOG() returns the logarithm of a number. EXP() returns the base of the natural system of logarithms raised to a specified power. That base is approximately 2.718281828459045. Example: CLS LINE INPUT "Number to root? "; t$ n# = VAL(t$) LINE INPUT "Level of root? "; t$ l# = VAL(t$) result1# = n# ^ (1 / l#) result2# = EXP(LOG(n#) / l#) PRINT n#; "^ (1 /"; l#; ") is"; result1# PRINT "EXP(LOG("; n#; ") /"; l#; ") is"; result2# Screen output: Number to root? 27 Level of root? 3 27 ^ (1 / 3 ) is 3 EXP(LOG( 27 ) / 3 ) is 3 ATN() SIN() COS() TAN() Now the functions I consider truly important! As you probably know, these are trigonometric functions for use with right triangles (triangles with at least one 90 degree corner). You also know that the angles of the three corners of a triangle always add up to 180 degrees. So if one angle is 90 deg, as it has to be, and another angle is 60 degrees, then you know that the remaining angle is 30 degrees because 180 - (90 + 60) is 30. For the purpose of trigonometry, we can assign labels to the three sides, and three corners of a right triangle. In trig, the upper case letters A, B, and C refer to corners, whereas the lower case letters a, b, and c refer to sides. Corners A, B, C are measured in units of angle. Sides a, b, and c are measured in units of length. B + (hypotenuse) / | c / | / |a (opposite side) / | / | +-----------------------+ A b C (always 90 deg) (adjacent side) sine of angle A is a / c a / c means the ratio of the length of side a to the length of side b, that is, the length of side a divided by the length of side b. cosine of angle A is b / c tangent of angle A is a / b cotangent of angle A is b / a secant of angle A is c / b cosecant of angle A is c / a Now of course you are not given functions for cotangent, secant, or cosecant, but you can find their values by manipulating the other functions. SIN(), COS(), and TAN() all return ratios, based on an angle. SIN() returns the sine. COS() returns the cosine. TAN() returns the tangent. ATN() returns an angle, based on a tangent ratio. ATN() is really a reverse of TAN(). arctangent of the ratio of (a / b) is A You are probably used to measuring angles in degrees. Everyone knows that there are 360 degrees in a circle. Each degree is exactly 1 / 360th of a complete circle. But QBASIC measures angles in radians. A radian is a unit of angular measurement, about 57.295 degrees, that is equal to the angle formed at the center of a circle by two radii cutting off an arc whose length is equal to the radius of a circle. 1 degree is about .0174532925199433 radians. 1 radian is about 57.29577951308232 degrees. There are about 6.283185307179586 radians in a circle. 1 radian is always approximately 1 / 6.283th of a circle. To convert degrees into radians, multiply by (pi / 180). To convert radians into degrees, divide by (pi / 180). (pi / 180) is approximately .0174. So, suppose you have a right triangle and you know that angle A is 30 degrees, and that side c is 10 inches. Since the sine of 30 degrees is .5, then you can multiply 10 inches by .5 to get the length of side a, 5 inches. Why? sine of A is a / c sine of 30 deg is 10 / c .5 is 10 / c therefore: c is 10 * .5 c is 5 Here is how you would do that in QBASIC. But remember, QBASIC variables, unlike the math variables in the diagram, are not case specific! Example: CLS pi# = 4 * ATN(1) '4 * ATN(1) is pi convert# = pi# / 180 'degree, radian conversion rate. angleA# = 30 'Corner A is 30 degrees lengthc# = 10 'Side c is 10 inches lengthb# = lengthc# * SIN(angleA# * convert#) 'Side b is Side a * 'sine of Corner A PRINT "Side b is"; lengthb#; "inches long." 'display result. Screen output: Side b is 5 inches long. If you aren't already familiar with these trig functions please learn how to use them! They will help you in computer programming and in every day life. You will find that any polygon can be broken up into right triangles. You can even use the functions to get coordinates for points on a circle's circumference. Review: 1. What does ABS do? 2. What do CINT and CLNG do? 3. What do FIX and INT do? 4. How can you round with INT? 5. What does HEX$ do? 6. How do you express a hex constant? How do you convert a hex STRING back to a number? 7. What do LOG and EXP do? 8. What type of shape does trig deal with? 9. What is the difference between degrees and radians? How do you convert between them? Which do you use? Which does QBASIC use? 10. Summarize SIN, COS, and TAN. What do they return? Based on what? 11. Summarize ATN. What does it return? Based on what? 12. Choose at least one of the 4 QBASIC trig functions and demonstrate a practical use for it. It would be good if you could do it for all 4. They should be apparent by studying the diagram and definitions. Just make up imaginary triangles and think: What dimensions do I know and what dimensions do I want to find out? 13. Can you think of a way to find X and Y coordinates for points on the circumference of a circle, based on the radius of the circle and on the degrees of the point's position, with the center of the circle being X 0, Y 0? Hint: use one function to find X and one function to find Y. --- 8. Introduction to conditional execution, line numbers, and GOTO. The last chapter was a bit intense. You may or may not find this one less so. It is time for you to learn some more fundamental features of programming that make it so versatile. Before we go on, I need to explain 2 things about the way code can be written. Neither will actually make your programs any more powerful, but their real use is to make your programs easier to read and more simple to keep organized. The first is white space. What is white space? It is any unnecessary space in your code. It can be extra spaces at the beginning of a line, skipped lines, or extra spaces in between words. What is the effect? None. White space has no effect on execution whatsoever (besides possibly a miniscule negative effect on performance). What is the point then? It can make your programs much easier to read, and much easier to organize. Already you have seen me skip lines in the code examples, for no other reason than to make them a little easier to understand. Consider this: CLS a% = 5 b% = 10 c% = a% + b% PRINT c% That would execute exactly like: CLS a% = 5 b% = 10 c% = a% + b% PRINT c% Of course that actually made the program much harder to read, but the point is that they execute the same. When I use white space, I rarely use extra spaces between words. What I do a lot is skip lines and use extra spaces at the beginning of lines. Later in this chapter you will see practical reasons for doing so. The second thing is the use of the colon (:). The colon can actually be used separate two different commands on the same line. For example: CLS a% = 5 b% = 10 c% = a% + b% PRINT c% is actually the same as: CLS : a% = 5: b% = 10: c% = a% + b%: PRINT c% Again, in this example that actually made it harder to read, but again, you will soon see a practical usage. So far the programs you have seen always do the same thing. Sure, the variables can be different, based on different keyboard input, but the program still does basically the same thing each time. So far, each line of code has executed directly after the preceding line. What if we could make it so that a line of code or a block of several lines of code could execute only if some condition were met? This way, a program could decide, based on evaluation, which lines and sections of code to execute. A program could do one thing one time, and something else another, depending on the current needs. QBASIC, and most other languages, do precisely that. It can be called conditional execution, because certain lines of code can be either executed or bypassed. Usually, that decision is based on the value of an expression. In QBASIC, one of the simplest methods to learn is the IF statement. Its name describes exactly what it is. It executes code if an expression is true. Here is the basic syntax: IF, followed by the expression, followed by THEN. The code to be executed can be placed either on the same line after the THEN keyword, or can be placed on succeeding lines. If it is placed on succeeding lines, use END IF to mark the end of the block. See the Help if you need too. IF num% = 7 THEN PRINT "Hey, the number is 7." In the sample line above, the PRINT statement is only executed if the expression, num% = 7, is true. Otherwise, the PRINT statement is completely bypassed, or skipped, with execution going to the next line. Here is another demonstration that does the same thing: IF num% = 7 THEN PRINT "Hey, the number is 7." END IF The END IF marks the end of the conditional block. If the expression is true, then the contents of the block are executed. If the expression is false, then the whole block, in this case just the PRINT statement, is skipped, and execution goes to the line after the END IF. Here is a multi-line block: IF num% < 5 THEN PRINT "The variable is less than 5." num% = num% + 1 END IF Did you notice my use of white space? That's right. I used an extra space for the line(s) in the block. That reminds me which lines are in the block and can be used to quickly find visually where blocks begin and end. You don't have to use white space like that, but you will find it helpful. If you have just a few commands that you want to be conditional, you can put them on the same line as the IF statement and use colons between them. That way, you don't have to bother with an END IF. IF num% < 5 THEN PRINT "The variable is less than 5.": num% = num% + 1 As a rule, if you put the conditional command(s) on the same line as the IF statement, that is, if there is anything following the THEN on that line, then that code is considered the code to be conditionally executed. Do not use an END IF. But, if nothing follows the THEN on that line, then the conditionally executed code is the line(s) that follow, up until the next ELSE, ESLEIF, or END IF. You must use an END IF. What if you put an IF statement inside the conditional block of another IF statement. That is called nesting, and it is perfectly fine. Consider: IF num% < 5 THEN PRINT "The variable is less than 5." LINE INPUT "Do you want to add 1 to it? "; choice$ IF (choice$ = "Y") OR (choice$ = "y") THEN num% = num% + 1 END IF which is the same as: IF num% < 5 THEN PRINT "The variable is less than 5." LINE INPUT "Do you want to add 1 to it? "; choice$ IF (choice$ = "Y") OR (choice$ = "y") THEN num% = num% + 1 END IF END IF Neat huh? One piece of advice though. Don't put more than one IF statement on the same line. Technically it is possible, but it will lead to confusion, possibly unpredictable results, and much grief. For example: IF a% = 5 THEN IF b% > 2 THEN PRINT "Hello" 'possible, but a bad 'thing to do. This would be much preferable: IF a% = 5 THEN IF b% > 2 THEN PRINT "Hello" END IF If you looked up IF in QBASIC's help, you will notice the optional ELSE and ELSEIF. These are neat little things that you can use if you choose to use a block for the conditional code as opposed to a line. (It is actually possible to use ELSE on a single line IF statement, but I rarely do.) You recall that the block of code on the lines after the IF ... THEN statement are executed if the expression is TRUE. But, what if you want the program to decide between 2 courses of action based on the truth or falsehood of the expression? That is what ELSE is for. The block following the ELSE is executed if the expression is false. IF a% = 5 THEN PRINT "The variable a% is 5." 'if (a% = 5) is true ELSE PRINT "The variable a% is not 5." 'if (a% = 5) is false END IF See the usefulness of that? Of course the same outcome could have been accomplished with 2 separate IF statements, but this was easier. ELSEIF takes it a step further. What if besides just executing if the expression is false, you want to check another expression too? This secondary test would only be made if the expression in the IF statement, or previous ELSEIFs were false. Look: IF (a% >= 0) AND (a% MOD 2 = 0) THEN '1st test. PRINT "The number is positive and even." ELSEIF (a% >= 0) AND (a% MOD 2 = 1) THEN '2nd test, if 1st was false PRINT "The number is positive and odd." ELSEIF (a% < 0) AND (a% MOD 2 = 0) THEN '3rd, if 1st & 2nd were false PRINT "The number is negative and even." ELSE 'otherwise PRINT "The number is negative and odd." END IF Neat huh? I actually don't use ELSEIF much. It is actually unnecessary (you could just use multiple IF statements each new one inside the ELSE block of another to accomplish the same thing), but there are situations when ELSEIF would be useful. Now that you know how to execute code conditionally, you may understand that it could be useful to jump from one part of your program to another. For example, if a certain condition were met, that is, a certain expression were true, you might want to jump to a different line. You can do so with the GOTO statement. But how do you tell it where to jump to? With line numbers. Not the actual line number in the file, but a number that you put at the beginning of a line. Look at this line: 10 PRINT "Hello" The 10 at the beginning is not part of the statement, it is a line number. Most older versions of BASIC actually required that every single executable line in a program have a line number. QBASIC does not require that. In QBASIC, line numbers are optional, and you usually only use them to mark destinations of jumps like GOTO. Example: CLS a% = 0 1 PRINT a% 'line marked as 1 a% = a% + 1 LINE INPUT "Again? "; t$ IF (t$ = "y") OR (t$ = "Y") THEN GOTO 1 'if yes, jump to line marked 1 Screen Output: 0 Again? y 1 Again? y 2 Again? y 3 Again? y 4 Again? n Example: CLS LINE INPUT "Loop how many times? "; txt$ NumToLoop% = VAL(txt$) counter% = 0 1 PRINT counter% '1 counter% = counter% + 1 IF counter% < NumToLoop% THEN GOTO 1 'jump to 1 to loop more PRINT "Done." Screen output: Loop how many times? 8 0 1 2 3 4 5 6 7 Done. As you can see, the GOTO statement combined with the IF ... THEN statement can be very powerful. As you progress, you will actually learn a better way of making the type of loop in that last example, but for now, at least you see the power of GOTO. Briefly there is one more statement that you will find useful. The program of course terminates, stops running, when it gets to its end. But now that we have conditional execution and jumps, it would be nice to be able to terminate the program early. That is what END does. (Of course END and END IF are 2 different things.) PRINT "Hello" PRINT "Goodbye" END 'Program terminates. PRINT "You will not see this" Example: CLS a% = -10 1 PRINT a% a% = a% + 1 LINE INPUT "Quit? "; t$ IF (t$ = "Y") OR (t$ = "y") THEN PRINT "Bye": END GOTO 1 Screen output: -10 Quit? n -9 Quit? n -8 Quit? n -7 Quit? y Bye SYSTEM is a statement very similar to END. It to terminates the program early. Depending on whether you use the /run switch when you started QBASIC, it can kick you all the way back to the DOS prompt. Another word of caution. Since it is possible to loop using the GOTO statement, make sure there is always a way out of the loop. Otherwise your program can loop endlessly. For example: 1 GOTO 1 'Endless loop. You will have to press CTRL + BREAK Review: 1. What is white space? Does it affect execution? What is its purpose? 2. How can you put multiple commands on the same line? 3. Explain the purpose of the IF statement. What determines if the code is executed or bypassed? 4. If you put your command(s) on the same line as the THEN, do you use an END IF? 5. If you put your command(s) on separate lines following the THEN, do you use an END IF? 6. Can you nest IF statements? If you do, should you put more than 1 on the same line? 7. What does ELSE do? What determines whether its conditional block is executed? 8. What does ELSEIF do? 9. How can you jump to a different line in your program? How do you indicate the destination? 10. How can you terminate your program early? 11. What are endless loops, and why are they bad? CONTINUED IN "MC-QB-3.TXT"