About a month ago, someone I met asked me if I could give him C programming lessons. To protect his privacy I won’t talk about him much, besides saying that he is a serious guy and he doesn’t know programming at all.
The first thing I did was give him a general explanation of what C does, the compilation process and so on. I then showed him a simple program, and showed him how to compile it, and how to run it.
I think the first thing beginners see when they start to program with C is all the “unnecessary voodoo”. For someone just starting to program, “#include <stdio.h>” doesn’t make much sense, and he shouldn’t be bothered with it. The same applies to “int main(void)”. So I just told him to ignore that for now, it would be made clear later on.
The next thing I did was give him a C book, and telling him what to read, and more importantly, what not to read. Teaching books suffer from a kind of “split personality” problem – they try to be both a tutorial and a reference. They also cover things fully the first time around. For example, consider variable types.
A first timer doesn’t need to know about anything besides int. He really doesn’t need to know about size limitations. He shouldn’t be bothered by these issues in the first few lessons.
As I see it, the order of things to learn is:
- General information such as how to compile, etc…
- Meaning of variables, and variable assignments.
- if-else, and then do-while.
So we covered these subjects in the first two lessons, and he was able to write some simple programs, such as compute the average of two numbers, and so on.
We wrote a simple ‘guess the number’ game together, and I used this opportunity to explain if-else by writing conditions for cases such as “warm” or “cold”, “too low” and “too high”. Simple while loops were explained as well: “keep playing as long as the number was not guessed”. We wrote some more programs after that.
As homework, I gave him the following problem:
Write a program to compute an average of numbers.
It will read numbers from the user, until the user gives the number -1.
After it finished reading the numbers, it will print their sum, and their average.
If the average is in the range, print: 0-55: failed, 56-72: could be better, 73-85: ok, 85-95: good, 95-100: excellent.
I knew this will be problematic, and indeed it was. He wrote a program that asked for three grades, and averaged them. It went on asking again until the grades 100, 100, 100 were entered – he thought that was nicer than -1.
Well, a few days ago we sat together, and I understood the problem:
He knew how to write C code, but he didn’t know how to program!
I simplified the problem. I asked him to write (during the lesson) a program that reads numbers from the user until a zero is entered. It will then output how many ones were encountered. He couldn’t write that as well, and that’s no surprise – he had a big concept to understand.
So I told him, let’s play this together. I will tell you numbers, and when I finish, you will tell me how many ones were there. I gave him ten numbers and I noticed he was counting on his fingers!
Grasping this opportunity, I told him to explain exactly what he does. Then I asked him to give me instructions on how to count numbers. The instructions were “read a number onto your left hand”, and “if the number on your left hand is one, set the number on your right hand to be the number on your right hand plus one”. It took some effort for him to understand this, but he did. I then asked him to do the same, but now summing the all of the numbers with the right hand.
I then showed him how I translate these instructions into C. I asked him for the definition of an average, and then, looking at the code on the screen, realization dawned on him. He was amazed – he managed to calculate the average of an unknown number of numbers!
It was amazing for me as well – it’s not often that you get to see someone understand a big concept such as programming.
After the averaging program I asked him to write a counter program – given a number, print all the numbers from zero up to this number. When he got stuck, I asked to turn off the screen, and again give me instructions on how to do the task. That he was able to do. Translating these instructions to C wasn’t that hard, and some 30 minutes later, he had a working program. Success!
If you can’t explain something to yourself, you have no chance of explaining it to a computer.
Writing code is just the projection of an internal model, and the hardest part of programming is building that model.
Yeah, the effect is striking, from my experience, too. I used to have my students write pseudo-code instead of C (after letting them flounder for quite a few minutes, to make the effect more pronounced ;o) — in Hebrew, even — and then the trivial translation to C.
Eg, exercise with printing Pascal’s triangle.
BTW, K&R did a cute quick introduction. Recommended.
But but, begs the obvious question, given your friend can’t yet think algorithmically, why C? Why not begin with Python? Seriously.
Anyway, see you at the sprint! In just three days!
;o)
Interesting post!
A friend recently asked me for a good JavaScript book, as she’d like to learn it. I’d usually recommend Crockford’s book, but it is written for readers that can already code, and I know she does not. Searching for the perfect book (I’m yet to find it,) it dawned on me why SICP is such a good book.
SICP teaches you Scheme, but that’s a side effect. What it really does, it teache you programming. And by using Scheme, it makes sure you learn more sense than syntax. Even if you don’t subscribe to the functional programming school of thought, any didactic experience will tell you C is horrible as a first programming language, since it requires much bookkeeping, which isn’t always easy for an experienced programmer, let alone for a beginner (and as you wrote, the boilerplate is scary, even if you tell her to ignore it.) A garbage collected, dynamic, and weak-typed language is so much nicer as a first language, since it doesn’t bother you with the bookkeeping C has.
SICP did gain some infamousy as the CS breaking bench, but I believe that this is due to culture shock from being a freshmen, combined with the speed at which it is usually taught. Read at a reasonable pace, SICP is a ultimate learn-how-to-program book: it only bothers you with details when you need them, provide a good balance between examples and definitions. In fact, going back and over SICP makes me want to try and translate the first couple of chapters to JS for my friend.
Shay & Ilan:
Well, the guy specifically asked me to teach him C. I explained a little about different languages, but he wanted to learn C, which I don’t consider a bad thing: C is not a bad language to start from.
Regarding SICP:
I actually bought this book when I took Intro to computer science in Tel Aviv University. At the time I was already proficient with C and C++, and I remember the course about scheme teaching me new things, and mostly new ways to think about programming. I then saw someone with the book, took a peek inside, liked what I saw and decided to buy it.
Still, I don’t think teaching someone scheme is the right way to go if his final objective is to get a good programming job.