Troubleshooting Guide

Writing a program is difficult. You are going to make mistakes; every programmer does. The question is, what do you do when something is not working? Rather than immediately asking me for help, I would like you to use this troubleshooting guide as much as you can. If you call me over, I will ask you to demonstrate that you have already tried everything in this guide.

Use Your Materials

You should have your course materials out and ready to use. Your notebook should be organized so that you can find all of your labs easily. If you are having trouble with a loop, then look at the lab on loops. You should also consult your flowchart to remind you of how your program is supposed to run.

You should have your glossary document open so that you can toggle back and forth between QuickBASIC and your glossary. Consult your glossary to read about the command that is giving you trouble. You might have forgotten something, but if you read about it you will remember.

Check Spelling

Unfortunately, QuickBASIC doesn't have a spell checker. If you spell a variable's name incorrectly, the computer will think that you have created a new variable. That variable will assume the default value of 0 and could cause your program to do something it is not supposed to do. If you spell a function's name incorrectly, QuickBASIC will think that the function name is actually a variable name, which again equals 0. The function will never get called.

If it is difficult for you to check spelling by eye, you might want to open your program in Word and use the spellchecker. Your variable names will come up as mistakes because of the way that they are typed (variableName) but you can ask the spellchecker to accept the correct name for the variable. After that any incorrect spellings of that variable should show up as mistakes.

Keep Your Code Organized

If your code is messy, it can be very difficult to find mistakes. The most important tool for organizing your code is indentation. Indentation allows you to see what happens inside a loop, as contrasted with things that are outside the loop. Indentation allows you to see what happens when an IF statement is true. Indentation allows you to check that all structures have been properly closed. If you ask me for help, I will expect to see proper indentation before I look at your code.

Another key tool for keeping your code organized is to write comments and to choose good names. You don't have to comment every single line, but it should be obvious what the purpose of every line is. Sometimes you can make it obvious with your choice of variable names and subroutine names. For example if you have a line like this:

	salesTax = computeTax(productPrice, taxRate)
then I know that you are computing the sales tax based on the product's price and the tax rate. Look through your lines of code and see if you can tell immediately why each line is there. If it's not obvious, add some comments and think about changing some variable names. Remember that you can use the "Search" menu to easily make a change. If you forget how to do that, check the end of the LINE lab. That information is also supposed to be in the variables section of your glossary.

Use Debug Features

If you look at the menu bar at the top of QuickBASIC, you see the category named "Debug." The options under this category can help you find a mistake in your program, so you should use them. As you learned in the FOR-NEXT lab, you can watch the value of a variable. When I come over to help you, I will expect to see variable watches at the top of your screen. Did your shape disappear off the screen? Put a watch on the value of x and y and see what they equal. Maybe x is a negative number and outside the range of your window.

Follow the directions in the FOR-NEXT lab to step through the program one line at a time and try to figure out when the variable got changed. As you step, watch the program flow and make sure it is following your flowchart. Does it go inside the IF block when it should? Look for things like that.

Note: it matters what sub your are in when you add the watch on your variable. If you are inside of "drawBox" when you add the watch, then you will only be able to see that variable while you are stepping inside "drawBox". After that, it will say "not watchable". If you want to see the same variable in more than one sub, you have to add a watch for each sub.

As you step through the code, you can also peek at what's on the output screen. F4 will toggle back and forth between the programming screen and the output screen. It allows you to see what has been drawn or printed at a certain point in the program.

Another debug feature that you didn't learn about in the labs is called a breakpoint. To set a breakpoint, go to a line of code that you are interested in and hit F9. The line will light up in red. Then start your program with Shift F5. The program will run until it hits the breakpoint. This allows you to bypass part of your program and go straight to the area you are concerned about. Maybe you just want to watch the operation of one subroutine. Put a breakpoint somewhere in that sub.

Once the program flow breaks, you will be brought back to the programming screen and you can see the value of any variables that you are watching. You can now step through the code line by line by hitting F8. If you want to pick up the program from where it left off, hit F5 (not Shift F5).

To remove a breakpoint, just go to the line that has the breakpoint and hit F9.

Analyze Error Messages

When you get an error message, you will see one line of code highlighted in your program. That is the line that is causing the problem, so be sure to look at that line when you are trying to figure out what's wrong.

Loop Without Do or For Without Next

This is one of the most infuriating error messages. It makes it look like you forgot to close your loop when you can see that you did close the loop! The problem is that somewhere inside your loop, there is a structure that is not closed. Most often, this is IF without END IF to close it. Double check your indentation, and make sure that every structure has been closed.

Type Mismatch

In the DIM lab, you learned about different variable types such as INTEGER and STRING. If you try to use an integer in a place where you need a string, you will get the Type Mismatch error. It could also happen if you use a single where you need an integer, and so forth. The types have to match. So check all of your DIM statements and make sure you are using the correct type of variable.

Here is a typical set of code that will produce the error:

	IF reply = yes THEN
	
The computer thinks that you have a variable named yes. If you didn't declare that variable, it will assume it is the default type, which is SINGLE. So if the variable named reply is a string, then you have a type mismatch because a string can't equal a single. The mistake in the code is that you need to put quotation marks around the word yes. You didn't intend to refer to a variable. You meant literally the word yes.

Parameter Type Mismatch

This is the same situation as above (Type Mismatch) where you are using the wrong type of variable. This particular message occurs when your mistake involves the arguments to a subroutine. If the sub requires a string and you send it a single, you will get this error. Go to the subroutine and read its argument list to see what type of variable it is expecting. Then go back to the place where you called the subroutine and make sure all arguments have been declared correctly with DIM statements.

Argument Count Mismatch

If you are not sure what the word "argument" means, go to the first page of the PRINT lab and read question 2. You should also consult your SUB lab, where you created the subroutine drawDottedLine. Read question 3 on that lab. It explains when and why you get this error. You should also include that information in your glossary entry on subroutines.

Illegal Function Call

This error typically occurs when you try to use an argument value that is outside the acceptable range. For example, if you say LOCATE 0, you will get that error. Consult your glossary to see what the acceptable range of arguments is. (If that information is not in your glossary, put it there!)

Illegal Function Call also occurs if you forget the SCREEN command when you are doing graphics. Look at your highlighted line of code. Is it something to do with drawing? If so, you are probably missing the SCREEN statement.

Duplicate Definition

This occurs for several different reasons. One might be if you try to DIM the same variable twice within a module. If a DIM line is highlighted when the error message occurs, then look for other DIM statements in your code.

Another reason for the duplicate definition message is that you are using the wrong syntax for calling a function. There is a difference between calling a sub and calling a function. If you write a function call as if it were a sub call, then you will get this message. Your glossary entry on subroutines should include how to call a subroutine and how to call a function. Look back at the SUB lab to help you with this. Also look at your guessing game program. When you called chooseSecretNumber, that was a function call. When you called letPlayerGuess, that was a subroutine call. See the difference? Make that clear in your glossary.

Subscript Out of Range

This is related to arrays. Check the SELECT CASE lab and you will see a place where it mentions this error.

If your program doesn't have any arrays, then this error could be due to using parentheses () incorrectly. Remember that when you call a SUB, you do not put parentheses around the arguments. With a FUNCTION, you do.

Array Not Defined

If you are trying to use an array, you must declare it with a DIM statement. See the SELECT CASE lab for more detail on this.

If your program doesn't have arrays, then this error could be due to a function call in your program. It happens if the function has arguments, because those arguments are contained in parentheses. Arrays also use parentheses. If you have spelled the name of the function incorrectly, or perhaps never defined the function, then it looks like you are referring to an array.

Expected

There are several different error messages that use the word "Expected". Generally, it means that you have a mistake in your syntax. You might have forgotten to put something in parentheses (), or perhaps you included parentheses when they didn't belong there. It can also happen if you make a mistakes with using quotation marks.

If you get the Expected message when you are trying to call a subroutine or a function, then you should consult your glossary entry on subroutines. That entry should demonstrate clearly how to call a subroutine (like "drawThickLine") and how to call a function (like "askPlayerName$" or "chooseSecretNumber"). If you don't have that information in your glossary, put it in there now. Open up your guessing game if you need it to remind you of how to call subroutines and functions.

Think!

Sometimes you just need to sit and think. You want to do something and you feel that you don't know how to do it. In most cases, you can figure out how to do it. Think first about variables. As you know, variables store information. Maybe the task you are trying to do requires you to store some information so it can be used later. Variables can be used for any kind of information. Sometimes they do something obvious like storing a player's name or the x value of your rocket.

When I come over to talk to you about your program, I will probably ask you some questions about the information you need to store. I might say something like "How are you going to keep track of how many balloons you have?" The answer should be something like "I have a variable named numBalloons." If you need to store information, you need a variable. Look at the top of your program where you have your DIM statements. See if you really do have a variable for each piece of information that needs to be remembered.

Variables can store any kind of information. It doesn't have to be a name or a number. The variable's value could be used to inform you whether something is true or not. Maybe you have a game where the user can choose to hit a special power button at certain times. The power button is either "on" or "off", right? So you can have a variable simply to tell you what the state of the button is. You could name the variable "powerOn" and then initialize the variable to equal "false" (or some other value that you prefer) at the beginning of the game because the user hasn't hit the power button yet. You can use decision structures to check the value of the powerOn variable and do certain things only if powerOn is set to a value of "true" (or some other value that you prefer).

Some people are getting confused about the difference between variables and subroutines. Variables are pieces of information. Subroutines are the ability to do an action. Write a subroutine when you have a task to do. You should think about the pieces of information that will be required to do that task. Those should be sent in as arguments to the subroutine. Arguments allow the main module to communicate with the subroutine. Check the SUB lab and read about how we designed the sub named drawDotteLine in order to accept arguments.

Use Time Wisely

If you are really stumped on something and you feel like you have thought about it as much as you can, then it might be time to work on something else until you can get help. You can switch over to a different subroutine, perhaps something involving graphics that is just time-consuming but not difficult to figure out. You could work on an introductory screen for your program.