Developing
Programs in C
Understanding the Problem
The first step is to get a clear
idea of what you want to do. It would be lunacy to start building your house
before you had established what facilities it should provide: how many
bedrooms, how many bathrooms, how big it’s going to be, and so on. All these
things affect the cost in terms of materials and the work involved in building
the house. Generally it comes down to a compromise that best meets your needs
within the constraints of the money, the workforce, and the time that’s
available for you to complete the project.
It’s the same with developing a
program of any size. Even for a relatively straightforward problem, you need to
know what kind of input to expect, how the input is to be processed, and what
kind of output is required—and how it’s going to look. The input could be
entered with the keyboard, but it might also involve data from a disk file or
information obtained over a telephone line or a network. The output could
simply be displayed on the screen, or it could be printed; perhaps it might
involve writing a new disk file updating an existing file.
For more complex programs, you’ll
need to look at many more aspects of what the program is going to do. A clear
definition of the problem that your program is going to solve is an essential
part of understanding the resources and effort that are going to be needed for
the creation of a finished product. Considering these details also forces you
to establish whether the project is actually feasible. A lack of precision and
detail in the specifications for a new program has often resulted in a project
taking much longer and costing much more than planned. There are many instances
of projects being abandoned for this reason.
Detailed Design
To get the house built, you’ll need
detailed plans. These plans enable the construction workers to do their jobs
and the plans describe in detail how the house will go together—the dimensions,
the materials to use, and so on. You’ll also need a plan of what is to be done
and when. For example, you’ll want the foundation dug before the walls are
built, so the plan must involve segmenting the work into manageable units to be
performed in a logical sequence.
It’s the same with a program. You
need to specify what the program does by dividing it into a set of well-defined
and manageable chunks that are reasonably self-contained. You also need to
detail the way in which these chunks connect, as well as what information each
chunk will need when it executes. This will enable you to develop the logic of
each chunk relatively independently from the rest of the program. If you treat
a large program as one huge process that you try to code as a single chunk,
chances are that you’ll never get it to work.
Implementation
Given the detailed design of a
house, the work can begin. Each group of construction workers will need to
complete its part of the project at the right time. Each stage will need to be
inspected to check that it’s been done properly before the next stage begins.
Omitting these checks could easily result in the whole house collapsing.
Of course,
if a program is large and you are writing it all yourself, you’ll write the
source code one unit at a time. As one part is completed, you can write the
code for the next. Each part will be based on the detailed design
specifications, and you’ll verify that each piece works, as much as you can,
before proceeding. In this way, you’ll gradually progress to a fully working
program that does everything you originally intended.
A large programming project usually
involves a team of programmers. The project is divided into relatively
self-contained units that can be allocated among the members of the team. This
allows several units of code to be developed concurrently. The interface
between one unit of code and the rest of the program must be precisely defined
if the units are going to connect together as a whole.
Testing
The house is complete, but there are
a lot of things that need to be tested: the drainage, the water and electricity
supplies, the heating, and so on. Any one of these areas can have problems that
the contractors need to go back and fix. This is sometimes an iterative process,
in which problems with one aspect of the house can be the cause of things going
wrong somewhere else.
The
mechanism with a program is similar. Each of your program modules—the pieces that make up your program—will need to be tested
individually. When they don’t work properly, you need to debug them. Debugging is the process of finding and
correcting errors in your program. This term is said to have originated in the
days when finding the errors in a program involved tracing where the
information went and how it was processed inside the computer by using the
circuit diagram for the machine. The story goes that in one instance it was
discovered that a computer program error was caused by an insect shorting part
of a circuit in the computer. The problem was caused by a bug. Subsequently,
the term bug was used to refer to any
error in a program.
With a simple program, you can often
find an error simply by inspecting the code. In general, though, the process of
debugging usually involves using a debugger that inserts code temporarily for
working out what happened when things go wrong. This includes breakpoints where
execution pauses to allow you to inspect values in your code. You can also step
through a program a statement at a time. If you don’t have a debugger, adding
extra program code to produce output that will enable you to check what the
sequence of events is and what intermediate values are produced when a program
executes. With a large program, you’ll also need to test the program modules in
combination because, although the individual modules may work, there’s no
guarantee that they’ll work together! The jargon for this phase of program
development is integration testing.
Functions
and Modular Programming
The word function has appeared a few times so far in this chapter with
reference to main(), printf(), function body, and so on. Let’s explore what
functions are in a little more depth and why they’re important.
Most
programming languages, including C, provide a way of breaking up a program into
segments, each of which can be written more or less independently of the
others. In C these segments are called functions.
The program code in the body of one function is insulated from that of other
functions. A function will have a specific interface to the outside world in
terms of how information is transferred to it and how results generated by the
function are transmitted back from it. This interface is specified in the first
line of the function, where the function name appears.
Figure 1-3 shows a simple example of a program
to analyze baseball scores that is composed of four functions.
Each of the four functions does a
specific, well-defined job. Overall control of the sequence of operations in
the program is managed by one module, main(). There is a function to read and
check the input data and another function to do the analysis. Once the data
have been read and analyzed, a fourth function has the task of outputting the
team and player rankings.
Segmenting a program into manageable
chunks is a very important aspect to programming, so let’s go over the reasons
for doing this:
• It allows each
function to be written and tested separately. This greatly simplifies the
process of getting the total program to work.
• Several
separate functions are easier to handle and understand than one huge function.
• Libraries
are just sets of functions that people tend to use all the time. Because
they’ve been prewritten and pretested, you know that they work, so you can use
them without worrying about their code details. This will accelerate your
program development by allowing you to concentrate on your own code, and it’s a
fundamental part of the philosophy of C. The richness of the libraries greatly
amplifies the power of the language.
• You can
accumulate your own libraries of functions that are applicable to the sort of
programs that you’re interested in. If you find yourself writing a particular
function frequently, you can write a generalized version of it to suit your
needs and build this into your own library. Then, whenever you need to use that
particular function, you can simply use your library version.
• In the
development of large programs, which can vary from a few thousand to millions
of lines of code, development can be undertaken by teams of programmers, with
each team working with a defined subgroup of the functions that make up the
whole program.
You’ll learn about C functions in
greater detail in Chapter 8. Because the structure of a C program is inherently
functional, you’ve already been introduced to one of the standard library
functions in one of this chapter’s earliest examples: the function printf().
■ Note in some other programming languages, the term method is used to refer to a self-contained unit of code. thus method means essentially the same as function.
// Program 1.7 A longer program
#include
0 comments:
Post a Comment