Let’s step back from the details of C++ and think about something in the big picture: specifically, the need for thinking about the big picture. In the rest of life, doesn’t planning help? You wouldn’t build a house, or cook a meal, without a plan. (Heating soup in the microwave doesn’t count.)
In programming, the plan is called an algorithm: a sequence of steps, to be executed in order, that leads to a goal.
Adventures in robotic cooking
Imagine if we can get our computer to make biscuits (the fluffy kind – like scones, but not sweet). A computer can follow instructions, but they must be clear.
I get out a bowl, and…what goes in biscuits, anyway? You got me. Flour should help. Don’t they put eggs in biscuits? And milk? Tell the robot to dump some flour in a bowl, put in a couple of eggs and a glug of milk, mix it up hard as it can, roll them, and put them in the oven.

(Left) Biscuits improperly made are often of use to the construction industry. At least you’ll think so once you try to eat them. (Right) What I’m hoping to make instead
Write the algorithm before the program, even for simple tasks.
Oven heated? Check. The robot can mix the dry ingredients. Let it take a cup of flour and mix in the salt and baking soda. The cup will overflow as the robot mixes them. Why didn’t it put the flour into a bowl? I didn’t tell it to.
Next, it will mix in the shortening and then the milk. Of course, we’ll get a wet mess. Then it will form the mess into balls. How many? I didn’t say. Is two OK? Then it puts the seeping mess in the oven, at which point it falls through the rack onto the bottom… I didn’t tell it to use a tray, either. And I never told it to take the biscuits out! Got a fire extinguisher handy?
The steps weren’t specific enough. For example, I told it to mix, but didn’t tell it that one of the steps in that is to put things into a bowl. We need more detail. Stepwise refinement is how to solve that problem: write down what needs doing, then break that step into sub-steps, then break those into sub-steps, until the steps so simple even a computer can handle them.
Refine your algorithm till it’s obvious how each line converts to C++.
Good. Now we’re done. It’s a tediously detailed algorithm, but if we’re going to get a computer to understand, we have to break it down till it’s obvious – to a computer! – what the steps mean.
Is it time-consuming to write all that detail? Not as time-consuming as puzzling out the same detail while writing code, getting it wrong, debugging, and starting again and again. Experts agree time spent planning ahead reduces programming time spent overall. For that reason, lazy programmers use the following rule:
Always write them.

Charles Babbage, Lady Ada Lovelace
Babbage certainly tried. He got the British government to fund his Difference Engine, which was meant to be a mechanical calculator, and then his Analytical Engine, designed as a mechanical computer. (In those days, government funding of research was nearly unheard of. Maybe that’s why it was called “the Age of Invention.”) Machine parts weren’t of sufficient refinement at the time, and the project failed.
Lovelace, daughter of the poet Lord Byron, took an interest in Babbage’s machine and understood the nature of the programs it ran or, rather, would have run if it had existed. “The Analytical Engine has no pretensions whatever to originate anything,” she said. “It can do whatever we know how to order it to perform.” This is sometimes used as an objection to the concept of artificial intelligence.
Writing a program, from start to finish
Let’s apply this planning-ahead thing to a real, if small, programming task.
Identify requirements, that is, make a precise statement of the goal.
Write the algorithm.
Trace the algorithm by hand.
Convert the algorithm to valid C++ code.
Compile.
Test.
If there are errors along the way, we can go back to previous steps.
Requirements: What do we want to do?

A program that makes concentric circles, each half the area of the next bigger one
Ready to start coding? Not yet. First, we’ll make a plan, as discussed in the previous section.
Algorithm: How do we do it?
Too obvious? I find that programming goes much more easily when I state the obvious, write it down, and try to refine it.
State the obvious, especially when just starting.
It’s not specific enough yet. We don’t know how to draw the circles because we don’t know the radii.
The outermost circle’s is 200. The next one in, as previously stated, I want the area to be half that of the first. Remember the formula for the area of a circle: π radius2. To get a halved area, we’ll need next circle’s area = first circle’s area/2. This works out to be that the next radius is the first radius/.
No, I didn’t say where! Try again:
draw the first circle at center of screen, with radius 200
draw the second circle at center of screen, with radius 200 / √2
draw the third circle at center of screen, with radius 200 / √2 / √2...
Too complicated.
We could use variables. We’ll start the value for radius at 200 and change it every time:
start radius at 200
draw a circle at center of screen, with this radius
divide radius by √2 to get a circle with half the area as before
keep going until the circle's too small to see -- radius 1, I'd suppose
This is specific enough. Do you need to go to this trouble every time you write a program? Pretty much. As time goes by and your skills improve, you can specify less detail. But experts still write out steps for anything they’re not certain of.
Trace the algorithm: Will it work?
Another thing I do is trace through the algorithm by hand, seeing what it does, and confirm that it does what I want.
First, radius is set to 200. The area is π 2002. We draw a circle with that radius.
Next, radius is set to what it was divided by . The area is π (200/
)2 = π 2002/2, which is half the first area; that’s what I wanted. We draw the new circle.
Next, radius is set to what it became divided by . The area is π (200/
)2 = π 2002/4, which is one-fourth the first area. Good. We draw the new circle.
Seems OK.
As programs get more complex, reviewing your algorithms will be even more useful. Why spend time getting a program to compile, if it’s not going to do what we want? I’m too lazy for that.
Coding: Putting it all into C++ (plus: commenting the lazy way)
To create the program, I start the usual way : I tell the reader exactly what I’m doing at the top of the file. Then I put the algorithm right into main, as comments, so I can refine it into a working program.
The cops didn’t arrest me for putting the algorithm right there into the editor, so I guess I’ll keep going.
Include the algorithm in the program, after //’s, and you’ve already written most of your comments.
The editor can turn text into comments quickly. (This is also useful for making troublesome bits of code stop generating errors; put ‘em in comments – “comment them out” – till you’re ready to deal with them.)
: Highlight the region and select C++ ➤ Comment out region to comment it; press Tab to indent if needed. If you’re in a non-graphical version of emacs, highlight the region by pressing Ctrl-Space at one end of the region and then moving the cursor to the other end. Ctrl-C will turn it into comments, and Tab will indent.
(Note that final cool emacs tip too: Highlight a region and press Tab, and emacs indents the region all at once.)

The Visual Studio window, with the Comment out button highlighted (top right)

The algorithm, in comments
Now you can press Tab to indent the region.
Sometimes, if an editor does the commenting for you, it will use a style of commenting we haven’t covered yet: bracketing the comments in /* and */. That works too.
A program to draw concentric circles, each half the area of the one outside it. Output is in Figure 6-3
Note how the program is broken by blank lines into the major steps from the algorithm. This isn’t a requirement, but it’s not a bad idea.
“When you just can’t figure a way to get started”: find it in the YouTube channel “Programming the Lazy Way,” or at www.youtube.com/watch?v=UJK4a623D20.
- 1.
Write an algorithm to find the average of three numbers.
- 2.
Write the corresponding program for Exercise 1.
- 3.
Write an algorithm, then a program, to draw a filled circle, by drawing many circles with radii ranging from 0 to some radius R. It doesn’t have to look completely filled.
- 4.
Write the algorithm for a program to draw the Australian flag, the New Zealand flag, the Ethiopian flag, a Scandinavian flag, or some other flag using shapes you can draw with SSDL. Concentrate on what makes a coherent subtask or a repeated subtask. We’ll be seeing more flag problems in subsequent chapters.