PROGRAMMING,
PROBLEM SOLVING,
AND
ABSTRACTION
WITH C
Revised Edition
Alistair Moffat
Department of Computing and Information Systems
The University of Melbourne, Australia
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPearson Originals is an imprint of Pearson Australia, a division of Pearson Australia
Group Pty Ltd. It has been established to provide academics throughout Australia and
New Zealand with fast and efficient access to the printing, warchousing and
distribution services of Australia’s leading educational publisher, ensuring « smooth
supply channel to your campus bookseller.
For more information about the Pearson Originals service, contact the Editorial
Department, Pearson Australia, Unit 4, Level 3, 14 Aquatic Drive, Frenchs Forest,
New South Wales, 2086. Telephone: 02 9454 2200,
© 2013, 2003 by Pearson Australia (a division of Pearson Australia Group Pty Ltd)
‘The Copyright Act 1968 of Australia allows a maximum of one chapter or 10% of
this book, whichever is the greater, to be copied by any educational institution for its
educational purposes provided that that educational institution (or the body that
administers it) has given a remuneration notice to Copyright Agency Limited (CAL)
under the Act. For details of the CAL licence for educational institutions
contact: Copyright Agency Limited, telephone: (02) 9394 7600, email:
info@copyright.com.au
Al rights reserved. No part of this publication may be reproduced, stored in a
retrieval system, or transmitted in any form or by any means, electronic, mechanical,
photocopying, recording, or otherwise, without written permission of the publisher.
Managing Editor: Jill Gillies
Solutions Consultant: Claire Sadler
Senior Project Manager: Lise D’Cruz
Production Controller: Julie McAsthur
Digitally printed in Australia by SOS Print + Media Group
ISBN 9781486010974
ISBN 9781486010981 (Vital Source)
Pearson Australia
4, Level 3,14 Aquatic Drive
Frenchs Forest NSW 2086
‘www pearson com 2u
Every effort has been made to trace and acknowledge copyright. However, should
any infringement have occurred, the publishers tender their apologies and invite
copyright owners to contact them. Due to copyright restrictions, we may have been
unable to include material from the print edition of the book in this digital edition,
although every effort has been made to minimise instances of missing content.
PEARSONContents
Preface vii
1 Computers and Programs 1
LL Computers and computation ©... 60.0.0 vee eee 2
1.2 Programs and programming 3
13° AfirstC program... . . 6
14 The task of programming . 9
15 Becareful 10
Exercises 12
2 Numbers In, Numbers Out B
21 Woentifiers 2... ccs eccccean eee EDEL DEER 3
2.2 Constants and variables... . . . ecen ces,
23° Operators and expressions... . 3 19
24 Numbers in 3 dias G60 im Bae oe aes a1
25 Numbers out... . . 2
2.6 Assignment statements i 23
2.7 Case study: Volume of a sphere . 25
Exercises ae a's 4 26
3. Making Choices 29
3.1 Logical expressions ......... . . *
3.2 Selection ....... 32
3.3. Pitfalls to watch for . : 3
34 Case study: Calculating taxes . . 36
3.5. The switch statement 38
Exercises 2.2.2.2... 40
4 Loops 45
4.1 Controlled iteration ......... be . 45
4.2. Case study: Calculating compound interest 49
43. Program layout and style 50
44 Uncontrolled iteration... . . . 52
45° Iterating over the input data . . . 56
Exercises ......... ee 59
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPace iv PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
5 Getting Started with Functions 63
S.1 Abstraction. . a
5.2 Compilation with functions... 66
5.3. Library functions 10
54 Generalizing the abstraction 2
55 sean ve . 4
5.6 Case study: Calculating cube roots... . . . « anes (76
5.7 Testing functions and programs . . . : B
Brorcleed ow ccc cee eee ee ee ee eee 79
6 Functions and Pointers 83
6.1 The main function. . . 83
62 Useofvoid . 84
63 Scope ......... 85
64 Global variables.......... sane ABE
65. Static variables 2 89
6.6 Pointers and pointer operations ©... eevee ee eee 90
6.7 Pointers as arguments......... SUR ae Wee Aare 408
6.8 Case study: Reading numbers 95
fiixercleec) «Gr 6 2s coekeeee a bor OSs ae: 96
7 Arrays 99
7.1 Linear collections of like objects... ee eee ee 99
7.2. Reading into an array 101
7.3. Sorting an array... . 103
7.4 Asrays and functions . 105
7.5 Two-dimensional arrays 109
7.6 Array initializers 112
7.7 Asrays and pointers . . 3
7.8 Stings... . = 116
79. Case study: Distinct words... 121
7.10 Acrays of strings 123
7.11 Program aaa - 124
Exercises ; 126
8 Structures 129
8.1 Declaring structures... ...... 129
8.2. Operations on structures = 131
8.3 Structures, pointers, and functions. 138
8.4 Structures and arrays 137
Bamciess 25.2.5. eb ou ont oe eeeeses 198
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonPace v
9 Problem Solving Strategies 141
9.1 Generate andtest .. 2... 141
9.2 Divide and conquer . . 142
9.3 Simulation... . ae 147
9.4 Approximation techniques. - 152
9.5 Physical simulations 156
9.6 Solution by evolution .............5 aeeues (59
Erercises 202... . 0.02. : : 160
10 Dynamic Structures 163
10.1 Runtimearrays... 2.2... 163
10.2 Linked structures . . . 170
10.3 Binary search trees. . 176
10.4 Function pointers . . . pee enman nee 19D
10.5 Case study: A Polymohic tree library oe tery HES:
Exercises 189
11 File Operations 193
111 Text files. . . . 193
11.2 Binary files . Eee ete 15
11.3 Case study: Merging ‘multiple aes eae . 199
fBixerleee) (2. 5 Gee eee = ee ee eee 202
12 Algorithms 203
12.1 Measuring performance... .. . « tee eee ee 203
12.2 Dictionaries and searching... . sane $5 ~ 205
12.3 Hashing... 207
12.4 Quick sort . 212
12.5 Merge sort 218
12.6 Heap sort. . 220
12.7 Other problems and algorithms - ines sews, OS
Exercises 0.22 vente eee 226
13 Everything Else 229
13.1 Some more C operations ...... . ee 229
13.2 Integer representations and bit operations 230
13.3 The C preprocessor . . 235
13.4 What next? ..... eee ere ee
cr seed Se ee kos ans six 290)
Index 241
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised ElionPreface to the Revised Edition
‘When I commenced this project in 2002, I was motivated by twenty years of teaching
programming to first-year university students, watching their reactions to and behav-
ior with a range of texts and programming languages. My observations at that time
Jed to the following specification:
* Length: To be palatable to undergraduate students, and accessible when re-
ferred to, a programming text must be succinct. Books of 500+ pages are
daunting because of their sheer size, and the underlying message tends to get
lost among the trees. I set myself a length target of 250 pages, and have
achieved what I wanted within that limit. For the most part I have avoided
terseness; but of necessity some C features have been glossed over. I don't
think that matters in a first programming subject.
Value for money: Students are (quite rightly) sceptical of $100 books, and will
often commence the semester without owning it. Then, if they do buy one, they
sell it again at the end of the semester, in order to recoup their money. I sought,
to write a book that students would not question as a purchase, nor consider
for later sale. With the cooperation of the publishers, and use of the “Pearson,
Original” format, this aim has also been met.
© Readability: More than anything else, I wanted to write a book that students
would willingly read, and with which they would engage as active leamers.
‘The prose is intended to be informative rather than turgid, and the key points
in each section have been highlighted, to allow students to quickly remind
themselves of important concepts.
© Practicality: I didn’t want to write a reference manual, containing page upon
page of function descriptions and formatting options. Students learning pro-
gramming for the first time instead need to be introduced to a compact core
of widely-applicable techniques, and be shown a pool of examples exploring
those techniques in action. The book I have ended up with contains over 100
‘examples, each a working C program.
‘© Context: | wanted to do more than describe the syntax of a particular language.
also wanted to establish a context, by discussing the programming process
itself, instead of presenting programs as static objects. [ have also not shirked
‘from expressing my personal opinions where appropriate — students should be
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPaGe vill PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘encouraged to actively question the facts they are being told, to better cement
their own understanding.
* Excitement: Last, but certainly not least, 1 wanted a book that would enthuse
students, and let them see some of the excitement in computing. Few programs
‘can match the elegance of quick sort, for example.
‘Those thoughts led to the first edition, finalized in late 2002, and published in early
2003. Now it is nearly 2013, and another decade has gone by. I have used this book
every year since then in my classes, and slowly built up a list of “I wish I hadn't done
‘it that way” issues. Those “I wishes” are all addressed in this revised edition. Most of
the changes are modest, and I think I have remained truc to the original goals. (One
of the more interesting changes is that I have removed all mention of floppy disks!)
How to use this book
In terms of possible courses, this book is intended to be used in two slightly different
ways. Students who are majoring in non-compating disciplines require C program-
‘ming skills as an adjunct rather than a primary focus. Chapters 1 to 8 present the
core facilities available in almost all programming languages. Chapter 9 then rounds
out that treatment with a discussion of problem solving techniques, including some
Jarger programs, to serve as models. There are also six case studies in the first nine
chapters, intended to provide a basis on which the exercises at the ends of the chap-
ters can be tackled. Fora service course, use Chapters 1 to 9, and leave the more able
students to read the remainder of the book on their own.
Chapters 10 to 13 delve deeper into the facilities that make C the useful tool that
it is, and consider dynamic structures, files, and searching and sorting algorithms
They also include two more case studies. These four chapters should be included in
‘course for computer science majors, either in the initial programming subject, or,
as. we do at the University of Melbourne, as a key component of their second subject.
Interms of presentation, Iteach programming as a dynamic activity, and hope that
you will consider doing the same. More than anything else, programmers learn by
programming, in the same way that artists learn by drawing and painting. Art students
also Jearn by observing an expert in action, and then mimicking the same techniques
in their own work. They benefit by seeing the first lines drawn on a canvas, the way
the paint is layered, and the manner in which the parts are balanced against each other
to make a cohesive whole.
‘The wide availability of computers in lecture theaters has allowed the introduc-
tion of similarly dynamic lessons in computing classes. By always having the com-
puter available, [ have enormous flexibility to show the practical impact of whatever
topic is being taught in that lecture. So my lectures consist of a mosaic of prepared
slides; pre-scripted programming examples using the computer; and a healthy dose
of unscripted exploratory programming, With the live demonstrations I am able to let
the students see me work with the computer exactly as I am asking them to, including
making mistakes, recognizing and fixing syntax errors, puzzling over logic flaws, and
halting infinite loops.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPREFACE PAGE IX
‘The idea is to show the students not just the end result of a programming exercise
as an abstract object, but to also show them, with a running commentary, how that
result is achieved. That the presentation includes the occasional dead end, judicious
backtracking and redesign, and sometimes quite puzzling behavior, is all grist for
the mill. The students engage and, for example, have at times chorused out loud at
my (sometimes deliberate, sometimes inadvertent) introduction of errors. The web
also helps with this style of teaching — the programs that are generated in class can
be made accessible in their final form, so students are free to participate, rather than
frantically copy.
Running a lecture in this way requires a non-trivial amount of confidence, both
to be able to get it right, and to deal with the consequences of sometimes getting it
‘wrong. More than once I have admitted that I need to go and read a manual before
‘coming back to them in the next class with an explanation of some obscure behav-
ior that we have uncovered. But the benefits of taking these risks are considerable:
“what will happen if...” is a recurring theme in my lectures, and whether it is a
thetorical question from me, or an actual interjection from a student, we always go to
the computer and find out.
Supervised laboratory classes should accompany the lecture presentations. Stu-
int
main(int arge, char vargv{]} {
printf (*Hello world! \n");
return 0;
‘The program in the box doesn’t do much, nevertheless, it is always a useful task to
get this program working on any new computer system you encounter, and (0 also
‘write the equivalent program in any new language you must master.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon1.3 AFiRsTC PROGRAM PAGE 7
‘There are several points to note. First, the text between the / and «/ pair is
discarded by the C system, and is purely for the benefit of any human readers — it
is a comment. Comments can be placed at almost any point of a program, and once
the /+ is read, all further text is discarded until a «/ combination is encountered.
Unfortunately, comments cannot appear within other comments there is no sense of
nesting. Later C standards also allow a form of comment where any text that follows
.// pair in a line is disregarded, but this is not legal in ANSI (C90) C programs.
Programs typically commence with a comment that records the author of the
program, a history of any modifications to the program and a set of associated dates,
and a summary of the operation of the program. For brevity the programs shown in
this book contain relatively terse commenting, and you should be more expansive in
the software that you write.
Second, most of the rest of the program is a kind of standard recipe that is used
without discussion for the next few chapters — the #include line and int main
lines are going to appear exactly the same way in every program, as are the zetusn
statement and final closing brace.
In fact, the only interesting part in this program is the print £ line, which says
that the sequence of characters ~ or string — e110 world! is to be written to the
‘output. The next box shows a possible interaction with this program on a computer
running the Unix operating system, assuming that the program’s lines have been
typed into a file called hel Loworid.c using a program known as an editor. The
word mac: is the prompt from the computer's operating system, and indicates that
user input is expected. The commands beside each prompt (1s, which lists the files
in the current directory, and gcc, which compiles the program) were typed by an
imaginary user; the other lines resulted from the execution of those commands,
mac? 18
helloworld.c
mac: gcc -all -ansi -o hellovorld helloworld.c
mac: 1s
helloworld helloworld.c
mac: ./helloworld
Hello world!
‘The gcc command compiles the C source code in file nelloworid.c using the C
compiler distributed by the Free Software Foundation’, and creates an executable
file called he1 Lowor1¢ that contains machine-language instructions corresponding
to the C source program. On a Windows system the executable would have a .exe
filename extension, but in the Unix and MacOS contexts it is conventional to cre-
atc exccutables that have no extension. All of the examples in this book presume a
Unix/MacOS environment, as shown in the example. The last command executes the
compiled program, and the “Hello world!” output message appears.
Figure 1.2 shows a second C program, and an execution of it. This one reads
a set of numbers, and calculates and prints their sum. It is presented to give you a
feel for what a more substantial program looks like, and you are not expected to have
*See http: //www.gnu.org.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.Pace & PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
reads and adds a set of values.
7+ R second C program
/
include
int
main(int argc, char vargvfl} (
int sux; /+ the running oum +/
int next; /+ the next value to be added +/
sum = 0;
/* get the numbers one by one «/
while (scanf("ta", énext) == 1) {
sun = sumtnoxt;
?
/+ and print their eum +/
print£(*The sum of the numbers is td\n", sum);
return 0;
mac: gcc “Wall -ansi -o addnumbers adcnumbers.c
mac: ./addnunbers
345648
256984
212345,
634534
The cum of the numbers ie 2049511
Figure 1.2: A program that reads numbers, and calculates and prints their sum. The lower
‘box shows an example compilation and execution of the program.
yet mastered the intricacies of how it was put together (so please don’t panic!). But
with a bit of luck, by reading the code - and the comments — you can identify the
basic building blocks: some variable declarations; a while loop that gets the input
numbers one by one into variable next, and adds them onto a running total sum that
is at first set to the value zero; and a print that prints out the value of sum.
Most programs, including the one in Figure 1.2, contain these components:
© Comments, which help human readers understand the program;
‘© Declarations, which tell the compiler what variables are being used in the pro-
gram, and what their types are;
‘* Assignment statements, which cause arithmetic to be carried out, and the val-
ues of variables to be modified;
‘© Control structures, witich direct the flow of execution, perhaps depending upon
the values of the variables; and
‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised Elion1.4 PROGRAMMING Pace 9
1/0 statements, which get values into the program (the program input), and
then back out again (the program outpu:)..
‘Look at Figure 1.2, and see if you can decide which of these categories each statement
falls into, The next few chapters discuss these various types of statements one by one,
and give dozens more examples of their use.
‘The principal features in most programs are comments, declarations,
assignment statements, control structures, and /O statements.
Because different operating systems require different interactions, from now on
examples usually show only the C source code for programs (or fragments of pro-
grams) and their output, without giving details of the compilation process or the file
names involved.
14 The task of programming
How do we go about the task of writing programs? An analogy that might help is that
earning programming is like learning how to ride a bike. One can study physics and
know of angular momentum, but the ability to balance is quite independent of that
knowledge, and only comes after (for most people) scraped knees and tears of frustra-
tion. Similarly, it is possible to study the properties of a programming language in the
abstract, but successfully conceiving and implementing a working program requires
more than purely abstract skills. The moment of truth as they learn to “balance” is a
watershed point for most students learning programming.
‘The single most important thing is to practice — exactly the same requirement as
when leaming to ride a bike. You can’t develop the necessary skills if you never get
around to writing small programs, on your own, or working with a friend. And you
‘can memorize this entire book, but unless you have spent time in front of a computer
making mistakes, you won't have the practical skills necessary to complement your
academic knowledge.
‘The basic steps in writing a program are always:
‘* Think about the problem, and decide how you, as a human “computer”, would
tackle it.
Write down your proposed solution as a sequence of steps using a natural lan-
guage such as English.
# For each step, decide how it should be solved, breaking it down into smaller
sub-steps.
© When the steps are straightforward enough, convert each into instructions in
the programming language.
Use an editor to create a file containing your program. Start with a simple
skeleton, inserting as few lines as possible, and including only a small fraction
of the eventual functionality.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPace 10 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘ Use the compiler to check the syntax of what you have typed, and to convert
your instructions into the very simple repetitive commands that the computer
actually executes.
© Once it is syntactically correct, test your partial program on a range of data.
# To fix errors, go back as far as necessary in the process.
© Then add the next step, or unit of functionality, and start the testing process
again.
In general, the more time spent at the beginning of this process, the less time
will need to be spent at the end. Carpenters don’t saw much wood on the first day
of a house construction project ~ they spend that day making plans, knowing that in
the end the time invested will be more than repaid. When they do start sawing, they
know exactly what piece they are cutting, where it is going to go, and what order
they are going to install the various functional components of the house ~ framework,
electrical, plumbing, exterior wall cladding, interior wall linings, painting, and so on.
‘A good programmer does the same.
Note also that you can test a partial program and make sure that the parts that
have been implemented so far carry out the desired tasks, even when not all of the
functionality has been incorporated. We don’t write programs as monolithic wholes,
and then start testing when they are too big to manage ~ that is as silly as supposing
that when eating pizza you should stuff three slices into your mouth before starting to
chew and swallow. Little kids at birthday parties do that with lollies, but always choke
in the end. Adults know to get each mouthful dealt with before embarking on the
next. The same “bite, chew, swallow” routine is just as important when constructing
program. The following “hacker’s motto” neatly summarizes this process:
‘A day of debugging can save an hour of planning.
Another useful motto to remember is this next “KISS” one. It says that the best
programs are the ones that carry out the desired transformation, from input to output,
in a simple and straightforward way, without being cluttered by excessive function-
ality or dubious features:
Keep it simple, stupid.
15 Be careful
‘We end this first chapter with a stern warning about computers, and their propensity
to fail. Yes, they are enormously reliable and accurate, often running for months
or years without hardware failure. But they do eventually fail, and if the user has
been naive, that failure can be heart-breaking. For a home computer, the value of the
hardware may be ten times the value of the software and data. You spent perhaps
$1000 on the computer, and have purchased a few hundred dollars worth of games.
In this case, the actual hardware of the computer is easily replaceable when it reaches
the end of its life, and there is relatively little to worry about.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonLS BE CAREFUL, Pace 11
But if you have used that computer as an authoring or storage device ~ for exam-
ple, because you are working on a programming assignment, or writing a book, or
‘managing the accounts for a small business, or storing your holiday photos — what
is stored quickly becomes more valuable than the hardware it is stored on. It would
not be unusual for a home computer used in this way to contain data that is worth
ten times the cost of the hardware. If this is the case, you need to be careful — los-
ing $10,000 worth of data is very upsetting. For a business computer, in a small or
medium-sized enterprise, the value of the data could be ten times the value of the
programs that manipulate it, and one hundred times the value of the hardware. That
$1,000 computer may well be storing $100,000 worth of work orders, invoices, and
overdue accounts.
So it makes sense to be careful with your data. For you, your “data” might only
be your programming work, plus some snapshots from your phone, plus some music.
But even so, keeping backups should be regarded as fundamental good discipline.
Somehow, the hardware always knows when you have become lazy with your backup
routine, and fails at the worst possible instant. Losing a week of work because of
hardware failure is stupid. Losing a month of work because of hardware failure
is unforgivable. And the truth is, losing more than a couple of hours of work is
completely avoidable.
‘What does this mean? Unless you have a permanent high-speed intemet con-
nection, the best way to manage backups of media files (photos and videos that you
have created) is to either regularly burn DVDs of files that have been added to your
‘computer, or copy them on to a removable thumb drive. Keep a careful record (in a
file or even a notebook) of what files you copied and when, and use more than one
thumb drive. Indeed, best practice would be to alternate between at least two thumb
drives, and keep one of them somewhere other than on the desk beside your com-
puter. And if you are authoring documents, such as programs and essays, every hour
or two of editing time on your home computer, you should similarly make a copy of
the files onto backup media; or copy them over your internet link into a cloud-based
storage service. Then, the inevitable day your computer refuses to boot, and just says
“Hard Disk Error’, you will be enormously glad that you have reasonably up-to-date
versions of your files available.
‘As a second level of security, once a month or so you should make a complete
copy of all your files (everything you have created, not just the ones you have been
working on recently) onto removable disk drive, carefully label and write-protect it,
and store it right away from your computer, in your locker at school, or at a friend's
house. This kind of off-site backup doesn’t have to be quite as regular as the routine
copying of files off the computer, but is no less important ~ a fire in your house is
‘twaumatic enough without losing a year’s worth of assignment work, even when you
have carefully carried out the first level of the backup regime.
Keep up this routine whenever you are working on the computer actually creating
information. It is easy enough to buy a fresh copy of some game program, or a music
track you can't live without, But no amount of money could, for example, resurrect
the photos you took in Nepal, climbing mountains; or the effort spent writing a book
such as this one.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPage 12 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘Time spent working on a computer is a resource far more precious than
the hardware itself. To minimize the impact of hardware failure, you
should adopt a regular backup routine.
‘If you are using a shared computer in a professional installation, then the backups
should be done centrally for you, and off-site storage arranged as part of a proper dis-
aster recovery plan. But you can still take some responsibility — why not periodically
make a copy of your files, and load them onto your home machine? Just in case the
backup regime at the central computer isn’t being done regularly? Gnashing your
teeth, and calling for the resignation of the system programmer who didn’t check that
the backups were working properly cannot absolve you from the responsibility of be-
ing careful with your own files. If you always act as if the worst is about to happen,
‘you will be better prepared for the inescapable moment when the worst does happen.
Exercises
1.1 Ask an older friend or relative about the first computer they ever bought. Try
to pin down the year, the price, and some of the physical characteristics of
their machine ~ disk space, memory space, and processor speed. Then look
at some newspaper or magazine advertisements, and find the same values for
amodem computer.
Once you have some “then” and “now” figures, calculate the annual com-
pound growth rate on performance that they represent. If you want to make
‘an accurate assessment, you probably need to allow for inflation too, but ig-
noring it won't affect your answer by much.
1.2 Find out how to use the editor on your computer to create a file, and type in
the “Hello World” program. Compile and execute it.
1.3 Study the program in Figure 1.2. Without trying to write any detailed C in-
structions, discuss with a friend what would need to be added if the average
(mean) of the input numbers was to be printed as well as their sum.
‘What do you think the original program does if no numbers are typed?
What should the extended program do if no numbers are typed?
1.4 Suppose that you get paid $18 per hour to do some work using a computer ~
perhaps writing a book, or doing some programming. Suppose that you spend
threc hours a day working on that task, five days a week.
After one year of effort, what is the value of the data stored in the computer?
‘And after three years? How does that compare with the cost of a computer?
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonChapter 2
Numbers In, Numbers Out
This chapter introduces the three elemental components of any C program: reading
numbers from the input; doing some calculation on them; and then printing numbers
back to the output. But first you need to know about the rules for forming identifiers
(Section 2.1), and about constants and variables (Section 2.2).
2.1 Identifiers
An identifier is a name used in a C program to represent a value. The rules for
forming valid identifiers are relatively simple:
© ‘They must begin with a letter or underscore (‘*.") character;
They can then use any combination of letters, digits, and underscore; and
* They may not contain any other characters.
For example, all of date and temperature and mean and big_long-name and
nitems and —funny are valid identifiers.
‘These ones are not: fast-food, because it contains a hyphen “-" character (and.
‘as the hyphen represents subtraction, the C systems interprets it as being fast take-
away food); 76trombones, because it starts with a digit; and # of words, because
‘it contains a hash (““#”) character.
You are also free to use identifiers like chad£t 76a£M and £5g6h7 8k9 in your
programs. Using names like these does not affect the execution of your program in
any way, and the C system doesn’t care what names you use. On the other hand, use
of non-mnemonic strings makes it harder for human readers to browse your program
~and it is reasonably likely that the next human who has to try and understand your
‘work will be you, in a week, a month, or a year. So it pays to use appropriate variable
names.
Use meaningful identifiers, so that names reflect the quantities being
manipulated.
‘The exception to this advice is where an identifier is used extensively over a short
section of your program, in which case it is usual to have names like i and j.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPage 14 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘There is a set of words that cannot be used as identifiers, because they have special
significance in the C system. These include words like int and while, both of
which have already been used in Figure 1.2. Several more such reserved words will
be encountered in the next few chapters.
Reserved words have special meanings in C, and may not be used as
identifiers.
2.2 Constants and variables
Some numbers used in programs are constants — fixed values that do not (and should
not) change during the course of execution. C offers a useful facility for assigning
symbolic namesto these: the #def ine. To define a symbolic constant, pick a suitable
‘identifier, and make sure that the “#" is the first non-blank character in each line:
define SEC_PER_MIN 60
#define Nr}
fcefine EXAM_PERCENTAGS 60
fdefine PROJECT_PERCENIAGE (100 - EXAM PERCENTAGE)
#detine KMPER MILE 1.609
Note that you should not put a semi-colon at the end of these lines. Note also
how in this example there are several different constants that all have the same value.
If a different symbolic name is used for each logically distinct quantity, even when
they are numerically the same, it is much easier to correctly modify the program. For
example, if the EXAM PERCENTAGE was to be changed from 60 to 70, and symbolic
constants were not being used, there is a very real possibility that in hunting through
‘your program looking for occurrences of 61 to be changed you will end up with some
hours containing 70 minutes, or some minutes containing 70 seconds. Note also that
constants can depend upon the value of other constants: PROJECT.PERCENTAGE
is definitely constant, but with a value that is not explicitly given. A change of
EXAM PERCENTAGE to 70 automatically changes PROJECT PERCENTAGE too,
There is no rule that says that symbolic constants should be all-uppercase letters,
and any identifiers can be used. Nevertheless, use of uppercase constants is a widely
followed custom, and is the style adopted in this book.
It is also both permissible and sensible to use constants for any fixed character
strings used in your program:
#define ERROR M
"values must be greater than zero
Strings are dealt with in more detail in Section 7.8 on page 116.
Use symbolic constants for all fixed values manipulated in your
programs, to improve readability, and to facilitate subsequent
modifications.
‘One extreme view is that the only permissible raw constants in your programs
should be zero and one, and then only when they are being used as the additive and
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon2.2. CONSTANTS AND VARIABLES Pace 15
multiplicative identities respectively. You might not want to take it quite this far,
but if you directly code any fixed value into your program, pause for a minute and
consciously decide whether or not in a years time it will look like a “magic number”,
and if so, give it a symbolic name.
The other values manipulated in a program are variables. In mathematics, vari-
‘ables are used to represent unknown, but fixed, quantities. In a program, variables
represent values that change. Consider, for example, the statement sum=sum+next
in Figure 1.2 on page 8. Writing the similar s = s +n in mathematics as an as-
sertion implies that n must be zero, and that s can be any value. In Figure 1.2, the
statement sum~sum#next: is a directive that means: “take the current value stored in
‘the variable called sum, add to it the current value stored in the variable next, and
then store the result back into sum”. At the end of that sequence, variable sum has an
altered value (presuming next is non-zero); and sum changes again if the statement
is repeated. That is, at any point while the program is executing, sum has a value
that is determined as an exact function of the sequence of numbers entered by the
program’s user.
‘Combinations of variables and constants are calculated as expressions, and their
values are preserved into the same or other variables using assignment statements.
‘Here are some more assignment statements that make use of the constants that were
defined earlier. Each assignment presumes that the various right-hand-side variables
have been given suitable values:
nitens = nitenstl;
miles = kn/KY_PER MILE;
tot_seconds = (hours*MIN_PER_HOUR + mins) +SEC_PER MIN +
finel_mark = (exam mark+EXAM_PERCENTAGE +
project_mark«PROJECT_PERCENTAG:
Note the use of a semi-colon to terminate each of the calculations. This is how C
knows where one statement ends and the next begins. Note also that none of the
white-space layout — achieved through the judicious insertion of blank, newline, and
tab characters — is significant in C. Long statements should be broken over scveral
ines in a neat and tidy manner. Observe how helpful it is to use sensible identifiers —
‘well-written program text can be read almost as if it were prose.
Semi-colons are used to terminate statements.
Each variable used in a program must be assigned a ‘ype in a preliminary state-
‘ment called a declaration. In Figure 1.2 on page 8, sum and next are both declared
tobe integer-valued variables by the initial line int sum, next. Similarly, all of km,
miles, tot seconds (and so on) need to have been declared prior to the assignment
statements given in the previous example. But it is probably not sensible to declare
km and miles to be of type int, as they might not be integer-valued. A range of
other types are described shortly, including one suitable for km and mites.
Each variable in a program has a type associated with it.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonPace 16 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘One common misconception is that declaring a variable also gives it an initial
value. This is not the case. The declaration indicates to the compiler that the variable
exists, but does not give it any particular value. That must be done by an assignment
statement, which is why sum is explicitly set to zero in the program in Figure 1.2
on page 8. C does permit one small shorthand to reduce the need for duplicate han-
dling, and variable declarations and an initial assignment can be combined in a single
statement if desired:
This statement both declares the integer variable oun, and sets it to zero.
Variables must be assigned values before they can be used in
expressions.
If a variable is used without an initial value being assigned, the results are un-
predictable. If you are unlucky, the system assigns zero or some other initial value,
and your program works. If you are lucky, your program fails, and you are forced to
investigate why. This second path is definitely the more desirable one - it is better to
find out early that a program is erroncous, than to use it for many years, then one day
transfer it to a different computer and have it mysteriously fail.
‘The type of a variable determines how its value is represented in the computer,
and how operations on that variable are carried out.
Integer variables store exact values, but only within a somewhat limited range.
‘On the majority of current computers the allowable range of integers is from —2°! =
—2,147,483,648 to +28! — 1 = +2,147,483,647, values determined by the use of
32 bits of memory for each int variable. Computations that result in integer values
outside this range result in incorrect answers, with no warning whatsoever. This
unfortunate fact is demonstrated by the next program fragment:
int big, bpl, bt2, bplt2;
big = 2147483647;
bpl = bigtt;
be2 = bigh2;
bplt2 = ppl+2;
print£(*big=8d, bpl=td, bt2=8d, bplt2=4d\n",
big, bpl, bt2, bplt2);
In this program, a number of assignment statements are executed in the order they are
written, and then each of the “sa” fields in the print statement is replaced by the
next corresponding value in the list of variables that follows. (The print £ statement
is considered in more detail shortly.) When executed on a standard 32-bit computer,
the program fragment produces this output line:
[ pigr2is7» multiplication 5.0*3.0 15.0
543.0 15.0
543 15
/ division 19.0/4.0 4.75
19.0/4 4.75
19/4 4
% remainder after division 19.0%4.0 illegal
19.084 illegal
1984 3
+ addition 7,543.0 10.5
7.543 10.5
143 10
— negation
= subtraction
‘Table 2.1: Operations on numeric values. When both operands to the binary operators are of
type int, the result is always of type inc. Ifeither or both of the operands are of type Float
or double, the result is of type double. The modulus operator “'” can only be applied if
both arguments are of type int. If both operands to a division are of type int, the result is
the truncated integer quotient.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon2.4 NUMBERS IN Pace 21
print £(°17.0/0 = ¥.3£\n", 17.0/0)7
print £(*1.0/(17.0/0) = ¥-3£\n", 1.0/(17.0/0));
print£ ("sqrt (-1.0) = 8.3£\n", sqrt (-1.0));
print£(*1.0/sqrt (-1.0) ~ %.3f\n", 1.0/sqrt (-1-0))5
print£(*17/0 = ¥d\q", 17/0);
When executed on one computer, the output was:
17.0/0 = int
1.0/(17.0/0) = 0.000
sqrt (-1.0) = nan
1.0/sqrt (-1.0) = nan
Floating exception (core dumped)
Note how, in this example, the second division 1/inf results in the calculation of
zer0; while 1 /nan continues to be nan. It also remains nan when squared or multi-
plied by ing. If your program is terminated, you may see the rather unhelpful error
message “Floating exception (core dumped)”. The reference to “core dumped” is a
link back to the early days of computers, when the internal memory in which pro-
‘grams and data were stored was composed of small magnetic donuts threaded with
wires — core memory. When a program fails like this, a file called core may be
written. You should delete coze files if you notice them in your directory.
‘When executed on a second computer, the final divison resulted in a bizarre num-
ber being generated, rather than an execution error. Beware.
2.4 Numbers in
‘To be useful, a program must be capable of operating on a range of data, not just
the fixed numbers compiled into it. It needs to be able to read numbers typed on the
keyboard. In C, the easiest way to read is through the use of the standard function
scané. The general form of scané requires a control string and a list of variables:
scant (control string , list of variable addresses )
where each component of the control string matches one of the variables, and indi-
cates how the data should be stored into that variable. Here are two examples:
nt n_pass, class_size, pass_percents
coubie mass, velocity, force;
scanf("sdtd", un_pass, iclass_size);
scanf("S1£S1£81£", 6mass, @velocity, force);
Inthe first, wo int variables are to be read, and so the control string is "84%4", with
each “sc” a format descriptor indicating that one integer is required. In the second,
three double values are read, each controlled by a “$12” format descriptor. Had
these variables been of type £1oat, format descriptors “+#” (for “float”, rather than
“long float”) would be required. Similarly, “®c” is used to read one character into a
variable of type chaz.
For scant to operate correctly, the names of the variables must be prefixed by an
ampersand character “s”. This indicates the use of the address of the variable rather
‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised ElionPage 22 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
than its value; why addresses must be passed is discussed in Section 6.7 on page 93,
and for the moment we will simply use the ampersands as part of a standard recipe.
In detail, what happens is that characters in the input buffer — from the keyboard,
unless Unix input redirection is used — are examined one by one. As cach character
is read, it is added to a lengthening value of the type specified in the corresponding
format descriptor. That format descriptor — and corresponding variable — is finished
when an character that cannot be incorporated is encountered; that character is then
the first one used for the next format descriptor, even if the next format descriptor is
in a different scans statement. These rules mean that leading whitespace is skipped
over for “4a” and “1” descriptors, but not for “8.c” descriptors. As another step in
scan£ processing, any additional characters in the control string are also matched,
with a blank matching any/all whitespace characters, and so on. For example, the
control string “$<. 84#8c” processes the input characters “5 .67###2” (using “#”
to show where the space characters are) into the int values 5 and 67, and the char
value ' 2".
If the control string format descriptors cannot be satisfied by the sequence of
characters in the input stream, the scan halts at that point, and the remaining
variables are not assigned values. For example, if “sasa%a is given the input
“##1234#45. 689” (where “#” is again used to show spaces) the first integer vari-
able is assigned the value 123, the second is assigned the value 45, and the third is
left unchanged — the period character terminates the second integer, but cannot be
used as a component of the third.
These rules are reasonably complex. So an important piece of advice is this:
always print out the values of variables after they have been read, so that there is at
least some chance that any discrepancies (or outright errors) are detected. Another
point worth noting is that scan retums as a value the number of objects that were
successfully read. So it can also be used as:
ant ("4d S1f %c", én, &z, Sc)
There were td values success:
ly read\n", num
‘There is more that you need to know about scanf before you can be a profi-
cient C programmer, but the minimalist treatment in this section is enough to get
you operational. Section 4.5 on page 56 returns to scan£ and explains more of its
functionality.
‘The function scant is used to read numeric values from the keyboard
into program variables. Values read should always be echoed back to
the output, to provide validation of the input process.
2.5 Numbers out
‘The examples in this chapter have already made use of the function print £. The
general structure is:
print (control siring , list of expressions )
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon2.6 ASSIGNMENT STATEMENTS Pace 23
{In simplest form, output is to the terminal screen or equivalent, a device that is char-
acter and line oriented, and often with a default of 80 characters wide.
As for scan#, the format descriptors must match the variables: “td” for int-
valued expressions; “£” for Eloat~ and double-valued expressions, or “Se” if
exponential form is required, for example, 6.67e-11; “tc” for chaz-valued ex-
pressions; and “ts” for strings. Note that — confusingly “1” is used only when
reading double variables, and they are written using either “S.£” or “se”.
More control can be exerted by modifying the format descriptor using a field
width: “3c” indicates that at least three character positions should be used, with
more consumed if necessary; and “10a” indicates that at Icast ten character posi-
tions should be used. In both cases, leading blank characters are inserted if the value
being printed requires fewer digits than the number specified as the field width.
With doubles and fioats, both the total width in characters and the number of
character positions after the decimal point can be controlled: “*5£” indicates that
at least five positions should be used; and “8 .2£” indicates that eight positions in
total should be used, with the decimal point placed in the third-from-right position,
and two characters after it
If the character width value is negative, the output string is left justified within a
field of the (positive) width. This is particularly useful in conjunction with the “3”
format descriptor used to format character strings ~ for example, “2-208” formats a
string at the left of a field of total width (at least) twenty characters.
When a line is to be terminated and a new line commenced, a "\n” character is
written into the format control string.
The function print is used to create and structure program output.
‘The example in Figure 2.1 shows a range of formats, with hash characters used
so that you can see where the blank characters are. Trace through the details, to be
sure that you understand how cach of the lines was generated.
‘One of the surprising things in Figure 2.1 is that char variables can be used in
arithmetic. In fact, the type char is a numeric type, and the constant ’ a” equates
to the integer 97 by virtue of the character ordering used in almost all computers.
Moreover, the lowercase letters form a contiguous sequence, as do the uppercase
letters starting at “A” equal to 65. Exercise 4.4 on page 60 explores the properties of
this “American Standard Code for Information Interchange” (ASCI) in more detail.
2.6 Assignment statements
You have now seen nearly all of the parts needed to write simple programs that read
numbers, do calculations, and print out answers. The only bit missing is a proper
introduction of the assignment statement:
variable = expression
‘There have been several examples of assignment statements in the previous parts
of this chapter, and there is nothing more that needs to be said about it at this stage,
except to reiterate that the value of the expression on the right -hand-side is calculated,
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPage 24 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
fdefine MARY "Mary, Mary, quite contrary"
int
main(int argc, char sargv{]) {
int n=12345;
double x=3.14159;
char o~/aly
printe("td %3d 86d $-6d\n", n,n, n, n)7
printe("eE %.4f 86.2f %-6.2E\N", x, x, XX;
printE("tc Ad Sc\n", cy cy c#3);
Print £(*¥s\n¥50s\nt-50s\n", MARY, MARY, MARY);
return 0;
12345¢F1 234584 1ZSOSRFIISOSE
3141590883. 141686003.14803.1488
abto7#ed
Mary, Mary, tquitetcontrary
saenestesesenessereetttemary, Mary, tquitetcontrary
Mary, MMary, Fquiteécontrary# #HEEHEEEAEAA FEE ARESRAEE
Figure 2.1: Use of different format descriptors in print statements. The symbol
used in place of blanks.
and then that value is stored into the specified variable. It makes no difference if the
Jeft-hand-side variable is used in the right-hand-side expression — it just contributes
to the final value that is calculated, exactly the same as any other constant or variable,
‘One convenient shorthand that it worth coming to terms with is the ability to omit
repeated variable names, a mechanism that allows the assignment sun=sun+next t0
be abbreviated as sum+=next. This form, with an operator prior to the “=”, can be
used for any binary operator: n /=2 divides n by two, and m+=1 adds one to m. The
latter of these has its own special shorthand: -++ adds one to variable m. Similarly,
-= subtracts one from r. These postincrement and postdecrement forms of the
assignment statement are used sparingly in this book, but are common in C programs
and you need to be aware of them. There are also preincrement and predecrement
‘operators described in Table 13.1 on page 230 that are not used in any of the programs
in this book.
‘The assignment statement allows the value of a variable to be changed.
One slight surprise arises with assignment statements: if the expression is of a
different type to the variable to which it is being assigned, an automatic cast takes
place. This process is shown in the next program fragment:
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon2.7 Case sTupy Pace 25
int nj double 2; char cj
42; 2 = 42; © = 42;
print£(*n-83d, 20812.8£, cmbc\n", ny 2, cdi
n= 100.99 z = 100.9; ¢ = 100.95
eet 12.8f, omtc\n", n, 2, ©);
exte\n", ny 2, cdi
0000000, cma
Note how char, int, and double values can all be assigned to each other, without
any warming message being generated by the compiler. Note also that the values
printed by the “sc” format specifier interpret values as codes in the ASCII character
set, hence the asterisk (code 42) and “a” (code 100) values in the final column of the
output. The fundamental message to take away from this example is that you ~ the
programmer — need to take care to get the types right.
2.7 Case study: Volume of a sphere
Using the assignment statement, and the other C skills described in this chapter, you
are now able to write a range of straightforward programs. You could also do exactly
the same type of computation very easily with a calculator or spreadsheet, but be
patient — you will soon sce calculations that can’t be done with a spreadsheet.
To confirm that you have leamed these skills, try the following exercise before
reading on. Don’t forget to include the standard boiler-plate code at the top and
bottom of your program. You can copy that from Figure 1.2.0n page 8.
Write a program that reads in the radius of a sphere, in meters, and
calculates and outputs the volume of that sphere, in cubic meters. The
volume of a sphere of radius r is given by $nr*.
Figure 2.2 provides a solution to this exercise. Note the various parts: a comment
at the top, followed by boiler-plate code; then declarations for two variables of type
double (their values cannot be assumed to be integral); a print £ statement to print
‘2 prompt, so that the user of the program knows when input is expected; a scant
statement to read in a value; an assignment statement to compute the desired output
value; and a print £ to do the writing.
The constant has been given a symbolic name in Figure 2.2. In fact, as will be
seen in Section 5.3 on page 70, a set of commonly used numeric values, including 7,
are already defined in many C installations, to greater accuracy than is shown here,
‘Section 5.3 shows how to access these predefined values.
Finally, note that the program prints the input value too, as was recommended
carlier. Doing so makes it more likely that you detect any errors in the scanf that
might cause an incorrect value to be read and processed. Whether a scanf terminates
prematurely is only partly in your hands — the person using your program also shares
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonPace 26 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
/+ Calculate the volume of a sphere given its radius.
“/
include
fcerine PI 3.14159
int
main(int age, char ¢argv{)) (
Gouble radius, volune;
print£(*Enter sphere radius: *);
seant("siz", eradivs);
volune = (4.0+2I+radius+radiussradius) /3.07
print£(*When radius is 4.2£ meters, ", radius);
printf ("volume is %.2£ cubic meters\n", volume);
reurn 0;
Figure 2.2: Calculating the volume of a sphere. The lower box shows an execution of the
rogram in the upper box.
that responsibility, and you should not rely on them — but you can at least show what
value ended up being used in your program.
Programs should always be written presuming that the user will either
deliberately or accidentally abuse them.
‘The program shown in Figure 2.2 is typical of programs in the simple “caleu-
late the output from the inputs” category discussed in this chapter. A wide range of
functional relationships can be evaluated using the same basic template.
Exercises
21 Foreach of the following, decide whether or not it is a valid C identifier:
—hello kn_per_hour
Hel1037 speed!
constant-value sensiblesnane
subject #1 _num_incorrect_
A big_long_name_many_letters
M Ioclock
2.2 Trace the following program fragment, and determine the final values of each
of the variables.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonEXERCISES Pace 27
Pa}
24
25:
2.6
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
a, By c Ge £, oF
(atb/2#6) /3;
a-bto-dte-£;
Given the following declarations,
double r, area, perimeter, elapsed hours;
int start_hour, start_min, start_sec,
finish hour, finish_min, finish_sec
write assignment statements that calculate:
a. The area of a square of edge length x.
b. The perimeter of a square of edge length r.
©. The area of a circle of radius r.
4. The perimeter of a circle of radius =.
©. The time in elapsed hours between the start time (three variables) and
the finishing time (three variables) of some event, assuming that the two
times are within the same day.
Write a simple program that has #include added at the top,
and then print out the values of the following constants: INT.MAX, INT.MIW,
FLTMIN, FLTMAX, DBL MIN, and DBL.MAK.
Do the values on your system agree with the values given in this chapter?
‘Try the calculation 1.23 x 10! + 4.56789 — 1.23 x 10% ona range of com-
puters and calculators (including a spreadsheet program).
Which device is the most accurate?
Which of the following output lines (with hash characters representing blanks
in the output) could not have been generated by the print £ statement on the
first line? (Note that the combination “*\"” represents a single double-quote
character.)
print£(*n = 43d, x = 98.42, m= \"$-15a\"\n", ny x, mF
123, #x4=#123 4567, #m#=#"hel 10, #hello##e*
1234, #x-41234.567, dm#=#"hellos sds fas HE”
123, #x#-#-1234.5670, imf#"hollo# fated EET
-123, #x#=#-1236.5670, #mameMEREE EEE EH ENOL LON
nd-#441, fo=-#48#3.1472, dmé=# "hello, #heLlo, #hel1o"
né-#l, txt-#3.1472, ime #"HFHE FERPA EL Lo”
441, fxto8#863.1472, dmé=#"neLL0"Pace 28 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
2.7 Study this program fragment:
int num, nj double 2; char ¢;
num = -1; 1 = 99; 2 = 9.99; c= "9";
nun - scanf ("ed t1f 4c", en, &2, &C);
peints("num = 4a", num)?
printf(", n= 4, 2 = tf, ¢
Se\n", ny 2, 0);
For each of these five input lines, determine what the program generates:
12 4.6%
4.612 2
12 4.6 4.6
12 4.6 b
1234x56.6Y
Ifyou are unsure, you might wish to compile and execute the program.
2.8 To convert from degrees Fahrenheit to degrees Celsius, you must first subtract
32, then multiply by 5/9.
Write a program that undertakes this conversion. Confirm that 212° Fahren-
heit maps to 100° Celsius, and that 82° Fahrenheit maps to a little under 28°
Celsius.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.Chapter 3
Making Choices
This chapter is about making decisions ~ choosing between altemative paths. We do
this all the time in our daily lives: if it is raining we take an umbrella, and if it is
sunny we do not; if itis dark we turn on a lamp, and ifit is light we do not; and if we
dial a wrong number, we apologize and then dial again more carefully.
Inprograms we need to make the same kind of conditional choices — if the number
read using a scant is negative, we might need to print an error message; ifthe scant
doesn’t read enough values, we might want to repeat it; and so on. In C there are two
‘mechanisms for performing this kind of selection, and they are discussed in detail in
this chapter. But first, Section 3.1 introduces a new kind of expression, one that is
regarded as being either true or false.
3.1 Logical expressions
‘Table 3.1 lists the standard relational and logical operators available in C. The first
group in the table is the relational operators, which are used exactly as you would
imagine: to compare two numeric values. Like the arithmetic operations listed in
Table 2.1 on page 20, if either of the two operands is a float or a double, the
other is cast to match before the comparison is undertaken. This makes sense: the
expression “1<1.1", should be true, which would not happen if the double was
converted to an int rather than vice versa. Note also —and this is critical — the use of
“=” in the equality test rather than “~”. Every C programmer has made the mistake
of using an “=” when they really meant “==”. The difference can be disastrous.
The table talks about “true” and “false” as if they are values. In fact, in C there are
‘no explicit constants true and false the way there are in some other languages, and the
result type of all of the operators in Table 3.1 is int. The rule in C is that the integer
value zero is always taken to mean “false” in places where a logical expression is
required; and that all non-zero values (including negative ones) are taken to mean
“true”. Conversely, when logical values are being generated, if a subexpression is
false, the value 0 is produced from that subexpression; and if the subexpression is
true, the value 1 is produced. This rather idiosyncratic interpretation means that it is
possible to write statements like nun.neg+=(n<0), for example, which adds one to
variable num_neg if variable n is negative.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPace 30 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
Operator Operation True when...
< _lessthan first operand is less than second
<= lessthan or equal _first operand is not greater than second
> greater than first operand is greater than second
greater than or equal first operand is not less than second
equal to first operand is equal to the second
not equal to first operand is not equal to the second.
and both operands are true
or either operand is tue
not the operand is false
‘Table 3.1: Relational and logical operators. As with the arithmetic operators in Table 2.1 on
page 20, if either operand is of type Sloat or doub oe, the other is converted to the same type
before the operation is applied. But here the result is always of type int. Note very carefully
the use of “==" for equality testing, not “=”, which indicates assignment.
Operands Operation
el_e2 _elese2 eliie2 sel
0 0 0 0 1
0 NZ 0 1 1
NZ 0 0 ii 0
NZ_NZ 1 1 0
‘Table 3.2: Details of logical operators. Both operands are of type Anz, and are cast if they
are not. For the purposes of these operators non-zero (NZ) values are treated as “true”, and
zero values as “false”.
The three logical combining operators ~ “and”, “or”, and “not” ~ that are listed
in Table 3.1 and defined in Table 3.2 may also be familiar. But there is one subtle
difference to be aware of — in English, when we say something like “would you like
coffee or tea", we don’t expect the answer to be “both”. But in C, a logical “or”
expression is true when either of the subexpressions is true, and is also true when
both of the subexpressions are true.
Given these relational and logical operators, can you work out the circumstances
under which each of the following integer-valued expressions is 1 (truc)?
cx
Sex && x comparison
“ equality
ae and
a) or
etc assignment Lowest.
‘Table 3.3: Precedence hierarchy for the arithmetic, relational, and logical operators that have
‘been introduced so far. The three unary operators not, negation, and cast, all have equal
precedence. Assignment is also an operator, but unlike the other operators listed, is evaluated
from right to left when precedence is equal.
These rules are known as De Morgan's Laws, after the mathematician who first
demonstrated their use.
Relational and logical expressions generate int values that can be
interpreted and used as if they correspond to true and false.
Having extended the set of operations, it is time to look at precedence again.
Table 3.3 lists all of the operators that have been discussed so far, in decreasing
precedence order. Using the table, for example, it is possible (but not exactly easy)
to work out the value of:
4243 664-5116
748
9/7 10> 21
‘The answer here is 1. Whether or not a programmer should be rewarded - in any way
at all - for writing such an awful expression is an entirely different story. There is no
doubt that the best policy is to over parenthesize, especially when mixing arithmetic,
relational, and logical operators in the same expression.
Including redundant parentheses costs nothing. Omitting necessary
parentheses can cost everything.
‘A final point to be noted from Table 3.3 is that assignment is an operator, like
any other. The value of an assignment statement is the value that is assigned, and the
actual assignmentis a side effect that happens while the expression is being evaluated.
Assignment is also one of the few operations in C that is evaluated from right to left.
Hence, expressions like ‘n=m=p=q=0" make perfect sense. That one is interpreted
= (q=0)))”, and all four variables are assigned zero. More complex
expressions are also possible: “n+~n++” is legal, but an absurd thing to write. If you
write this kind of expression in your program, you will probably get exactly what you
deserve.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonPage 32, PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
‘The C system is free to determine the order in which the various components of,
an expression are evaluated. For example, in the expression a+b+ eed, the system is
permitted to evaluate a+b first and then cd, or to do it in the other order. All that the
precedence rules require is that the two multiplications take place before the addition.
This flexibility means that if any of the subexpressions a, 5, c, or d have side effects
—as is automatically the case when any of them involve assignment operators — then
the semantics are unclear. You should avoid such confusion in your programs by not
trying to be too clever: remember to keep it simple, stupi
Beware of the side effects caused by assignment operators inside
expressions. Use them cautiously and sparingly.
‘There are two operators for which the ANSI C standard does stipulate the evalu-
ation order: in the expression “a &« B” (logical and) you are guaranteed that b will be
evaluated only if a is found to be non-zero; and in the expression “a | | 8” (logical or)
‘you are guaranteed that b will be evaluated only if a is found to be zero. That is, these
‘two logical operators are evaluated in a strict ordering, and the second component is
evaluated only if its value determines the whole expression. Hence, it is safe to write
things like “x!-0sey/x>5”: by the time “y/x>5” is evaluated, you are guaranteed
that “x! =0”, so a “divide by zero” error cannot arise during computation of “y /x>5”
The evaluation of the logical operators “s«” and “| |” is performed in a
lazy left-to-right manner. The second operand is evaluated only if it
determines the value of the expression.
3.2 Selection
Now for the if statement. The most general form looks like this:
3€ ( guard )
statement]
else
statement
‘There is a second version that omits the e1se part and looks like this:
if (guard )
statement
Either or both of statement] and statement2 can be empty statements (no statement
at all), single statements, or compound statements bracketed by “(" and ‘*)” pairs,
‘The examples given shortly show what is meant by this.
When an i£ statement is executed, the value of the logical expression used as the
‘guard is calculated. If the expression is true (non-zero), then statement! is executed.
If the expression is false, and an clse part is given, then statement2 is executed,
Figure 3.1 shows this flow of control.
The best way to grasp the power of this statement is to look at the examples
shown in Figure 3.2. Although the two alternative branches on an i statement each
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised Editon3.3. PITFALLS Pace 33
Figure 3.1: Execution flow through a i £ statement when an ese partis given.
nominally contain just a single statement, a group of several statements can also be
controlled if they are enclosed in a'“(” and “}” pair to form a compound statement. If
Just one statement is being controlled, as is the case in the first example in Figure 3.2,
the braces are not needed. Strictly speaking, they are not needed in the last example
either, because the comments are not statements, But it doesn’t hurt to have them
there, and it is far easier to always put the braces in than it is to decide whether or not
they are required; and potentially less confusing to a reader of the program.
‘The i £ statement allows alternative execution paths to be followed,
based upon the values of variables during execution. Multiple
statements can be controlled if braces are used to create a compound
statement.
The second example in Figure 3.2 shows how the if can be combined with
scans to verify that data is being read correctly. ‘The call to function exit pass-
ing the argument EXIT .FATLURE is a directive to “quit executing the program, there
has been a serious error”. If execution is to be terminated without signaling an error,
the call exit (2XIT-SUCCESS) should be used instead. Both EXIT_FAILURE and
EXIT.SUCCESS are defined symbolically in the file std@lib.h. In many operating
systems, the argument passed to the exit function is available after the termination
of the program, and can be used as a diagnostic as to why the program terminated.
‘The function exit can be used at any point to terminate program
execution. Return of a non-zero exit value signals an “abnormal”
termination.
The final example in Figure 3.2 shows a cascading 4 ¢ statement, in which more
than two outcomes are available. Nothing special needs to be done to obtain this
functionality, and any number of ‘else i” groups can be strung together. The last
else clause catches the remaining cases not dealt with by any of the guards, and
each time the overall construct is executed, exactly one of the alternatives is selected.
3.3 Pitfalls to watch for
‘There are a number of pitfalls associated with the use of i statements, usually in
connection with the guard. Figure 3.3 shows the most common of these problems.
CCopytght © Peersen Austata e divin of Pearson Austala Group Ply Ll) 2018 976486010674 -MofletPrograrvning, Problem Galng, and Abstraction wih © Revised EditonPage 34 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
if (n <0)
if (scanf(sdtdtd", en, om, 6x) !
print£("scanf failed to read
‘exit (EXIT_FAILURE) ;
3
three items\n");
if (yeart4==0 &6 (yearti00!=0 11 yeart40\
7+ need to allow for leap years */
length_of_year = 3667
length_of_feb = 29;
) else {
J= not a leap year «/
Jength_of_year = 365;
Jength_of_feb ~ 28;
= length_of_feb;
I month==6 I
9 || month==11) {
Js thirty daye hath september, april, june,
and november */
Jengeh_of_month = 30;
) else {
J= all the rest have 31, except february... */
Jength_of_month = 31;
Figure 3.2: Examples of the use of the if statement. Statements between a “{” and “}” pair
are a compound statement, and treated as a single statement.
‘At face value, when the number zero is entered the program should print a message
that more students can be accepted. But when the program is executed (the lower
box in Figure 3.3), the other message is printed, and itis clear that the {£ statement
took the first of the two alternative paths. Why? Well, you were warned about this
earlier — look carefully at the guard in the i, and count the number of “=” characters.
‘Two are required for an equality test, and when there is only one, it is an assignment
statement. So that guard says “assign the value MAX.CLASS.SIZ# to the variable
clacs.size, and then, if the value that was assigned is non-zero, execute the first
problem. The gcc compiler used while preparing this book does not naturally give
such warnings (sce the first compilation linc in the lower box of Figure 3.3), but can
be instructed to look for potential problems via the use of the “a1” option to the
“1” compiler wamnings-level flag (the second compilation line), which asks for all
‘warming messages to be listed. The ~ansi flag similarly asks that the gcc compiler
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon3.3. PITFALLS Pace 35
define MAX_CLASS_sIZE 50
int class_size;
printf ("Enter class size: ");
scant ("sa", &class_size);
Af (class_size = VAX_CLASS SIZE) (
print£("Class is now full\n");
} else {
printf("Wore students can be accepted\n");
)
gee -0 equalinif equalinif.c
: .fequalinit
Enter class size: 0
Clase ie now full
mac: gcc Mall -ansi -o equalinif equalinif.c
equalinif.c: In function ‘main’:
equalinif.c:11: warning: suggest parentheses around
assignzent used as truth value
Figure 3.3: A flawed i statement. The program always prints “Class is now full”, even if
2 class.sizo of 0 is entered. The reason why is revealed in the second compilation line
shown in the lower box, when all warning messages are requested using “-Wa11”. Now the
compiler draws attention to the assignment statement inside the guard of the { statement,
and suggests that it might be problematic, despite that fact that the program is technically
correct as it stands.
int x=3, v4, 2-6
if (02)
SE (y>6)
2am
else
z= 87
printf(*after the if statement 2=4d\n", 2)7
Figure 3.4: Another flawed i statement.
not accept any constructs that are not part of the ANSI standard definition of C.
‘There is no reason at all why you shouldn’t always use these warning and diagnostic
facilities if they are available.
What about the program fragment in Figure 3.4? What is the final value of 2’?
Should be 6, right? The first guard is uue, but the second guard is false, right? So
z remains unchanged, right? Wrong! The rule is that an ice part attaches to the
most recent unmatched if that is available to it, irrespective of program layout. So
the e1se in this fragment belongs to the second i, and when the second guard is
false, the statement 2~8 is executed.
Like the previous pitfall, the program in Figure 3.4 is correct according to the
rules of C, and when compiled using the default gcc options, no warning message is
‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised ElionPace 36 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
generated. But when -via11 is used:
mac: gee Wall ~ansi -o danglingelse danglingelse.<
denglingelse.c: In function ‘main’:
danglingelee.ci10: warning: euggest explicit braces to
avoid ambiguous ‘else’
This issue is known as the dangling else question, and the C rule is the one usually
adopted in programming languages in which it arises. If you always put the braces
in, as was recommended a few paragraphs ago, you will never encounter a dangling
else in your programs.
If your C compiler provides for additional warning and diagnostic
facilities, you should gratefully accept the assistance.
‘One last example draws out another mistake that it is easy to make: what is the
final value of z in this program fragment?
int x3, yah, e6)
af (Cy <2)
z= atl;
if (2 > y> x)
2 = 242;
printf(*after the two if statements z=sd\n", 2);
The obvious answer is 9, but by now you are probably (and rightly) suspicious of
the obvious answer, In fact, the program prints 7. To understand why, insert the
implicit precedence-derived parentheses, which make the second guard (2>y) >x.
‘Then remember that (>y) will be either zero or one. When the first version of this
book was written, using -Wa11 didn’t help find this type of problem — the compiler
was silent even when you asked to be warned of possibly erroneous constructs. But
the gcc compiler is under constant development, and it now recognizes this potential
problem and issues a warning message that “comparisons like x < y < 2do not have
their mathematical meaning”, Take the hint, and always use ~ma11.
3.4 Case study: Calculating taxes
You now have enough C knowledge to tackle a non-trivial program. See if you can
implement a solution to this calculation:
The 2012/13 Australian tax rates stipulate that annual income between
$18,200 and $37,000 is taxed at 19.0 cents in the dollar; income be-
tween $37,000 and $80,000 at 32.5 cents in the dollar; and income
between $80,000 and $180,000 at 37.0 cents in the dollar. Any further
income is taxed at 45.0 cents in the dollar. In addition, a Medicare levy
of 1.5 cents in the dollar is applied to all income. For a given gross
income, what net income is received?
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised Editon3.4 Case srupy Pace 37
7s Calculate Australian tax and Medicare levy, 2012 scales.
“/
include
include
fdefine RATED 0.000
fdefine RATE 0.190
fdefine RATE2 0.325
fdefine RATE3 0.370
fdefine RATEG 0.450
fcefine RATEM 0.015
fcefine THRESH! 1820.00
define THRESH2 3700.00
fdefine THRESE3 80000.00
fcefine THRESHs 180000.00
define BASED 0.00
fdefine BASEL (BASEO + RATEQ*THRESH1)
ficefine BASE2 (BASE1 + RATE1s (THRESH2-THRESH1))
fcefine BASE3 (BASE2 + RATE2« (THRESH3-THRESH2))
fdefine BASE4 (BASE3 + RATE3«(THRESHI-THRESH3))
int,
main(int arge, char sargv{]) {
Gouble gross, tax, medicare, net;
print£(*snter gross salary: $*);
4£ (scanf ("$1£", goross) != 1) {
print£("No value was entered\n");
exit (EXIT_FATLORE) ;
)
4£ (gross <= THRESHL) (
tax = BASEO + gross+RATEO;
} else if (gross <= THRESH2) {
tax = BASEL + (gros~THRESH1) «RATE1;
) else sf (gross <= THRESH3) (
tax = BASE2 + (gross-THRESH2) #RATE2;
} else if (grose <- THRESH) [
tax = BASE3 + (gross-THRESH3) «RATES;
) else {
tax = BASES + (gross-THRESH4) «RATES;
)
medicare = RATENsgross;
net = gross ~ tax ~ medicare;
print£(*grose incone $89.2£\n", gross}
printf ("less tax $89.2f\n", -tax);
print£(*less medicare 989.2£\n", -medicare);
print£("net income $89.2£\n", net);
return 0}
‘Figure 3.5: A program to calculate net income es a function of gross income.
‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised ElionPace 38 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
Figure 3.5 shows how the task can be tackled using a cascading if statement.
Note how the use of symbolic constants avoids much of the complexity inherent
to this computation — in a sense, the program is controlled by two tables, one of
threshold amounts, and another of corresponding tax rates. Changes to the thresholds
or tax rates can thus be made relatively easily, and even if the number of steps in
the tax scale changes, it is clear how the program should be altered. On the other
hand, the program is also repetitive in its computation, and there is scope for exrors to
creep in because of that. Chapter 7 introduces techniques that allow a more elegant
implementation of this kind of task. Until then, the program in Figure 3.5 is pretty
much the best we can do for this problem.
Here is what happens when it is executed:
mac: ./taxation
Enter gross salary: $98765.43
gross incone § 98765.43
less tax $-24490.21
less medicare $ 1481.48
net. income $ 72793.73
Neat and tidy output is important if the eventual users of a program are to place
their confidence in a program, and you should never forget that the only part of your
program seen by most users is the interface though which input values are read and
output values are reported.
If the interface to a program is untidy or awkward to use, users will
‘assume that the program itself is of poor quality.
3.5 The switch statement
‘There is another mechanism provided in the C language to achieve selection ~ the
switch statement. It doesn’t really offer any extra functionality compared to the it
statement, nor is it any more succinct. Indeed, the one way in which it differs from
the if statement is capable of causing more confusion than it is worth, and you are
advised to avoid any use of the switch.
Nevertheless, you may encounter the switch in programs that you are asked to
‘maintain. The general form of itis
switch ( integer expression ) (
case ( integer! ):
statement]
break;
case ( integer? ):
statement2
break;
case (integer n):
statement n
break;
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.3.5. THE SWITCH STATEMENT Pace 39
default:
statement
)
When executed, the value of the integer expression is calculated. That value is then
compared in turn against the various case expressions, until either a match is found,
or the default (if it exists) is reached. The corresponding statement or list of
statements is then executed, continuing through until cither the closing brace of the
switch is encountered, or until a break statement is executed. Note that the general
form shown here presumes that there is a break for each case. Unfortunately, it is
not mandatory.
If there is a break after each group of statements, the behavior of the switch
is the same as that of a corresponding cascading if. The following box shows a
switch that is well structured in this regard:
‘switch (month) {
case 2:
length_of_month = 28 +
(year’4==0 4& (yeart100!=0 || yeart40
break;
case 6:
ease 11:
length_of_ronth
break;
default:
Length_of_nonth
break;
Note how in this case the accumulation of cases is plausible ~ a bit like several differ-
cent tests connected with “or” operations in an 4 ¢-statement guard. In this fragment
there are three mutually exclusive sets of statements controlled by the switch, and
three matching break statements.
If the programmer does not follow the discipline of having one reak for every
‘group of statements, cases flow together in a chaotic and confusing manner. It is for
this reason that the switch statement is to be distrusted. Program execution starts at
the first case with a matching value, and moves through all subsequent statements
‘until a break is encountered. Programmers trying to be “clever” then order the cases
to exploit this flexibility. To see an example of this “cleverness”, trace the switch
statement in Figure 3.6 for each possible starting value of x between 1 and 10, and
determine the final value of x that corresponds to each starting value. Confusing,
isn't it! Should a programmer who writes things like this be rewarded?
The switch statement offers a general form of the cascading i¢. Use
it with caution, and maintain the discipline of having a brea for each
non-empty group of statements,
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonPace 40 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
witch (x) {
case 1
case 4
case 7:
break;
case 3)
case 9:
xi 3;
default:
Figure 3.6: A dangerous switch statement,
Exercises
3.1 Number each of the operators in this expression with the order in which it is
applied. Then work out the value of the expression.
7 7 10>
a<5 a6 6
&
Tee-2s
3.2 Trace the action of these statements, and determine the values printed out by
each of the print £ statements. Assume that all variables have been declared
to be of type int. Be careful — some of them illustrate common errors.
a T
£ (i
fdefine NAX_YEARS 7 /+ number of years to compute for */
fdefine MONTHLY 100 /+ monthly savings amount «/
fcefine MIN.RATE 2 /+ minimum annual percentage rate +/
fdefine NAXRATE 7 /+ maximum interest rate */
int
main(int arge, char vargv(}) (
int month,
rate,
year;
double balance,
nonthly_rate;
/s print the table heading lines +/
print£(*Monthly savings of $%d", MONTHLY);
print£(", with monthly compounded interest\n");
printf(*Annual Rate 1");
for (rate-MIN RATE; rate<-MAX RATS; ratet+) [
printe("e4d¥s ", rate);
)
print£(*"\n")5
/+ and now the rows of the table, one by one +/
for (year=1; year<-MAK_YEARS; yeart+) (
print£("After tld years | ", year);
for (ratenMIN_RATE; rate<-MAX RATE; rate++) {
/* compute one value */
balance = 0.
monthly_rate = 1.00 + ((rate/100.09)/12);
for (month=1; monthe=12syear; month++) (
balance «= monthly_rate;
balance += MONTHLY;
)
print£("$5.0£ *, balance);
}
J* end of one row +/
print£(*\n");
)
return 0;
Figure 4.6: Using nested loops to generate a table. An example of the output generated by
this program appears in Figure 4.5.
braces should be prominently displayed. Yet another style tucks the closing brace
of each compound statement up at the end of the last statement. What is important
is that you adopt a single style, and then stick with it. Consistency is more impor-
tant that the particular style used. Indeed, to obtain consistency, organizations often
‘Copyright © Pearson Ausbata(edivsin of Pearson Australia Group Pty Li) 2010 ~ 976406010674 -MullevProgramming, Problem Soiving, nd Abstraction wih C Revised ElionPage 52 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
printi("Enter date in dd/mm/yyyy format: ");if (scant (
"ad/ad/%d", edd, om, eyyyy) !=3) (printf ("Invalid input \n")
jexit (EXIT_FAILURE) ; }length_of_feb~28+ (yyyyt4==066 (yyy
§100!-0] | yyyy#400--0) ) ;daynum-dd; for (nonth~1 jmonth1;) is identical, and would have served equally well, but the use of the
word white in some sense captures the open-ended nature of the computation ~ we
are not actually in a position to demonstrate that this loop will terminate, since there
is no guarantec that every path through the loop results in the guard moving closer to
becoming false.
Note also that in this program a single nested loop has been used, despite the
fact that the output of the program again appears as a table. In this case the tabular
layout is purely a convenience, and the underlying computation is essentially one-
dimensional. So a single loop is used, and the two-dimensional output is obtained
through the use of an if statement within the loop that periodically inserts newline
characters into the output character stream.
<_ gues >
Non-orol
statement
Figure 4.8: Execution flow through a whi Le statement.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonCopyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
Page 54 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
7+ @ value for n has been read +/
cycles = 0;
while (n>1) (
printf (*"’5d ", n);
) else {
n= Sent;
)
Sf (npmax) {
max = nj
1
eyeles 4 1;
Sf (cyclestPERLINE
print£("\n");
)
)
print£(*\n$d cycles consumed, maximum was d\n",
cycles, max);
mac: ./threen
Enter starting value for n: 8
ay” wh (2
3 cycles consumed, maximum was 8
mac: ./threen
Enter starting value for ni 9
9 2 14 7 22 WW 34 17
52 26 «413 «400 «20 «10tiSC
a
19 cycles consumed, maximum was 52
Figure 4.9: A program to explore some properties of the 37 + 1 problem.
Both for statements and wh:.1e statements share a common attribute — they test
the guard prior to each and every iteration, and continue with that execution only if,
the guard is true, This means that they cannot terminate until the guard is false. More
to the point, it means that when such loops do terminate, the guard is always false.
When a for or while loop terminates, the guard is false,
This observation means that one way of creating a loop guard is to decide what
is supposed to be true at the end of the loop, and then make the guard the negation of,
that. For example, if n==1 is required at the end of a loop, the guard should be n !=1
Every iteration of the loop should then move a step closer towards changing the guard
from true to false. If you think about your loops as needing to make progress towards
falsifying the guard, you will be less likely to get bogged down debugging infinite
loops.
If a loop is to terminate, every iteration must move one step closer to
‘making the loop guard false.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonCopyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
4.4 UNCONTROLLED ITERATION Pace 55
7+ @ value for n has been read +/
isprine = 1;
for (divisor=2; divisorsdivisormax) {
print£("td values read, maximum is $d\n", n, max);
mac: ./readloopl
Enter values, control-D to end: 12326527154
‘D
9 values read, maximum is 27
Figure 4.12: Use of scan¢ in a loop to process a set of input items of arbitrary size. The
Jower box shows an execution of the program fragment in the upper box.
Copyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonCopyright © Pearson Ausbata (edison of Pearson Australia Group Pty Lt) 2019.
Pace 58 PROGRAMMING, PROBLEM SOLVING, AND ABSTRACTION
int ch, incomment=0, newlinelast=1;
while ((ch=getchar()) != EOF) {
if (ch == 'C’ && newlinelast) {
incomment ~ 17
3
if (!incomment) {
putchar (ch);
)
if (ch == "\n") {
incomment =
Rewlinelast
) else {
newlinelest = 0;
)
mac: more data.txt
Ca comment in the first line
ut no Comtent here
or here
© but there ie one here
mac: ./fortconm < data.txt
but no Content here
or here
Figure 4.13: Use of get char and putchar to process the input stream character by char-
‘acter. The program fragment removes lines that start with an uppercase “C”, The lower box
shows an execution of the program fragment in the upper box.
and output — the functions get char and putchar. To show the use of these two
functions, suppose that we are required to write a program that deletes all of the
lines in a file that start with an uppercase “C”. (This is the convention for indicating
comments in Fortran programs.) Figure 4.13 shows a program fragment that achieves:
this goal. The first character of each line is the character after the previous newline
character; and a newline always ends a comment.
‘Note the loop guard, and the way in which the guard both assigns to variable ch
the integer ASCII value of the next input character, and then also tests to see if the
assignment resulted in a valid value. This is one situation in which assignment side
effects can be both tolerated and exploited, to make a recipe for reading that all C
programmers know and use.
‘The predefined constant EOF takes on a value outside the ASCII set, and in most,
implementations has the value —1. The need to represent this non-character is why
cch must be declared to be an int rather than a char.
Functions getcha® and put char allow processing of the input as a
stream of characters. The variable used must be declared to be an int.
in order for end of file value EOF to be manipulated properly.
And now for a challenge. Earlier in this book you saw a C program that read a
set of numbers and printed out their sum, Without looking back at page 8, can you
76486010074 - MollProganning, Problems Golvng, and Abstraction wih © Revised EditonEXERCISES Pace 59
write an equivalent program using the C programming techniques described so far’?
If you can, you are doing well; if you can’t, you should review Chapters 1, 2, and 3,
before proceeding to the next chapter. Now might also be a good time to implement
solution to Exercise 1.3 on page 12.
Exercises
4.1 Trace the action of these loops, and determine the values printed out by each
of the print £é statements. Assume that all variables have been declared to be
of type int. Be careful with the last two — they illustrate two common errors.
a for (1=0; 1<20; 1-143) {
print£("82d\n", i);
}
b. for (i=1; i1<2000000; i=24i) {
print£("87d\n", 1);
)
G
(ist; isto; itt) ¢
peint£("S(#2d) = #2d\n", i, sum);
)
a. 7 i<8; i+) 1
for (Sith; 3<8) 5
printf ("i=td,
}
)
e for (1-0; i<8; i++) {
for (Jeitt; 3<8; 3483) (
if (its=57) (
break;
>
print£("ietd, jmtd\n", i, 4);
1
»
f. 7-5
for (1-0; ict; At {
printf ("i-td, j-td\n", 3, 3);
d
B a= 5
For (in0; i