Writing C programs

The writing skills you've developed in English classes can help you with writing programs.

I. The Topic

You wouldn't (or shouldn't) start writing a paper unless you understood the topic. Similarly, you shouldn't start writing your program until you're completely sure that you understand what's being asked of you. Don't approach your programming assignments with the attitude of "I'll figure it out as I go."

There are several things you can do to help you understand the assignment. They're pretty basic: go to lecture, go to precept, do the reading, do the exercises, ask your preceptor for help.

II. The outline / brainstorming

By now, you've probably developed your own style for getting started. Perhaps you write a formal outline, or maybe you just write a long list of thoughts and then organize them afterwards. English teachers have emphasized the importance of this step in the overall process. You shouldn't overlook it when you're programming.

As you develop your programming skills, you will fine tune your own method for this step of the process. I think it's just as important for beginning programmers to receive some guidance in this skill as it is for beginning writers to receive instruction from their English teachers. Here's my advice:

Write pseudo-code. Pseudo-code is halfway between English and C. In the beginning, your pseudo-code should probably look more like English, since that's what you're more comfortable with. Over time, you will develop your own shorthand, and your pseudo-code will look more code-like and closer to C. In the practice programming assignment on dice rolling, I give an example of pseudo-code. Here's another:

Assignment: Write a program that calculates a final grade for a student in this course. The user of the program will have to enter in his/her grades when prompted. The program should print the final grade for the user. The user should have the option of continuing (to calculate another average for a new set of grades.)

Pseudo-code: version 1

include necessary libraries
main()
	some initialization
	prompt user for his/her grades
	calculate average using percentage weights
	print average
	ask user if he/she wants to continue
	if yes, prompt for new set of grades
			 calculate new average
			 print new average
			 ask if he/she wants to continue again ...
	if no, just end
end of main()

Pseudo-code: version 2
In this version, I want to make my pseudo-code a little more specific.

include stdio.h  (for printing/prompting)
main()
	float total_score = 0;
	int p1, p2, p3, p4, p5, p6, p7, p8;
	int m1, m2, f, participation;
	char prompt_response = 'y';
	loop start: while (prompt_response == 'y')
		prompt user to get values for p1...m1, m2, etc.
		total_score = (p1 + p2 + ... + p8)/8 * 0.3
         	       + m1*0.15 + m2*0.15 + f*0.3 + part.*0.1;
		print total_score;
		ask user if he/she wants to continue
		prompt_response = user's response
	loop end
end of main()

At this point, I'm ready to start writing my program. All that's missing is the specific printf and scanf commands. I didn't really need to put the actual percentages into the average calculation for the pseudo-code, but it's certainly o.k. to put actual numbers in your pseudo-code (just like you might have a couple of quotes in the outline of your English paper.)

III Writing your program

Now, the temptation is to just start typing in your program, from start to finish. After all, you've already written your outline, so now it's time to type it in, right? Wrong. Would you just write your entire thesis from introduction to conclusion without stopping along the way to read what you've written so far? I don't think so. Most people would make sure that each chapter is good before going on to the next. Imagine that you make some assumption in chapter 2 on which you base the whole rest of your thesis. If it's wrong and you don't catch it early enough, the rest of the paper is doomed. The same idea holds in programming.

When you are writing a program, you need to check your work as you go along. Maybe you do write your papers from beginning to end without stopping to read what you've written. Perhaps you write your rough drafts like this. The big problem with doing this in C is that you don't know how to read this language as well as you can read English. You do have the computer to help you check your errors, but in a lot of cases it won't be more useful than a spell-checker for helping you revise your 'paper.'

What you should do is test your code at every step. As you are writing a block of code, you should be thinking about how you can test it. For example, in our program above, you could write the prompting part of the code first and test that. In testing it, you might find that your prompt is ambiguous. This is such a simple program that it's difficult to see what might go wrong. So, just take my word on this. Write your program in parts, and test each part before you start the next. In the beginning programming assignments, I'll try to help you see what the natural divisions of the program are.

IV Testing your program

This section could be numbered III-B, since you will be going back and forth between writing and testing throughout the programming process. Here are some techniques you can use to 'debug' your program:

I. hand-simulation

I'll do this a lot in precept, whenever we're trying to understand what a particular piece of code does. Hand-simulation refers to the process by which you trace through your code, line-by-line, starting with main(). You aren't reading your code from top to bottom; rather, you should read the code in the order the computer will execute them. That means that if you encounter an if exprssion, you should test the condition and continue according to the result.

Keep track of the values of all the variables. You may find that you aren't updating some of them correctly.

Although it may seem overly time-consuming, hand-simulation is a great way for you to improve your programming skills. It's not as fast as repeatedly compiling your code, but often you will find logical errors more easily.

II. using printf

This technique refers to the process of inserting extra printf statements into your code. This is particularly helpful in seeing how the values of variables change within a loop. For example, if you had a loop that computed the sum of the first n integers, you could print out the value of the running total each time through the loop to check that you haven't made any errors.

Also, you can just insert printf statements to determine whether you've reached a certain point in your program. Perhaps you've written a condition for a loop that can never be true. By putting a printf statement inside that loop, you'll quickly see that you never executed the code of the loop (because the statement won't print.)

If you use this method, make sure that you take out all the extra print statements before you turn in the final version of your program.