So you've followed Part 1 and designed your code. You've typed it all in, and now it just says Error in line ??. Blah Blah, Incomprehensible String of Letters. What do you do now? Apart form panic, obviously - that never helps. you start by looking at what it's telling you - there is generally a lot of information there which will help you fix it.
Introduction
This is one of a set of (planned) articles which aim to cover at least the basics of "getting started with development" and which try to give you the tools - including the mindset - to fix your own problems while you get up to speed.
At present, there are five planned articles:
- How to Write Code to Solve a Problem, A Beginner's Guide[^]: This covers how to get from the requirement (probably a homework assignment) to something you can code.
- How to Write Code to Solve a Problem, A Beginner's Guide Part 2: Syntax errors[^]: You are reading it!
- Part 3: Getting it working. Debugging your code when it is running.
- Part 4: Asking for help. For when you are completely stuck!
- Part 5: Testing, for when you realize that it doesn't really work that well after all ...
TL;DR
This is something you will be doing on a regular basis: we all make mistakes, we all get syntax errors - and they generally don't take long at all to fix, and the speed with which you fix them improves as you get used to it as well! It's certainly something it's worth learning to do -if nothing else, it saves you waiting half an hour for someone else to fix it for you! :laugh: So give it a try - see how far you can get - and give us actual information if you can't fix it yourself:
- The error message. Copy and paste this!
- Where it occurred. Should be with the message, but if it isn't, we still need to know.
- The line of code plus a few above and below for context.
Without that ... we can't fix it either!
Overview
The code is coded, the app is ready - but the compiler just won't let you run it. Why not? Let's find out.
Most of the code here is probably not going to be in your chosen language - but it's all pretty simple stuff, and the process is the same in any language. Just "bleep" over the brackets and semicolons if you don't understand them!
Let's just step back and look at the broader picture for a moment - it should help you understand what is going on.
When you code an app, you need three pieces of software:
- A text editor to actually type the code into a file
- A compiler to check the code you typed, and generate something the machine can understand
- The app itself in a form the machine can understand
Often, the first two are "bundled together" (along with other very useful software that I'll hopefully get to in the next part of this) in "an IDE" - which stands for Integrated Development Environment) so that you don't; need to faff about with compiler switches, makefiles, or leaving the environment in order to do anything - hence the "Integrated" part of "IDE".
Compiled vs Interpreted
But even if they aren't, there are two types of application languages: Compiled and Interpreted. The first runs your source through a program called a compiler which checks the instructions, and either spits out error messages or creates an executable file you can run. Interpreted code skips this step, and checks the instructions while the app is running as it meets them line by line instead of checking them in advance. It will still spit out error messages, but your code will run until it hits one. These errors are called "Syntax errors" because almost without exception, they happen because what you typed isn't understandable to the system: like writing a sentence with the words in the wrong order:
Cup may I? a have please coffee of
Doesn't make any sense, even though all the words are understandable - it doesn't match "normal English syntax". Reorder the words and you get a nice drink:
May I have a cup of coffee please?
So a compiled program will only run if there are no syntax errors, and an interpreted program will.
Compiled languages include:
- C#
- C++
- C
- Visual Basic
- Java
- Objective C
Interpreted languages include:
So I Want an Interpreted Language Then?
Well ... no.
I can see that it might look like a good idea to be able to run your code without the messy business of having to type it correctly first, but it's really a major disadvantage.
The first reason I'll give is simple: if you misspell a variable in an interpreted language, then that isn't spotted until you try to use it (and in some languages, it isn't spotted at all). That's a problem because you may well have been typing information into your app for some time before that actual line gets executed - and that's when the error is spotted and your app terminates with an error message. A compiler will spot that before you start running any code so you know that only faults in your design (or data) will cause your app to misbehave. So in an interpreted language, you only get an error when the user causes that line of code to be executed - and if you didn't test every single path through your code, that could mean it crashes on your user and throws away hours of work. Generally speaking, this doesn't encourage your users to continue being users ... LOL.
Which would you rather do: type a line of code and get an error immediately, or type a line and only find out hours or even months later?
There are a lot of other reasons, but they do get complicated to explain because you need to understand a lot of concepts beginners haven't met yet - so I'll leave them out rather than confuse things.
Generally speaking, I'd recommend a compiled language, especially for beginners - so that's what I'll concentrate on. Interpretors can generate the same errors, but later in the development process.
So What Is a Syntax Error? Why Do They Matter?
If I write a mathematical expression like this:
2 * 3 + 4
You can understand it - but there are two ways it could be evaluated - one gives a result of 10, the other 14. Generally speaking, most adults "know" that multiplication is "more important" than addition, so evaluate it by doing that first:
2 * 3 + 4
6 + 4
10
And it doesn't matter which way we write it, we get the same result:
4 + 2 * 3
4 + 6
10
But a child might well do it differently:
4 + 2 * 3
6 * 3
18
To clear up misunderstandings, we use brackets:
(2 * 3) + 4
6 + 4
10
4 + (2 * 3)
4 + 6
10
But there is another way to write it: Reverse Polish Notation (which was popular among owners of HP calculators last century, but pretty much nobody else). In that, evaluation is entirely stack based and no operator precedence is needed, because the operator pops two values off the stack, evaluates the result and pushes that back to the stack.
4, 2, 3 * +
is always 10.
To get 18, we have to write it differently:
2, 4 + 3 *
The syntax of how you write an expression depends on which notation you use, and unless you understand the notation being used, it just looks like rubbish - if you ask the average person to evaluate an RPN expression, all you will get is a confused look.
That look is a syntax error message, and it's saying "I can't do anything with that, I don't understand what you are trying to do".
Let's ignore computers for a moment, and look at what my wife leaves on my shopping list. No, seriously - we have an electronic shopping list on my phone (OurGroceries - free, and available for Android, iPhone, and web, it lets the whole family add to a list which updates in real time: so if I'm shopping in the supermarket and we run out of milk, Herself can add it and I get it before I leave the store).
But ... she's something of a Luddite, can't spell, and can't type for toffee, so I get auto corrected shopping items like this:
Helmand ceased smoked garlic
Now, I'm used to how she thinks, and strange items, so I can work out from the context of what she was doing what she ran out of:
Hellmann's Caesar with Smoked Garlic Salad Dressing
But ... to you, "Helmand ceased smoked garlic
" is probably meaningless. I have information you don't.
And for a computer? That's even worse, because it's trying to translate what she wrote into a totally different language and make sense of it.
Think of the compiler as you try to work out what this means:
Al fine spelling and grandmother forget
What I started with was:
Find all spelling and grammar mistakes
But I autocorrect stepped in and I ended up with valid English words:
Fined Al spelling and grandma Miss steaks
If I translate that word for word, I get this in French:
Amende Al orthographe et grand-mère oublier
Which translates back to English as:
Al fine spelling and grandma forget
And I'm sure you can understand the compiler throwing up its hands in horror and saying "Enough! I don't understand you".
Compilers do their best - and modern languages like C# have pretty good error messages these days. It's the older stuff that generally is cryptic: C, C++, SQL ...
Looking at Syntax Errors
Most systems these days try really hard to give you comprehensible error messages, and to a large extent, they succeed - with the exception of SQL where the error message is almost always:
Msg 102, Level 15, State 1, Line n
Incorrect syntax near: 'seemingly random word'.
but even that is trying to help you, honest!
The first thing to notice is that a syntax error almost always generates loads of error messages rather than just one - because the compiler is trying to work out what you did wrong and continue as if you got it right! But that's really very difficult to do and they generally get it wrong - which generates further errors. Fixing one syntax error can get rid of a whole load of other ones so always start with the first, not the last!
Even with SQL messages, there is information:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near: 'WHERE'.
It's telling you what line of text the error was found on: "Line 1
".
It's telling you roughly where on that line the error was found: "near 'WHERE'
".
And it's telling you that it wasn't expecting "WHERE
" in that part of the line.
So look at line 1:
INSERT INTO MyTable WHERE ID=0 VALUES (666, 777)
The formal syntax of an SQL INSERT
is:
INSERT INTO <table name> {(<columns list>)} VALUES (<values list>}
There is no mention of a WHERE
clause (because INSERT
doesn't operate on existing data, it adds new data) so the problem is that it doesn't expect the word "WHERE
" at all.
A compiler can generate quite a lot of errors from very little code if you let it ...
An Example in C++
This code actually came from a recent question: What is the error? I cannot run the program[^] and is partially what get me to find the time to start working on this article. It's C++, and fairly typical of a simple mistake that throws up loads of syntax errors:
Here is the complete error message:
main.cpp:56:9: error: no match for ‘operator<<’
(operand types are ‘std::istream’ {aka ‘std::basic_istream’} and ‘int’)
56 | cin<<pgibg;
| ~~~^~~~~~~
| | |
| | int
| std::istream {aka std::basic_istream<char>}
And there is a lot of information there:
main.cpp:56:9:
That's the file name, and the line and column numbers where the error was detected. So go there: most editors support CTRL + G to go directly to a line number. It's this one:
cin<<pgibg;
error: no match for ‘operator<<’
(operand types are ‘std::istream’ {aka ‘std::basic_istream’} and ‘int’)
That's a description of what it found. It doesn't look that helpful in this case, but it tells you something: there is no "operator<<
" defined for an input stream and an integer.
56 | cin<<pgibg;
| ~~~^~~~~~~
| | |
| | int
| std::istream {aka std::basic_istream<char>}
The rest just shows you the line and points out the parts it didn't understand. Now look at that line with a couple of lines for context:
cout<<"PhilHealth Monthly Contribution: "<<((rate*day)+(ot*otrate)*.035);
cin>>phil;
cout<<"\nPAGIBIG Monthly Contribution: "<<((rate*day)+(ot*otrate)*.02);
cin<<pgibg;
Hmm ... shouldn't cin
be directed into a variable, rather than a variable directed into cin
? Turn the less thans into greater thans, and the error should go away.
cin >> pgibg;
And that error is fixed!
But I'm Not Using C++
C# compilers, Java compilers, pretty much all modern language compilers give very similar error info - file, line, char, and message - so start with your first one and repeat the process above for that:
- Find the file and line.
- Read what the compiler thinks the problem is.
- Look at the "faulty" line and a few around it.
- Read the error message and try to relate it to the code you see and wrote.
- Compare that with your knowledge of the language (or use the documentation) for that code.
- Try to fix it.
- Recompile, and then see what errors you get.
When it goes away, repeat that process of examination and cogitation for each error message, and you'll soon fix them all!
Ways to avoid syntax errors
There are things you can do to avoid getting them in the first place, and to make it easier to find them when you do.
The first is simple:
Indent your code.
In Python, correct indentation is absolutely necessary, since the language uses the indentation to decide which lines of code form a "block" - if two adjacent lines are indented identically, they are a block.
But other languages aren't like that (thankfully - it causes problems with Python as well). Instead indentation is optional - but it's well worth turning it on. Not only is code more readable when indented:
private void ShowWords()
{
IEnumerable<string> canBe = words;
foreach (Control c in gbAttempts.Controls)
{
if (c is WordleLine wl && !wl.IsEmpty)
{
canBe = wl.ApplyFilter(canBe);
}
}
tbPossibles.Lines = canBe.ToArray();
IEnumerable<string> suggested = GetSuggestions(canBe);
tbRecommended.Lines = suggested.ToArray();
}
Compared to:
private void ShowWords()
{
IEnumerable<string> canBe = words;
foreach (Control c in gbAttempts.Controls)
{
if (c is WordleLine wl && !wl.IsEmpty)
{
canBe = wl.ApplyFilter(canBe);
}
}
tbPossibles.Lines = canBe.ToArray();
IEnumerable<string> suggested = GetSuggestions(canBe);
tbRecommended.Lines = suggested.ToArray();
}
It's also a lot easy to spot a missing bracket:
private void ShowWords()
{
IEnumerable<string> canBe = words;
foreach (Control c in gbAttempts.Controls)
{
if (c is WordleLine wl && !wl.IsEmpty)
{
canBe = wl.ApplyFilter(canBe);
}
tbPossibles.Lines = canBe.ToArray();
IEnumerable<string> suggested = GetSuggestions(canBe);
tbRecommended.Lines = suggested.ToArray();
}
private void ShowWords()
{
IEnumerable<string> canBe = words;
foreach (Control c in gbAttempts.Controls)
{
if (c is WordleLine wl && !wl.IsEmpty)
{
canBe = wl.ApplyFilter(canBe);
}
tbPossibles.Lines = canBe.ToArray();
IEnumerable<string> suggested = GetSuggestions(canBe);
tbRecommended.Lines = suggested.ToArray();
}
Especially when that missing bracket throws up an error that is completely unrelated to brackets and on a different method!
So pick an indentation style that suits you, and use it every time: I don't really care which (I use Whitesmiths) you pick as long as you are consistent. Most modern IDEs will help you if you tell it what indentation rules you want to follow.
Don't use single character variable names.
It's far, far too easy to mistype them, and end up with a different variable altogether - and it may not support the property, method, or event you expected it to. Using descriptive names reminds you what the variable holds, and that tells you what you should be able to do with it: booksList
is better than a
because you know it's a list when you try to use it, so it contains multiple items and can be Added to, Removed from, Sorted, and so on. a
could be anything - so it doesn't help you to avoid calling the wrong methods on it and generating a syntax error that doesn't make any sense!
History:
- 2022-02-16 Tcaught by Colins2 fixed.
- 2022-02-14 Tided a few things Deeksha missed, and added the "Ways to avoid ..." section.
- 2022-02-14 Tidied up by Deeksha
- 14th February, 2022: First release version