Solving code problems can be a challenge, especially when the errors aren't obvious. With a bit of debugging practice, though, you can learn to quickly identify and fix common errors. One of the ways you can practice your troubleshooting and critical thinking skills is to take an application that is broken, and fix it.
Below is an example of broken code. The Poem Generator application should ask three questions, then generate a short poem using the player's input, a random noun, and some random adjectives. Unfortunately, the code has bugs and won't even compile!
First, let's see what the application should look like if there were no errors. In answer to the questions, I'll enter 'Jeff', 'coffee', and 'purple'.
Types of Errors
There are several ways to classify debugging issues. Two common categories are syntax errors and logical errors. Understanding these two types helps you know what type of problem solving approach to take.
Syntax errors: These are usually much easier to find and correct. An example would be in C# declaring a variable with the identifier count, then later referring to it as Count.
int count=0; Count = 10; //Count is interpreted as a different entity than count
C# is case sensitive. count and Count are interpreted as two separate entities. An IDE (Integrated Development Environment) like Visual Studio highlights syntax errors and provides hints as to how they might be fixed.
Logical errors: These types of errors are generally far more difficult to find and solve. IDEs usually aren't able to detect the problem. Logic errors are usually only discovered when the application gives you a result you weren't expecting, or behaves in another unexpected way.
The Broken Code
Look over the code below. Can you tell why it won't compile?
/* Debugging C# Example (Poem Generator) * Ask a user/player questions * Use information submitted to print out a 'poem' with random elements */ using System; namespace BrokenCode { class Program { static void Main() { Poem poem = new Poem(); Console.WriteLine(Poem.Randomness()); Console.ReadKey(); } } class Poem { string FirstName = "Kale"; string IceCreamFlavor = "vanilla"; string Color = "purple"; Random RandomNumber = new Random(); string[] adjectives = { "spicy", "sweet", "snappy", "strong", "spry", "peppy, "fancy", "hip" }; string[] nouns = { "sand", "fish", "clouds", "fire", "water" }; public Poem() { string title = "Hello, you."; Console.Title = title; Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine(title); Console.ResetColor(); } public string Randomness() { string output = ""; string space = " "; Console.WriteLine("I've got a couple of questions."); Console.WriteLine("First, what is your name?"); FirstName = Console.ReadLine(); Console.WriteLine("What ice cream flavor do you like the best?"); IceCreamFlavor = Console.ReadLine(); Console.WriteLine("Which color is your favorite?"); Color = Console.ReadLine(); Console.WriteLine("\n\n\n"); output += "You've inspired me. I've got a poem for you:\n\n"; output += space + "Ode to " + adjectives[RandomNumber.Next(adjectives.Length)] + " " + FirstName + "\n\n"; output = space + FirstName + ", " + adjectives[RandomNumber.Next(adjectives.Length)] + ", like " + Color + " " + nouns[RandomNumber.Next(nouns.Length)] + "...\n"; output += space + "or " + IceCreamFlavor + ". A " + adjectives[RandomNumber.Next(adjectives.Length)] + ", " + adjectives[RandomNumber.Next(adjectives.Length)] + " taste."; output += "\n\nIt doesn't rhyme, but I think it is a good poem.\n(press enter to quit)"; return output; } } }
Syntax Highlighting
One of the nice things about an IDE, or a text editor that has syntax highlighting, is that syntax errors are easier to see. Looking at the code in Visual Studio, you can immediately see some of the problems.
If you have an editor with syntax highlighting, you can copy and paste the code above to view it in the environment you are most comfortable.
The code in Visual Studio:
Now let's see what happens when we try to run the broken version.
We don't want to run the last successful build. We want to see what the errors are. If I click No, the Error List window will show all the issues Visual Studio sees with the code.
The Error List
At first, error messages can be difficult to decipher. With practice, though, they become much easier to understand.
Looking at Visual Studio's Error List, we see 19 errors.
The actual amount of problems in the code is not 19. Sometimes when you fix one problem, several errors in the Error List will clear up. Other times, fixing one bug will reveal even more problems. Even though the number of errors in the list may not match the number of actual problems, the Error List is definitely helpful.
Let's take out some of the redundant data (like the file and project names) so we can focus on just the error code, the description, and the line number for each item in the list.
Code Description Line CS1003 Syntax error, ',' expected 28 CS1003 Syntax error, ',' expected 28 CS1003 Syntax error, ',' expected 28 CS1003 Syntax error, ',' expected 28 CS1003 Syntax error, ',' expected 28 CS1010 Newline in constant 28 CS1525 Invalid expression term 'string' 29 CS0443 Syntax error; value expected 29 CS1003 Syntax error, ',' expected 29 CS1525 Invalid expression term '{' 29 CS1003 Syntax error, ',' expected 29 CS1513 } expected 29 CS0120 An object reference is required for the non-static field, method, or property 'Poem.Randomness()' 16 CS0103 The name 'fancy' does not exist in the current context 28 CS0103 The name 'hip' does not exist in the current context 28 CS0103 The name 'nouns' does not exist in the current context 29 CS0623 Array initializers can only be used in a variable or field initializer. Try using a new expression instead. 29 CS0103 The name 'nouns' does not exist in the current context 56 CS0103 The name 'nouns' does not exist in the current context 56
If you use Visual Studio and your Error List window isn't open, you can access it by going to the menu View, then choosing Error List. There are a lot of options with the information in this window, such as sorting and searching. Find out more at MSDN.
Debugging the First Error
The first entry in the Error List is:
CS1003 Syntax error, ',' expected 28
In Visual Studio you can double-click on the error, and the application will move to the part of the code with the problem. In this case, it shows line 28.
Visual Studio's syntax highlighting uses color to show the different code elements. In this theme style, keywords are blue, identifiers are white, and strings are brown.
More About Keywords, Identifiers, and Strings
Keywords are words that have predefined meaning to the compiler. For example, a data type like int, or a statement like while that indicates a loop. Identifiers are words that programmers choose to name elements they create, such as the name of a variable, or the name of a method. A string is a type that represents a Unicode characters.
An example:
int Total = 30; string Name = "Player One";
In the two lines of code above, int and string are examples of keywords. Total and Name are examples of identifiers. "Player One" is an example of a string.
Error Indicators
Using Visual Studio, we have some visible clues to help us.
- First, if you are familiar with an array of strings, you might immediately notice that the coloring is off in line 28. Some of the array elements are the wrong color; "fancy" and "hip" should be brown like the rest of the strings. Instead, they are white.
- Second, the red wavy underline that indicates an error starts at the word "fancy".
The third visual indicator is a light bulb next to where Visual Studio has detected a problem. Clicking on the icon shows suggestions for how to fix the error.
Deciphering the Error Message
Clicking the light bulb, Visual Studio provides some suggestions for how to fix the problem. One of the first options has a more detailed error message:
CS0103 The name fancy does not exist in the current context
The definition for CS0103 at MSDN says "An attempt was made to use a name that does not exist in the class, namespace, or scope."
The compiler recognizes an identifier, but not the declaration or reference for it.
Remember identifiers in the screenshot above were color-coded white? Even though "fancy" and "hip" are intended to be string elements in the array, that's not how they are being perceived by the compiler, and why both of the words are showing as white instead of brown.
To the compiler, the problem is at the word fancy.
string[] adjectives = { "spicy", "sweet", "snappy", "strong", "spry", "peppy, "fancy", "hip" };
But we can also look at the problem in a different way. The string that comes before fancy, peppy, is missing a closing quote mark.
Why does Visual Studio only identify the problem with the word fancy, and not also with peppy?
In a C# array, each element is separated by a comma. The compiler sees the quote mark before the word fancy as being the closing quote mark of peppy. Essentially, it sees the adjectives array as holding these values:
- "spicy"
- "sweet"
- "snappy"
- "strong"
- "spry"
- "peppy, "
When the compiler encounters the word after peppy, it doesn't understand that it should be another string in the array. It detects:
fancy", "hip" };
which is interpreted as an identifier (fancy), a string (", "), another identifier (hip), and then the beginning of another string (" };).
Fixing the Problem
Add the missing quote mark after the word peppy so the line now looks like this:
string[] adjectives = { "spicy", "sweet", "snappy", "strong", "spry", "peppy", "fancy", "hip" };
The red underline should disappear. Your error list should update as well.
One error? That's a big drop from 19 to 1.
The Second Error
CS0120 An object reference is required for the non-static field, method, or property 'Poem.Randomness()' 16
As we saw with the previous error we fixed, sometimes looking at what is around the area Visual Studio points us to is helpful for context. There are three lines inside of Main() (lines 15, 16, and 17). Line 17 simple holds the console window open, so we don't really need to look at that.
Lines 15 and 16:
Poem poem = new Poem(); Console.WriteLine(Poem.Randomness());
Line 15 creates a new instance of the Poem data type. Once we have an instance, we can call a method of that class by typing the instance name, a dot, and then the method's name.
The error message says "An object reference is required for the non-static field, method, or property...". But we created an object reference in line 15, didn't we?
When the method Randomness() is called, it is with the class name (Poem), not the instance identifier (poem). C# is a case-sensitive language; Poem and poem are seen as two different elements.
Fixing the Problem
We can fix this in two ways - either by making the method Randomness static (so that it can be called with the class name instead of an instance name), or by making sure that we are using the instance name (poem).
On line 15 an instance is created, so the intention of this code's author is not have the Randomness method static. The intention is to use the instance name when calling the method. To fix this error, change line 16 to be:
Console.WriteLine(poem.Randomness());
The red underline disappears, and our error list is cleared!
Debugging Complicated Errors
Looks like our code is no longer broken, right? Let's test it and see. This time I am going to use different input: Julius, fish, and orange.
At first glance it might look like everything is fine. The compiler didn't say we had any errors, and we've got output in our console window. But, if you look again at the screenshot of what our application is supposed to look like, you'll see that some lines of text are missing.
The application is using random words, so the output will be different. However, we can clearly see that we are missing two lines.
You've inspired me. I've got a poem for you: Ode to fancy Julius Julius, strong, like orange sand... or fish. A strong, snappy taste.
What happened, and why isn't Visual Studio pointing out an error?
This is an example of a difficult-to-spot error. The code compiles, but the application isn't doing what we think it should be doing. This type of error can be frustrating when you are debugging code.
The problem is between lines 54 and 57; a plus (+) is missing before the equal (=).
output += "You've inspired me. I've got a poem for you:\n\n"; output += space + "Ode to " + adjectives[RandomNumber.Next(adjectives.Length)] + " " + FirstName + "\n\n"; output = space + FirstName + ", " + adjectives[RandomNumber.Next(adjectives.Length)] + ", like " + Color + " " + nouns[RandomNumber.Next(nouns.Length)] + "...\n"; output += space + "or " + IceCreamFlavor + ". A " + adjectives[RandomNumber.Next(adjectives.Length)] + ", " + adjectives[RandomNumber.Next(adjectives.Length)] + " taste.";
We declared and initialized a variable "output" on line 42.
string output = "";
The assignment operator (=) sets the value of output to be an empty string.
On line 54 we use the addition assignment operator (+=) to set the value of output to be what it currently is (an empty string), plus the value of the right-hand operand ("You've inspired me. I've got a poem for you:\n\n").
On line 56, however, the assignment operator (=) replaces the current value instead of adding to it. This could be a typo, or perhaps code was copied and pasted from another part of the application. The result is that instead of adding to the string output, the value of output is replaced.
Fixing the Problem
This is an easy fix. Add a + before the = on line 56 and test the application again.
output += space + FirstName + ", " + adjectives[RandomNumber.Next(adjectives.Length)] + ", like " + Color + " " + nouns[RandomNumber.Next(nouns.Length)] + "...\n";
Summary
Debugging code can help improve your problem-solving and critical thinking skills, especially when you encounter a logic error or mistake where your application still compiles, but gives an unexpected result.
Fixing bugs is part of the process of programming. Although sometimes difficult when you are first learning a new language, the more you build, the easier debugging will become.
Read more: Problem Solving in Programming