Updated: 2003-01-19 05:50

How To Write C Programs

By Robert Allison, Algonquin College
Updated: Sunday January 19, 2003 05:50

The best way to approach a C language problem is to consider it in three major stages:

  1. Problem analysis and program design - about one-half the total time;
  2. Writing the program itself - about one-quarter of the total time;
  3. Testing and debugging - the time remaining, about one-quarter of the total.

Most students tend to skimp on the first part and merge the other two into an unending sequence of "try this" and "try that", until something happens to work. Sometimes it’s not really understood why it finally works (if it really does)!

The solution is to use tools like pseudocode to sort out how to actually write the program.

Analyze the problem

This may sound easy, but it’s the part most often neglected. Read over the lab carefully. Now read it again. Read it a third time, and try to write out (on a separate piece of paper, or using a tool like Word) an outline of what you believe is required. From that, list items you are unclear on, or parts that appear contradictory. Now read the lab and your notes again, making corrections as you go. Consult with the person next to you, your SO, your mother, or (often a last resort) even the lab instructor. Repeat this until you are certain that you understand the entire problem.


Identify the awkward parts of the problem, areas you might not be sure how to code, things that are new to you, or issues central to solving the lab. Now write a prototype program, a small C program that you will discard when you are done with it. Run the prototype as often as necessary, using the debug tools to trace your way through the code, watching key variables change as you do so.

Yes, you should use pseudocode or another software engineering tool to help you write each prototype. Once you have tested all the prototype programs you believe you will need to address the lab, move on to program design.

Program design

First, write out all the instructions, prompts, error messages, and any other interactions the finished program will have with its user. Make a note of the conditions that will require each message to be issued. This will require you to also map out any program input, whether from a file or from the keyboard. Describe the input’s layout, and any variation you can expect in it that will make the input readily useable by the user of the program. Now you can start writing pseudocode.

My own preference is to write the code for main() first, using a function whenever a chunk of logic seems to suggest one, or whenever the logic of main() is getting too involved. It may be necessary to re-write this pseudocode several times until it looks neat, tidy, and well-structured. Repeat this for each function, until the entire program’s logic seems to be both complete and correct. Do a ‘paper’ compile and execute now, tracing the path by hand through the logic, for both good and bad data. Revise your pseudocode until this seems to work well.

Writing the program

It's often wise to write the program from the outside inwards. That is, start with main()’s major loop, stick in a few printf()s, and compile and run it. Test it, then fix it. Now add the next level of refinement and run it again, replacing the old printf()s with new ones as appropriate. Using this technique, you will have (relatively) short lists of compile errors that are easier to resolve than long lists.

When you test run the partial program, you will have less to debug - and you won’t often have to go back and fix an area written and tested in a previous step as often as if you had written it all at once.

Testing and debugging

Don’t just start it up and hope it works right the first time. It won’t. Guaranteed. Instead, select a number of breakpoints in places chosen to ‘catch’ it if it gets away on you (like inside each loop, at the start of every function, and so on), set watches on key variables, and run the debugger with Trace Into. If you see something odd happening, stop. Inspect some other variables.

When you think you understand why it’s doing what it’s doing, change the source, re-build the program, and run it again. Keep running it under debug until it all seems to work.

Finally, remove the breakpoints and start the real testing, checking all cases and all boundary conditions. Try for complete code coverage - to have every part of the program execute.

Updated: Sunday January 19, 2003 05:50

Web Author: Ian! D. Allen idallen@idallen.ca      Updated: 2003-01-19 05:50

Internet Free Zone Level 1 logo Support free and non-commercial Internet.

Any Browser logo This site works best in Any Browser, a campaign for non-specific WWW.

Creative Commons License logo This work is licensed under a Creative Commons License.