Tech Your Self C PDF
Tech Your Self C PDF
Tech Your Self C PDF
Third
•
Teach
Yourself
c
Third Edition
"'\ct. io..~ ~ ~
II'(';)C\oJ}
OsbOrne McGraw-HIM
8ef1itele) New York St louis Sen Ft~ncis!:o AuclQInG ~ Hamburg london Medrid Me.voo Cit)'
Milan MontnseI j.,;aw Delhi ?tI11IO/NI Oty Pant SIo P.uIo S:ogapore S')IdI)8y Tokro TOI'Onto
•
Teach
Yourself
c
Third Edition
. OsbOrne McGraw-HIH
8e~ ~ YOt1l St lOUis Sen Fr.nciso:) AucklIII'IO ~ HIomOuI'Q london M.and Me~~ Cit)<
SIo....,
M:1an Montreal l.oew Delhi ' nT'I5IM City Pw.s S:fIG8pOfe: Sydney Tok)'O Toronto
,".,. ' ,
Contents
Preface, Xl
For Ftmher study, XV"
,,,,'.)' C Fundamentals . . . 1
1.1 UNDERSTAND THE COMPONENTS Of A C
PROGRAM, 2
1.2 CREATE AND COMPILE A PROGRAM. 7
V3 DECLARE VARIABLES AND ASSIGN VALLIES,
• 10
1.4 INPUT NUMBERS fROM THE KEYBOARD. 15
1.5 PERFORM CALCULATIONS USING
ARITHMETIC EXPRESSIONS, 17
1.6 ADD COMMENTS TO A PROGRAM. 20
1.7 WRITE YOUR OWN FUNCTIONS, 23
1.8 USE FUNCTIONS TO RETURN VALUES, . 27
~ USE fUNCTION ARGUMENTS, 32
1.10 REMEMBER THE C KEYWORDS, 35
2 Introducing C's Program Control Statements . . . 39
2.1 BECOME fAMILIAR WITH THE if, 41
2.2 ADD THE else, 44
2.3 CREA'rE BLOCKS OF CODE, 46
2.4 USE THE for LOOP, 49
2.5 SUBSTITUTE C'S INCREMENT AND
DECREMENT OPERATORS, 54
2.6 EXPAND printf( )'S CAPABILITIES, 58
2.7 PROGRAM WITH C'S RELATIONAL AND
LOGICAL OPERATORS, 61
o Answers .. 493
Index • .. 633
Preface
A Short HIst"" of C
C was invented and first implemented by Dennis Ritchie on a DEC
PDP-II using the UNIX operating system. C is the result of a
development process that started with an older language called BCPL,
developed by Martin Richards. BCPL influenced a language called B
that was invented by Ken Thompson and that led to the development
of C in the 1970s.
For many years, the de facto standard for C was the one described
in The C Programming Language by Brian Kernighan aJ;ld Dennis
Ritchie (Prentice-Hall, 1978). However, as C grew in popularity, a
committee was organized in 1983 to create an ANSI (American
National Standards Institute) standard for C. The standardization
process took six years (much longer than anyone reasonably
expected). The ANSI C standard was finally adopted late in 1989 and Ix
."
•... TEACH YOURSELF
the first copies became generally available in 1990. The standard was
amended slightly in 1996. Today, virtually all C compilers comply with
ANSI standard C and that is the version of C you will learn in this
book. (That is, this book teaches ANSI standard C.)
C is often referred to as a mllidle-Iel'ellanguage. Before C th~re "'ere
basically two types of languages used to program computers. One is
called assembly language, which is the symbolic representation of the
actual machine instructions executed by the computer. Assembly
language is a low-Ievellangllage because the programmer is working
with (in symbolic form) the actual instructions that the computer will
execute. Assembly language can be used to create very efficient
programs, but it provides no built-in control structures or 110
functions. All such items must be manually constructed by the
programmer. By contrast, a hlgh-levellal1guage b~ffers the programmer
from the computer. A high-level language typically supplies various
control structures, input and output commands, and the like , which
make programming easier and faster. However. the elements of a
high-level language may not relate directly to the way that the
computer ultimately carries out the program. This separation often
causes programs written using a high-level language to be less efficient
than those written in assembly language. Because many people find
assembly language programming to be a tedious, difficult task, there
was a need for a language that balanced ease-of-use with efficiency.
Many programmers feel that C provides this balance. It successfully
combines the structure of a high-level language with the power and
efficiency of assembly language. Since it spans the gap between
• assembly language and high-level languages, it is called'a middle-Ie"el
language.
Initially, C was used primarily for creating systems sojtu'are. Systems
software consists of those programs that help run the computer These
include programs such as operating systems, compilers , and editors
However, as C gained in popularity, it began to be used for general
purpose programming. Today, C is used by programmers for virtually
any programming task. It is a language that has survived the test of
time and proven itself to be as versatile as it is powerful.
C IrS. c++
If you will be developing programs for the Web, you will want to
read
ret-type function-name(param-list)
{
statement sequence
}
•
.,
4 TEACH YOURSElF
C
You can specify the file name in either upper- or lowercase, but
lowercase is the traditional method. The STDlO.H header file
contains, among other things, information related to the printf( )
library function. Notice that the #include directive does not end with
a semicolon. The reason for this is that #include is not a C keyword
that can define a statement. Instead, it is an instruction to the C
compiler itself.
One last point: With few exceptions, C ignores spaces. That is, it
doesn't care where on a line a statement, curly brace, or function
name occurs. If you like, you can even put two or more of these itenlS
on the same line. The examples you wiII see in this book reflect the
way C code is normally written; it is a form you should follow. The
actual positioning of statements, functions, and braces is a stylistic,
not a programming, decision.
EXAMPLES
int rnain(void)
{
printf(~This is a short C program.");
return 0;
)
..
8 TEACH YOURSD.f
C
. function,
This is a,C statement. It calls the standard library
printf( ), which causes the string to be displayed.
The following line causes maine ) to return the value zero. In
this case, the value is returned to the calling process, which is
usually the operating system.
return 0;
int main(void)
(
printf("This is ") i
printf(-another C R) i
printf("program. R ) ;
return OJ
EXERCISE
-
I. Enter into your Gomputer the example programs from Section
1.1. Compile them and run them.
. .
~ Keyword
character data char
signed whole numbers int
floating-point numbers float
double-precision floating-point numbers double
valueless void
TABLE 1-1 C's Five Basic Data Types T
1.3
C FUNO_ENTALS
type var-name-
where type is a C data type and var-name is the name of the variable.
For example , this declares counter to be of type int:
int counter ;
'" c
You can declare more than one variable of the same type by using a
comma-separated list. for example, thIs declares three floating-point
variables, x, y, and z:
float x, y, z;
variable-name = value;
For e.ample, to assign an Integer variable named num the value 100,
you can use this statement:
num = 100;
%d" . 991;
pr~ntt ( 'T1_~ prl.nts the number '
C FIJNOAMEJfI'ALS 13
1.3 DEClARE VARIABUS AND ASSIGN VALUES
'"
displays This prints the number 99 on the screen. As you can see,
this call'to printf( ) contains not one, but two arguments. The first
is the quoted string and' the other is the constant 99. Notice that the
arguments are separated from each other by a comma. In general,
when there is more than one argument to a function, the arguments
are separated from each other by commas. The operation of the
printf( ) function is as follows. The first argument is a quoted string
that may contain either normal characters or forma! specifiers that
begin with the percent sign. Normal characters are simply displayed
as-is on the screen in the order in which they are encountered in the
string (reading left to right). A format speCifier, also called a format
code, informs printf( ) that a different type item is to be displayed. In
this case, the %d means that an integer is to be output in decimal
format. The value to he displayed is found in the second argument.
This value is then output to the screen at the point where the format
specifier is found in the string. To understand the relationship
between the normal characters and the format codcs, examine this
statcment:
printf (-This displays %d. too", 99);
Now the call to printf( ) displays This displays 99, too. The key
point is that the value associated with a format code is displayed at the
point where that format code is encountered in the string.
If you want to sped/)' a character value, the format speciffer is %c .
•
To specify a floating-point value, use %f. The %f works fpr both float
and double. As you will see, printf( ) has many more capabilities.
Keep in mind that the values matched with the format specifier
need not be constants; they may be variables, too.
int main(void)
(
int num;
num = 100;
printi ("The value is %d ", num) ;
return 0;
)
The statement
i nt num ;
1n t ma1n(void)
(
c har ch
float f;
double d;
ch = 'X';
f = 100 . 123;
d = 123. 00 9;
printf("ch is %c ... , chI;
printf("f is %f, ., f);
printf("d is tEo, dl;
return 0:
)
C RlNDAM£NTALS 15
~
,.. ,NPUT NUMBERS FROM TIlE KEYBOARD
scanfC'%d". &int-var-name);
where im-uar-l1ame is the name of the integer variable you wish to
receive he value. The first argument to scanf( ) is a string that
determines how the second argument will be treated. In this case, the
%d specifies that the second argument will be receivir g an integer
value entered in decimal format. This fragment. for example, reads an ·
integer entered from the keyboard.
int num;
scanf ("'d·. &num) i
J
16 TEACH YOURSELF
'" C
scanfC'%f', &floal-var-name);
- EXAMPLE :
int main(void) •
{
int n\lln:
float f;
return 0:
}
C FUNDAMENTAlS 17
1.5 PERFORM CALCULAnONS USING ARfTHME77C EXPRESSIONS
"
EXERCISES
Operator Meaning
+ addition
subtraction
• multiplication
t division
% modulus
The +, -, I, and' operators may be used with any of the basic data
types. However, the % may be used with integer types only. The
modulus operator produces the remainder of an integer division.
This has no meaning when applied to floating-point types.
The - has two meanings. First, it is the subtraction operator.
Second, it can be used as a unary minus to reverse the sign of a
number. A unary operator uses only one operand.
An el'pression may appear on the right side of an assignment
statement. For example, this program fragment assigns the integer
variable answer the value of) 00' 31.
1.
.~
_YOURSElf
C
int answer;
answer = 100 • 31;
10 - 2 0 5
but this one produces the value 40.
(10-2)05
EXAMPLES
int main(void)
{
print! ("'d", 5 / 2) ;
printf(" %dOl , 5'2) ;
printf(" %d· , 4/2) ;
printf(" %dOl , 4%2) ;
return 0; .
)
int main(void)
(
int len, width;
return 0:
i = 10;
i = -i:
printf(-This is i: %d", i)i
22
'r'
return 0 i
)
EXERCISES ·
int main(void)
{
r ... '/
}
ret-type f1(param-lisf)
{
r' ... */
}
ret-type f2(param-lisf)
(
r ... '/
)
ret-type fN(param-lisf)
{
r ...*/
}
Its prototype is
void myfunc(void);
The only function that does not need a prototype is maine) since
it is predefined by the C language .
Prototypes are an important part of C programming, but you will
. need to learn more about C before you can fully understand their
purpose and value .. for the next few chapters we will be using prototypes
without any further explanation. They will be included as needed in
all of the example programs shown in this book. You should also
include them in programs that you write. A full explanation of
prototypes is found in Chapter 7.
When a function is called, execution transfers to that function. ;Vhen
the end of that ,function is reached, execution returns to a point
immediately after the place at which the function was called. Put
differently, when a function ends, execution resumes at the point in
your program immediately following the call to the function. Any
function inside a program may call any other function within the same
program. Traditionally, maine) is not called by any other function ,
but there is no technical restriction to this effect.
In the examples that follow, you wi11learn to create the simplest
type of C functions: those that that do not return values and do not use
parameters. The skeletal form of such a function is shown here:
void FuncName(void) {
/* body of function here * /
}
C FUNDAMENTAlS 25
1.7 KW1C YOUR OWN FUNCnONS
'"
Of course, the name of the function will vary. Because the function
doe. not return a value, its return rype is void. Because the function
does not have parameters, its parameter list is void.
EXAMPLES
I. The following program comains rwo functions: main() and func1(). Try to
determine what it displays on the screen before reading the description that
follows it.
#include <stdio.h>
int main(void)
printf.("I H);
ftmcl() ;
printf("C."li
return 0;
)
void fuftcl(void)
printf("like ");
)
" C
#include <stdio.h> •
int main(void)
{
func2 () ;
printf{"3~) ;
return 0;
}
void func2(void)
{
funcl (J ;
printf("2 ~);
void funcl(void)
{
printf("! ");
}
EXERCIIU
1. Enter, compile, and run the two example programs in this
section.
2. Write a program that contains at least two functions and prints
the message The summer soldier, the sunshine patriot.
3. Remove the prototype from the first example program and then
compile it. What happens?
answer = sqrt(lO.O);
printf ( ~%f". answer);
return 0;
1
This program calls sqrt( ) and assigns its return value to answer.
Notice that sqrt() uses the MATH.H header file.
28 TEACH YOURSELF
... C
int main(void)
(
printf("%f",sqrt(lO.O));
return 0;
}
The reason this works is that C will automatically call sqrt( ) and
obtain its return value before calling printf( ). The return value then
becomes the second argument to printf( ). If this seems strange,
don't worry: you will understand this sort of situation better as you
learn more about C.
The sqrt( ) function requires a floating-point value for its
argument, and the value it returns is of type double. You must match
the type of value a function returns with the variable that the value
will be assigned to. As you learn more about C, you ",ill see why this is
important. It is also important that you match the types of a function's
arguments to the types it requires.
When writing your own functions, you can return a value to the
calling routine using the return statement. The return statement
takes the general form
return value;
int rnain{void)
(
int num;
nwn = func();
C FUNDAMENTALS
1.8 USE FUNcnONS TO RETU~ .vALUES
printf(~%d·, num);
return 0;
r
int func(void)
{
return 10;
)
In this example, func( ) returns an integer value and its return type
is specified as into Although you can create functions that return any
type of data, functions that return values of type int are quite common.
Later in this book, you will see many examples of functions that return
other types. Functions that are declare' 3S void may not return values.
If a function does not explicitly specify a return type, it is assumed
to return an integer by default. For example, func( ) could have been
coded like this:
func(void)
{
return 10;
)
In this case, the int is implied. The use of the "default to int" rule is
- .
very common in older C code. However, recentlv there. has been a
move away from using the integer default. Whether this trend will
continue is unknown. In any event, to avoid misunderstandings, this
book will always explicitly specify into
, One important point: When the return statement is encountered,
the function returns immediately. No statements after it will be
executed. Thus, a return statement causes a function to return before
its closing curly brace is reached.
The value associated with the return statement need not be a
constant. It can be any valid C expression.
A return statement can also be used bv . itself, without a return
·value. This form of return looks like this:
return ;
'" C
you can also use this form of return in functions that are supposed to
return values. However, doing so makes the returned value undefined.
There can be more than one return in a function. You will see
examples of this later in this book.
Even though a function returns a value, you don't necessarily have
to assign that value to anything. If the return value of a function is not
used, it·is lost, but no harm is done.
EXAMPLES
int get_sqr(void) i
int main(void)
(
int sqr;
sqr = get_sqr();
printf(nSquare: %d K
, sqr);
return 0;
}
int get_sqr(void)
int nurn~
void funcl(void);
int main{void)
{
funcl {I;
return 0;
)
void funcl(void)
{
printf("This is printed. "I;
return; / * return with no value */
printf ("This is never printed.");
EXERCISES
int £1 (void) ;
int main(void)
{
double answer;
answer = fl();
printf("%f-, answer);
return 0;
32 TEACH YOURSELF
~
C
int fl(void)
return 100;
)
void func(void)
{
int i;
return i;
)
E FUNCTION ARGUMENTS
As stated earlier, a function's argument is a value that is passed to the
fimction when the functiQn is ~alled. A function in C can have from
,ero to several arguments. (The upper limit is determined by the
compiler you are using, but the ANSI C standard specifies that a
function must be able to take at least 31 arguments.) For a function
to be able to take arguments, special variables to receive argument
values must be declared. These are called the formal parameters of the
function. The parameters are declared between the parentheses that
follow the function's name. For example, the function listed below
prints the sum of the two integer arguments used to call it.
void surn(int x. int y)
{
printf("%d· x + y);
)
C FUNDAMENTAlS 33
1.9 uSE FUNCnON ARGUMENTS •
Each time sum( ) is called, it will sum the value passed to x with the
\'alue passed to y. Remember, howe"er, that 11: and y are simply the
function's operational variables, which receive the "alues you use
when calling the function. Consider the following short program,
which illustrates how to call sum( ) .
/* A simple progr~~ that demonstrates sum(). -,
~include <sLdio.h>
int main(voidl
,.
sum(l. 2')):
surr.(9, f: ;
s'.lrniE!. 9':
This program "'ilI print 21. 15. and 90 on the screen. When sum( )
is called, the \'alue of each argument is copied into its matching
parameter. That is, in the tirs, rail to sum( ) , 1 is copied illlO x and 20
. is copied illlO y, In the second call, 9 is copied into x and 6 into y , In
the third call. 81 is copied illlO 11: and 9 into y .
If you ha"e ne"er worked with a language that allows parameterized
functions. the preceding process may seem strange. Don't worry-as
you see more examples of C programs. the concept of arguments.
par~meters, and functions wi11 become clear.
Qt is Important to keep two terms straight. First, mgument refers to
Ihe ",lillc that is passed to d function. The variable that rcc.ei'·cs the
,'alul' ul the argument inside the function tS the tomw/ parame,e,' of
the functiun Functions that take arguments are called parame,enzed
34 TEACH YOURSELF
~
C
EXAMPLES
#include <stdio.h>
•
int !"'1ain(void)
outcl)ar( 'h');
outchar( 'B');
outchar( 'e'):
return 0;
printf("%c", ch);
35
1.10
C FUNDAMENTALS
EXERCISES
#include <stoio.h>
int main(void}
(
rett.!rn 0;
)
(
p::-if'.cf ("%d", num * nu!':1);
,\
1.10 EMEMBER
, THE C KEYWORDS
Before concluding this chapter, you should familiarize yourself with
the keywords that make up the C langu,l ge A0!SI C standard has 32
keyu'ords that may not be used as variable or function names. These
words, combined with the formal C syntax, form the C programming
language. They are listed in Table 1-2.
Many C compilers have added several additional keywords that are
used to take better advantage of the environment in which the
compiler is used, and that give support for interlanguage program-
ming, interrupts, and memory organization. Some commonly used
extended keywords are shown in Table 1-3.
The 10\\'ercase lettering of the keywords is significant. C requires
that all kevwords be in lowercase form. For example, RETURN will
not be recognized as the kevword return . Also, no kevword mav be
• y -
---
-- double Int struct
auto switch
else long
break typedef
enum register
case union
extern return
char unsigned
float short
canst void
for signed
continue volatile
goto sizeof
default
static while
do if
- - - -- - ~-~----
- -- --
The 32 Key.vords as Deflfled by the ANSI C Standard ...
TIUIlE 1-2
ds es
asm cs
far huge
_55 cdec!
near pascal
Interrupt
Check
1. The moon's gra\'1t\' Pi about 17 percent of Earth's Writp a
progranl {hat allm\'s you to enter your weight and cOlnpuIes
your effecti\'e \\'C1ghr on the moon .
2. \\'hat is \\Tong \\' ith thi!-. program fragnlent'?
? L~~S inputs a nUITDer
scar.f ( ~%d", &m:m ) ;
2
Introducing CIS
Program Control
Statements
chapter objectlv..
39
"
40
., TEACH YOURSELF
'" thiS ehdpter you will learn about t\\'o of C's most important
program control statcments: if and fOI". In gencral, program
c011trol statements determine your progr<l1l1's flow of execution .
.As such, they.form the backbone of your prugrmns. In addition to
these, yuu ,,·ill also learn about blocks of cocle. the relational and
logical operators, anumore about the printf( ) function.
\ Review
Skills Check
Before proceeding, you should he able to correctly ans"·cr these
qUCStlOllS and do these exercises:
,
1. ;\011 C programs are c;olnposcd of one or more functions. \\'hat is
the name of the function that all programs must llave? rurtl1cr,
\"har special purpose doe~ it perform:
') The printf( ) fUllctlon IS lIsed to outpUt information to the
screen WritC' J program rhdt tlisplJ~' s This is the nurnbcr 100.
(Output the 100 as a number, not as a ,,!·ing.)
3. Header tilt,!'> (untain infonn,l1ion used by tll!" srallcbrd library
fUIlUlOIlS. Hm,· do you tell the cnrnpilcr [0 incllldl~ onc ill your
' program-:' Gi\"e all example.
4. C supports five basic types of data. Name the Ill .
J. Which (~I these vdriable nameS are ill\"alid in C~
a. count
h. 123Lount
•
c. $test
d. This_is_aJong_nanle
e. new-',-onJ
6. What is seanfe ) used for"
7. Write a program that inputs an integer from the kcvboard anJ
displays its square.
8 . How arC' comments entered into a C progranl'? Give an eX31nple
9. 1{o,," docs a function return a value to the routine that called it?
INTRODUCING C'S PROGRAM CONTROL STATEMENTS 41
21 BECOME FAMILIAR WITH THE if
...
if(expression) statement:
'" C
C uses < as its less than opemtor. For example, 10 < 11 is true . To
test for equality, C provides the = = operator. (There can be no space
between the two equal signs.) Therefore, 10 == 10 is true, but 10 ==
11 is not.
Of course, the expression inside the if may involve variables. for
example. the toll owing program tells whether an integer entered from
the keyboard is negative or non-negative .
#include <stdio.h>
int main(void)
(
int num;
return 0;
i
EXAMPLES
int main{void)
(
int answer;
· ;,
INTRODUCING C'S PROGRAM CONTROL STATEMENTS 43
2.' BECOME FAMIUAR WITH THE If
...
return 0;
inc main(voidl
float nurn;
int choice:
return 0;
)
EXERCISES
~ C'
2. Write a program that asks the user for an integer and then tells
the user if that number is even or odd. (Hint, use Cs modulus
operator' %.) .
DO THE.else
You can add an else statement to the if. When this is done, the if
statement looks like this:
ifCexpression) statement1:
else statement2;
If the expressi~n is true, then the target of the if will execute, and the
else portion will be skipped. However, if the expression is false, then
.'
the target of the if is bypassed, and the target of the else will execute.
Untl,'r no circumstances will both statements execute. Thus, the
additlon of the else-provides a two-way decision path.
EXAMPLES
I. YOll can ,lise the else to create more efficient code in some
cases. For example, here the else is used in place of a second if
in the program from the preceding section, which determines
whether a number is negative or non·negative.
~include <stdio.h>
int main(void)
{
int num;
return 0;
)
return 0;
)
EXERCISES
EA TE BL OCKS OF CODE
if[express;on) (
statement/:
statement2:
statement N:
)
else (
statement/;
statement2,~
statement N;
)
If the expression evaluates to true, then all the statements in the block
of code associated with the if will be executed. If the expression is false,
then all the statements in the else block will be executed. (Remember,
the else is optional and need not be present.) For example, this
fragment prints the message This is an example of a code block,
if the tlscr cntr:rs any positi\'f~ l111l11her. -'
INTRODUCING C'S PROGRAM CONTROL STATEMENTS 47
..,
23 CREATEBLOCKSOFCODE
if{num> 0) {
printf ("This is ");
printf ("an example of ");
printf("a code block.~);
)
EXAMPLES
•
I. This program is an improved version of the feet-la-meters,
meters-to-feet conversion program. Notice hO\v the use of code
blocks allows the program to prompt specifically for each unit.
#include <stdio.h>
•
int main (void)
{
float num;
int choice;
if(choice == 1) {
printf ("EntEtr number of feet: ");
48 W\CH YOURSELF
'" C
scanf(~%f·, &num);
printf(nMeters: %f", num / 3.28);
}
else {
printf(~Enter number of meters: .);
scanf(-%f", &num);
printf("Feet: %f~, num· 3.29);
return 0;
int main{void)
.
p=ir,tf ("vJhat is . 10. + :4? .. ) ;
scan: ("%d", &answer) i
} .
printf{"The ans\o..'er is 24 .... );
return ·0 ;
•
)
The for loop is one of C's three loop statements, It allows one or more
statements to be repeated. lfyoll have programmed in any other
computer language, sllch as BASIC or Pascal, you will be pleased to
learn that the for behaves mllch like its equivalent in other languages.
The for loop is considered by many C programmers to be it<; most
flexible loop. Although the for loop allows a large number of
variations, we will examine only its most common form in this section.
The for loop is used to repeat a statement or block of statements a
specified number of times. Its general form for repeating a single
statement is shown here,
• C
evaluates true, the loop repeats. If it is false, the loop stops, and
program execution picks up with the next line of code that follows the
loop. The conditional test is performed at the start or top of the loop
each time the loop is repeated. The increment portion of the for is
executed at the bottom of the loop. That is, the increment portion is
executed after the statement or block that forms its body has been
executed. The purpose of the increment portion is to increase (or
decrease) the loop-control value by a certain amount.
As a simple first example, this program uses a for loop to print the
numbers 1 through 10 on the screen.
#include <stdio.h>
int main(void)
(
int nurn;
1 2 3 4 5 6 7 8 9 10 lenninating
The program "'arks like this: First, the loop control variable Dum is
initialized to I. Next, the expression num < 11 i$ evaluated. Since it
is true, the for loop begins running. After the number is printed, Jnlm
is incremented by one and the conditional test is evaluated again. This
process continues u!,til num equal' 11. When this happens, the for
loop stops, and tenninating is displayed. Keep in mind that (he
initialization portion of the for loop is only executed once, when
the loop is first entered.
As stated earlier, the conditional test is performed at the stan of
each iteration. This means that if the test is false to begin with, the
loop will not execute even once. For example, this program only
displays terminating because num is initialized to 11, ca~ing the
. conditional test to fail.
1N11I00UCING C'S PROGRAM CONTROL STATtMENTS. &1
2.4 USE THEfor LOOP
...
.
int main{void)
{
int num;
printf ("terminating");
return 0;
J
int ma in( vo i d)
i nt num, sum , pr o d ;
sum = 0;
prod = 1;
for (num=l; num<6; num=num+l) (
sum = sum + num;
,
prod = prod * num;
)
printf (·product and sum.: %d %d- .. prod. sum);
return 0;
J
• C
#include <stdio.h>
return 0;
)
EXAMPLES
return 0:
)
Notice that this program has an if sta tCmenL& part of the for
block. Notice further that the target of elae is a block of code.
This is perfectly valid. In C. a code block may contain
IJI11IOI)UCING C'S _ CON1ROI. STATtMEHTS 53
2.4 USE THE for LOOP
"
int main(void)
(
int num, L is-prime;
return 0;
)
I
TfACH YOURSELF
C
Although not incorrect, you will almost never see a statement like
num = num + 1 in professionally written C programs because C
provides a special operator that increments a variable by one. The
iJ1C>"cmcl1t opacao,- is ++ (two pluses with no intervening space). Using
the increment operator, you can change this line of code:
i=i+l;
into this:
i++;
111erefore, the for shown earlier will normally be written like this:
for (num=O; n~~<some_value; num++J ...
can be rewritten as
count--,.
Aside from saving you a little typing effort, the reason you will want
to use the increment and decrement operators is that, for I1106t C
compilers, they will be faster than the equivalent assignment
statements. The reason for this difference is that the C compiler can
often avoid separate load-and-store machine-language instructions and
substitute a single increment or decrement Instruction in the
executable version of a program.
The increment and decrement operators do not need to follow the
variable; they can precede it. Although the effect on the variable is the
2..
INIROOUCING C'S _ CONTROL STA1IMUITS
same, the position of the operator does affect when the operation is
performed. To see how, examine this program:
#include <stdio . h>
int main(void)
(
int i. j;
i = 10,
j = i+.;
i = 10;
j = ... i;
.
&8 1IACII YOUR8(JS
C
return 0;
)
EXAMPLES
int mainlvoidl
{
int enswer. count;
return 0;
I
.-
{
~ ..... ,-
" int ii
i = 0;
i++;
printf (" %d " i) ; j' prints 1 ' j
i--·,
printf ("'d " i) ; j' prints 0 ' j
return 0,
J
-.- .., -
int main(vcid)
(
int a,~ bi
a = 1;
a = a + 1,
b = a,
b = b - 1,
return 0;
)
60 TEACH YOURSELF
'" C
return 0;
)
int main(void)
{
printfl"\xAO \xAl \xA2 \xA3");
return 0;
int main(void)
•
{
printf(Mone\ntwo\nthree\nfour-) ;
return 0;
)
INTROOUCING C'S PROGRAM CONTROL STATEMENTS 61
27 PROGRAM WTTH C'S RELAnONAL AND LOGICAL OPERA TORS
"
displays
one
two
three
four
on the screen.
EXERCISES
The C language contains a rich set of operators. In this section you will
learn about C's relational and logical operators. As you saw earlier, the
relational operators compare two values and return a true or false
result based upon that comparison. The logical operators connect
together truelfalse results. These operators are shown in Table 2-2
and Table 2-3.
62 TEACH YOURSELf
... C
Operator Action
The logical operators are used to support the basic logical operations
of AND, OR, and NOT according to this truth table. The table uses 1
for true and 0 for false.
p q p&&q pliq !p
o o o o 1
o 1 o 1 1
1 1 1 1 o
1 o o 1 o
•
The relational and logical operators are both lower in precedence
than the arithmetic operators. This means that an expression like
10 + count > a + 12
Operator Action
&& AND
II OR
NOT
The table below shows the relative precedence of the relational and
logical operators.
Highest
> >= < <=
== !=
&&
Lowest II
There is one Important fact to remember about the values produced .
by the relational and logical operators: the result is either 0 or I. Even
though C defines true as any nonzero value, the relational and logical
operators always produce the value 1 for true. Your programs may
make use of this fact.
You can use the relational and logical operators in both the if and
for statementS'. For example, the following statement reports when
both a and b are positive:
if(a>O && b>O) printf(~Both are positive.·);
, EXAMPLES
The reason is that in C, true is any nonzero value and false is zero.
Therefore, the preceding statement is generally written as this:
if(count} .. .
TEACH YOURSELF
C
int main(void)
int i, j;
/ * relational operations */
printf(ni < j td\n-, i < j);
printf(-i <= j %d\n", i <= j);
printf"("i == J %d\n", i == j);
printf("i > j %d\n", i > j);
printf("i >= j %d\n", i >= j);
/ * logical opera~ions */
printf("i && j %d\n", i && j);
printtl"i II j %d\n", i II jl;
printf ( ~!i !J %d %d\n", !i, !j);
return 0;
)
p q XOR
o o o
o 1 1
1 o 1
1 1 o
That is, the XOR operation produces a true result when one and
only one operand is true. The following function uses the &&
and II operators to construct an XOR operation. It compares the
values of its two arguments and returns the outcome of an XOR
operation.
int xor(int a, int b)
(
return (a II b) && ! (a && b);
)
int main(void)
(
int p. q;
return 0;
)
" C
(
.return la II b) && ! (a && b);
)
chapter objectives
69
•
70 TEACH YOURSELF
" C
NPUT CHARACTERS
Although numbers are important, your programs will also need to read
characters from the keyboard. In C you can do this in a variety of
ways. Unfortunately. this conceptually simple task is complicated by
MORE C PROGRAM CONTROL STATEMENTS 71
3.1 INPUT CHARACTERS
"
some baggage left over from the origins of C. However, let's begin with
the traditional way characters are read from the keyboard. Later you
will learn an alternative.
C defines a function called getchar( ), which returns a single
character typed on the keyboard. When called, the function waits for a
key to be pressed. Then getchar( ) echoes the keystroke to the screen
and returns the value of the key to the caller. The getchar( ) function
is defined by the ANSI C standard and requires the header file STDlO.H.
This program illustrates its use by reading a character and then telling
you what it received. (Remember, to display a character, use the %c
printf( ) format specifier.)
#include <stdio.h>
int main(void)
(
char chI
return 0;
)
• C
The reason that getchar( ) works the way it does is that the version
of UNIX for which C was developed line-buffered input. When C
compilers were created for other interactive environments, developers
had to decide ho'" to make getchar( ) behave. Many C compiler
developers have decided, for the sake of compatibility, to keep
getchar( ) line-buffered, even though there is no technical reason for
it. (In fact, the ANSI C standard states that getchar( ) need not be
line-buffered.) When getchar( ) is implemented in a line-buffered
fashion in a modern interactive environtnent, its use is severely
limited.
Because many compilers have implemented line-buffered versions
of getchar( ), most C compilers supply another function to perform
interactive console input. Although it is not defined by the ANSI C
standard, most compilers call this function getche( ). You use it just
like getchar( ), except that it will return its value immediately after a
key is pressed; it does not line-buffer input. for most compilers, this
function requires a header file called CONIO.H, but it might be called
something different in your compiler. Thus, if you want to achieve
interactive character input, you will usually need to use the getche( )
function rather than getchar( ).
Since all readers will have access to the getchar( ) function, it will
be used by most of the examples in this book that require character
input. However, some examples will use the getche( ) function. If
your compiler does not include this function, substitute getchar( ).
You should feel free to experiment with getche( ) on your own.
At the time of this writing, when using Microsoft's Visual C++ compiler,
getche() is not compatible with C's standard input funcyons, such as scanf().
Instead, you must u~e special console versions of these of these functions,
such as cscanf(). This and other non-standard liD functions are described in
Chapter 8. The examples in this book that use getche() work correctly with
Visual C++ because they avoid the use of the standard input functions.
than 'b', '2' is less than '3', and so on. You may compare characters just
like you compare numbers. For example.
ch = getchar() i
if(ch < 'f' printf("character is less than flo);
is a perfectly valid fragment that will display its message if the user
enters any character that comes before f.
EXAMPLES
l. This program reads a character and displays its ASCII code. This
illustrates an inlponant feature of C: You can use a character as
if it were a "little integer." The program also demonstrates the
use of the getche( ) function.
~include<conio.h>
#include <stdio.h>
int main(void)
char chi
return 0;
}
int main(void)
{
int a, bi
char chi
return 0;
}
)
MORE C PROGRAM CO~ROl STATEMENTS 75
3.2 NESTif STATEMENTS
'"
EXERCISES
I. Write a program that reads ten letters. After the letters have
been read, display the one that comes earliest in the alphabet.
(Hint: The one with the smallest value comes first.)
2. Write a program that displays the ASCII codes for the characters
A through Z and a through z. How do the codes differ between
the upper- and 10wer~ase characters?
EST if STATEMENTS
• C
EXAMPLES
if(expression) statement,
else
if(expression) statement,
else
if(expression) statement,
else statement,
The "xpressions arc c\'aluated from the top dow nward . As soon
as a true condition is found. the statement assori<lted with it is
executed , and the rest of the ladder is bypassed . If none of the
" xpressions arc true, the final else will be executed. That is, if
all other conditional tests fail, the last else statement is
performed . If the final else is not present, no action will take
place if all expressions are false .
Although the indentation of the general form of the if-else-if
ladder JUSt shown is technically correct, it can lead to overly
deep indentation. Because of this, the if-else-if ladder is
ge nerally written like this;
if(expression) statement,
else if(expression) statement,
else if(expression) statement;
else statement;
#include <stdio.h>
int main(void)
(
int a, b;
char chi
return 0;
J
int main(voidl
{
int a n swe r, count ;
78 TEACH YOURSELF
~
C
i:1t again;
/* nested if .. /
if (answer count+count) printf("Right!\n");
else
printf("Wrong, the answer is %d\n" ,
count+count) ;
)
)
return 0;
)
Here, the second if is nested within the outer ifs else block.
EXERCISES
EXAMPLES
int main{void)
{
int i;
char chi
ch = getche () ;
)
return 0;
)
Here, the condition that controls the loop has nothing to qo with
the loop-control variable. The reason ch is given an initial value
is to prevent it from accidentally containing a q when the
program begins.
2. As stated earlier, it is possible to leave an expression in a loop
empty. For example, this program asks the uSer for a value and
then counts down to zero from this number. Here, the
loop-control variable is initialized by the user outside the loop,
so the initialization portion of the loop is empty.
#include <stdio.h>
int main!voidl
{
int i;
return 0;
)
int main{void)
{
char chi
return 0 i .
}
int rnain{void)
int i;
'-
for(i=O; i<10; ) {
printf ("%d ". i);
i++:
82 TEACH YOURSELF
~
C
return 0;
)
.
1. Write a program that computes driving time when given the
distance and the average speed. Let the user specifY the
number of drive time computations he or she wants to perform.
2. To create time-delay loops, for loops with empty targets are
often used. Create a program that asks the user for a numher
and then iterates until zero is reached . Once the countdown is
done , sound the hell, but don't display anything on the screen.
3. Even if a for loop uses a loop·control variable , it need not he
incremented or decremented by a fixed amount . Instead, the
amount added or subtracted may vary . Write a program that
begins at 1 and runs to 1000. Have the program add the
loop·controI variable to itself inside the increment expression .
This is an easy way to produce the arithmetic progression 1 2 4
816, and so on .
while(expression) statement:
Of course, the target of while may also be a block of code. The while
loop works by repeating its target as long as the expression is true .
When it becomes false, the loop stops. The value of the expression is
checked at the top of the loop. This means that if the expression is
false to begin with, the loop will not execute even once.
MORE C _ CONTROl. STATEMENTS 83
14 UNDERSTAND CSwhi&e LOOP
"
EXAMPLES
int main(voidJ
{
char ch;
ch = getche();
return 0;
)
ch = getche ( ) ;
while(ch != '\r') {
84 TEACH YOURSELF
... C
printf("%c", ch+l ) i
cr getche ( ) i
return 0;
EXERCISES
SE THE do LOOP
do (
statements
) w hile(express;on);
If only one statement is being repeated, the curly braces are not
necessary. Most progrzllllmers include thenl. however, so that they can
easily recognize that the while that ends the do is part of a d o loop,
not the beginning of a while loop.
The do loop repeats the statement or statements while the
expression is true. It stops when the expression hecomes false. The do
loop is unique because-it ",ill always execute the code within the loop
at least once, since the (~:\pre~sion controlling the loop is tested at the
bottom of the loop.
MORE e PROGRAM CONTROL STATEMENTS 85
3.5 USE THE Ito LOOP
"
EXAMPLES
1. The fact that do will alwavs execute the body of its loop at least
once makes it perfect for ~hecking menu input. For example,
this version of the arithmetic program reprompts the user until
a valid response is entered.
~include <stdio.h>
int main(void)
(
int a, b;
char chi
ch = getchar ( ) ;
} while{ch!='A' && ch!='S' && Ch!='H' && ch!='D');
printf("\n") ;
return 0;
int main(void)
{
char Chi
do {
ch = getche ( ) ;
} while(ch!='q')i
return 0;
)
EXERCISES
•
1. Write a program that coilVerts gallons to liters. Using a do loop,
allow the user to repeat the conversion. (One gallon is
approximately 3.7854 liters.)
2. Write a program that displays the menu below and uses a do
loop to check for valid responses. (Your program does not need
to implement the actual functions shown in the menu.)
1. Enter addresses
2. Delete address
5. Quit
•
REA tE NESTED LOOPS
When the body of one loop contains another, the second is said to
be nested inside the first. Any of C's loops may be nested within any
other loop. The ANSI C standard specifies that loops may be nested
at least 15 levels deep. However, most compilers allow nesting 10
virtually any level. As a simple example of nested fors , this fragment
prints the numbers 1 to lOon the screen ten times.
for(i=O; i<10; i++) {
for(j=l; j<11; j++) printf("%d" j); j* nested loop */
printf ("'n ft
) ;
EXAMPLES
int main{voidl
(
int answer , count, chances, right;
right = 0;
88 .TEACH Y~ELF
". C
/* nested for */
for (chances=O; chances<3 && !right; chances++) (
printf("What is %d .... %d? ", count, count);
scanf{"%d", &answer);
if (answer == cQunt+cQuntl {
printf("Right!\n") ;
right = 1;
}
}
return 0;
2. This program uses three for loops to print the alphabet three
times, each time printing each letter twice:
#include <stdio.h>
return 0;
}
The statement
printf("%c". 'A'+j);
works because ASCII codes for the letters of the alphabet are
strictly ascending-each one is greater than the letter that
precedes it.
_C_~cotrINK.ITA-
.
11 USE_ roEXTTALOOP
..'"
,.
The break statement aJlows you to exit a loop from any point within
its budy. bypassing its normal termination expression. When the break
statement is encountered inside a loop, the loop is immediately
stopped, and program control resumes at the next statement follOWing
the loop. For example, this loop prints only the numbers 1 to 10:
.include <stdio.h>
return 0:
The break statement can be used with all three of C's loops.
You can have as many break statements within a loop as you
desire . However, since too many exit points from a loop tend to
destructure your code, it is generally best to use the break for special
purposes, not as your normal loop exit.
,
80 1IACII YOUMUf
y
c·
EXAMPLES
int main(void)
(
int i;
char ch;
.
'* display all numbers
for(i=l: i<10000; i++)
that are .nultiples of 6 '*/
(
if(!(i\6» (
print! (-'d, more? CY IN) ", i 1;
ch = getche ( J ;
if(ch=='N') break ; /. stop the loop + j
printf(-\n") :
return 0 i
}
7.. A break" will cause an exit from only the innermost loop. For
example, this program prints the numbers 0 to 5 five times:
Finclude <stdio.h>
int iTIain(voidl
(
int .i. j j
return 0;
)
iflch != 'Q') (
/ * do something */
.if~ch != 'Q') (
.' * do something else·/
)
etc. */
/ *
) whilelch != 'Q')
)
'* etc. ftj
82
...
EX'IICIIEB
I . On your own, write several short programs that use break to
exit a loop. Be sure to try all three loop statements.
.
2. Write a program that prints'a table showing the proper amount
of tip to leave. Start the table at $1 and stop at SIOO, using
increments of SI. Compute three tip percentages: \0%, 15% ,
and 20% . After each line, ask the user ifhe or she wants to
continue. If not, use break to stop the loop and end the program.
return 0;
)
EXAMPlE
int main(void)
{
int total, i, j;
total = 0;
do {
printf ("Enter next number (0 to stop): .. ) i
scanf{"'d", &i);
printf(-Enter number again: ");
scanf {"'d", &j);
if(i != j) {
printf("Mismatch\n") ;
continue;
)
total = total + i;
,.
94 TfACH YOURSElf
C
) while(i);
return 0;
)
case .constant2:
statement sequence
break;
case constant3;
statement sequence
break:
default
statement sequence
break:
I
The default statement sequence is performed if no matches are
found. The default is optional. If all matches fail and default is
absent, no action takes place. When a match is found, the statements
associated with that case are executed until break is encountered or,
in the case of default or the last case, the end of the switch is reached.
As a very simple example, this program recognizes the numbers 1,
2. 3, and 4 and prints the name of the one you enter. That is, if you
enter 2, the program displays two.
#include <stdio.h>
int mainlvoidl
(
int i;
scanf(-%d-, &i);
switch(i) (
case 1:
printf(ft one ") ;
break;
case 2:
printf (-two·);
break;
case 3:
printf{"three K );
break;
TEAQt YOU!lSW
86
... C
case 4: •
printf ("four");
break:
default: .
printf(-Unrecognized Number-);
}
return 0;
}
The switch statement differs from if in that 8witch can only test
for equality, whereas the if conditional expression can be of any type.
Also, switch will work with only int or char types. You cannot, for
example, use floating-point numbers.
The statement sequences associated with each case are not blocks;
they are not enclosed by curly braces.
The ANSI C standard states that at least 257 case statements will be
allowed. In practice, you should usually limit the amount of case
statements to a much smaller number for effiCiency reasons. Also. no
two case constants in the same switch can have identical values.
It is ~ossible to have a switch as part of the statement sequence of
an outer switch. This is called a nested suitcll. If the case constants of
the inner and outer switch contain common values, no conflicts will
arise. For example, the following code fragment is petfectly acceptable:
switch(a) (
case 1:
switch(b)" {
case 0: printf(-b is false~);
break;
case 1: printfC-b is true-);
}
break ;
case 2:
EXAMPLES
int main(void)
(
int a, bi
char chi
5witch(ch) (
case 'A': .printf("'d", a+b);
break;
case '5': printf("'d", a-b);
break.;
case 'M': printf ("%d" a-b) ;
I
break;
case 'D': if(b!=O) pr'n1;f("'''", alb);
)
return 0;
)
9a TEACH YOURSElf'
y
C
int main(void)
(
char chi
do (
printf("\nEnter a character. q t.o quit: ");
ch = getche () ;
printf ("'n"';
switch (ch) {
case 'a':
printf ("Now is .. );
case 'b':
printfl"the time .);
case 'c':
printf("for all good men");
. break;
case 'd':
printf("The summer .);
case 'e':
printf("soldier .);
)
} whilelch != 'q');
return 0;
)
If the user types a, the entire phrase Now is the time fc:.r all
good men is displayed. Typing b displays the rime for all
_ C PROGRAM CONTROl STATlM£NTS 99
~
3.9 SELECT AMONG ALTERNA nVES WITH THE switch STATEMENT
good men. As you can see, once execution begins inside a case,
it continues until a break statement or the end of the switch is
encountered.
3. The statement sequence associated with a case may be empty.
This allows two or more cases to share a common statenlent
sequence without duplication of code. For example, here is a
program that categorizes letters into vowels and consonants:
#include <stdio.h>
#include <conio.h>
int rnain(void)
{
char Chi
5wicch(ch) (
case 'a' :
case . e':
case . i' :
case '0' :
case 'u' :
case 'y' :
printf(" is a vowel\n");
break;
default:
printf(" is a consonant");
)
return 0;
)
scanfl"U", &f);
.,
100 TEACH YOURSElf
switch(f) 1.
case 10.05:
About the only good use for goto is to jump out of a deeply nested
rOll tine when a catastrophic error occurs.
MORE C PROGRAM CONTROL STATlMEII'IS 101
3.10 UNDERSTAND THEgoto STATEMENT
"
EXAMPLE
int main(void)
(
int i;
i = 1;
again:
printf("%d" i);
i++;
if(i<10) gato again:
return 0;
• C
ch = ' x' ;
for ( ; ch ! = ' , ; ) ch = getche () ;
break;
case 3: printf ("quarter M
) ;
} •
alldone
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
_C_COIIIROLsrll_ 103
•
l. Using a switch statement, write a program that reads characters
from the keyboard and watches for tabs, newlines, and
backspaces. When one ia received, diaplay what it is in words.
For example, wilen the uaer preues the TAB key, print tab.
Have the _ enter a q to stop the program.
2. While tbia program ia not incorrect, show how it would look if
written by an experienced C programmer.
'include <stdio.h>
return 0;
1
,
4
A Closer Look at
Data Types, Variables,
and Expressions
•
105
~
•
4
A Closer Look at
Data Types, Variables,
and Expressions
•
chapIer objeLtl_
c-
4.6 Understand type conversions in assignments
105
'"
-IH IS chapter more fully examines several concepti presented
in Chapter 1. It covers COs data-type modifiers, global and
local variables, and constants. It also dlscuaaes how C handles
various type conversions.
( " ~.
Before proceeding, you should be able to answer these questions
and perfonn these exercises:
1. Using C's three loop statements, show three ways to write a loop
that counts from 1 to 10.
2. Convert this series of ifs into an equivalent switch.
if(ch=='L') load() ,
else if(ch=='S') save(),
else if(ch=='E') enter(),
else if(ch=='O') display()
else if(ch=='Q') quit(),
3. Write a program that inputs characters until the user strikes the
ENTER key.
long
short
signed
unsigned
The type modifier precedes the type name. For example, this declares
a long integer:
long int i;
0111111111111111
If this is a signed value and the high-order bit is set to 1, the number
would then be interpreted as -1 (assuming two's complement format).
However, if this is an unsigned value, then when the high-order bit
is set to I, the number becomes 65,535.
Table 4-1 shows all allowed combinations of the basic types and
the type modifiers. The table also shows the most common size and
minimum range for each type as specified by the ANSI C standard .
It is important to understand that the ranges shown In Table 4-1 are
just the minimums that all compilers must provide. The compiler is
free to exceed them, and most compilers do for at least some data
types. As mentioned, an int in a 32-bit environment will usually have
a range larger than the minimum . Also, in environme!1ts that use
A CLOSER LOOK AT DATA TYPES. VARIABLES. AND EXPRESSIONS 109
.:i. I USEC'SDATA-TYPEMODIFIERS •
two's complement arithmetic (which is the case for the vast majority
of computers), the lower bound for signed characters and integers is
one greater than the minimums shown. For instance, in most
environments, a signed char has a range of -128 to 127 and a short
int is typically -32,768 to 32,767. You will need to check your
compiler's documentation for the specific ranges of the data types
as they apply to your compiler.
C allows a shorthand notation for declaring unsigned. short, or
long integers. You may simply use the word unsigned, short, or l~ng
without the into The int is implied. For example,
unsigned count;
unsigned int num;
magnitudes cif the values eaclt may hold. Therefore, as m'e ntioned
earlier, a signed char variable can also be used as a 'small' integer
when the situation does not require larger numbers.
When outputting integers modified by short, long, or unai~
using printf( ), you cannot simply use the %d specifier. The re<\SOn is
that printf( ) needs to know precisely what type of data it is
receiving. To_use printf( ) to output a short, use %hd. To output a
long, use %ld. When outputting an unsigned value, use %u. To ·
output an unsigned long int, use %lu. Also, to output a long double
use %Lf.
The seanf( ) function operates in a fashion similar to printf( ).
When reading a short int using scanf( ), use 'l6hd. When reading a
long int, use %ld. To read an unsigned long int, use 'l6lu. To read a
double, use %If. To read a long double, use %Lf.
EXAMPLES
I. This program shows how to input and output short, IOllg, and
unsigned values.
'include <stdio.h>
return 0;
)
2. T;) understand the difference bttween the way that signed and
unsigned integers are interpreted by C, run the following short
program. (This program assumes that short integers are J 6 bits wide.)
Aca.IlIiUlOlAfIlAfAftIIII,W...... AllliA.IIIUU. " ,
, ' ., IotIfCSD4TA'nI'f__ •
'include <stdto,h_
iftt main(voidl
t
short int i, /" • • igned abort integer "'
unsigned ahort int ", '" an unalgned abort integer *'
u = 33000;
i = u;
printf("hd 'hu', i, ul/
return 0,
}
int aain(voidl
(
int i;
char j;
i = 0;
for(j~l: j<lOl; j++) i • j + i;
return 0;
l
112 TEACH YOURSW
" c
:) t :1 . ' ••
int main(void)
(
f1 () ;
return 0;
)
•
A CI 0IlR LOOK AT DATA TYPES, VARIABLES, AND EXPRESSIONII 1'" :-:
4.2 LEARN WHERE VARJABL£S ARE DECLARED
v
void fl (void)
(
int count;
void f2 (void)
(
int count;
This program prints the numbers 0 through 9 on the screen ten times.
The fact that both functions use a variable called count has no effect
upon the operation of the code, Therefore, what happens to count
inside f2() has no effect on count in fI().
The C language contains the keyword auto, which can be used to
declare local variables. However, since all local variables are, by
det:,ult, assumed to be auto, it is virtually never used. Hence, you will
not see it in anv of the examples in this book
Withm a function, local variables can be deciared at the start of any
block They do not need to be declared only at the start of the block
that defines the function. For example, the following program is
perfectly valid:
#incl~je <stdio.h>
j ::: i * 10;
printf ("%d", j);
return 0;
114 TEACH VOURSElf
c
int main(void)
(
printf{~This program wo~'t compile.- ) ;
int ii / * this should come f i rst *'
i = 10:
return 0;
)
When a function is called, its local variables are created, and upon
its return, they are destroyed . This means that local variable s cannot
retain their values between calls.
The formal parameters to a function are also local variables. Even
though these variables perform the special task of receIving the v~lue
of the arguments passed to the function , they can be used like any
other local variable' within that function .
Unlike local variables, global variables are known throughout the
entire program and may be used by ony piece of code in the program .
Also, they will hold their value during the entire execution of the
program. Global variables are created by declaring them outside any
function. For example , consIder this program:
.include <stdio.h>
voj.d f1 (void) ;
fl ( I ;
return 0;
)
void f1 (void)
(
int i;
Here, both main() and fI() use the global variable m ax. The maine )
function sets the value of max to 10, and fI ( ) uses this value to
control its for loop.
EXAMPLES
void f1 (void);
int main(void)
•
count = 10;
fl () ;
printf(."count in main(): %d\n", count);
return 0;
)
void fl(voidl
(
int count; /* local count */
count = 100;
printf(-count in fl() %d\n". count);
116 TfACH YOURSELF
•
c
count in f1 () : 100
count in main() : 10
int m t e;
int main(void)
(
m :;: 2;
e = 3;
return 0;
)
(
int temp, temp2;
temp :; 1;
ternp2 = e;
fore ; temp2> 0; temp2--) temp:; temp· m;
return temp;
)
int mai:'1(voidl
int m, e;
m = 2·,
e = 3;
return 0;
)
temp = 1:
fort e> 0; e--) temp = temp * m;
return temp;
)
11 • TfACH YOURSElf
. " C
int main(void)
int i;
•
for(i=O; i<10; i'++) printf("%d series(») ;
return 0;
)
/ * This is incorrect. *I
int series(void)
int total:
EXERCISES
The sign is optional. Although the general form is shown with spaces
between the component parts for clarity, there may be no spaces
between the parts in an actual number. For example, the following
defines the value 1234.56 using >'Cientific notation:
120 TEACH YOUAIIlU'
c
123.456El
ch = 'A ' ;
ch = 65;
When y{)U enter numeric constants into your program. the compiler ·
must decide what type of constant they are. for example, is J 000 an
int, an unsigned, or a short? The rcason ,. .'e haven't worried about
this earlier is that C automatically converts the type of the right side of
an assignment statement to that of the variable on the left. (We will
examine this process more fully later in this chapter.) So, for many
situations it doesn't matter what the compiler thinks 1000 is. However,
this can be important when you use a constant as an argument to a
function, such'ils in a call to printf( ).
By default, the C compiler fits a numeric constant into the smallest
compatible data type that will hold it. Assuming 16-bit integers, 10 is
an int by default and 10(1003 is a long. Even though the value 10 could
be fit into a char, the compiler will not do this because it means
crossing type boundaries. The only exceptions to the small<:st-type
rule are floating-point constants, which are assumed to be doubles.
For virtually all programs you will write as a beginner, the compiler
defaults are perfectly adequate. However, as you will see later in this
book, there will come a point when you will need to specify precisely
the type of constant you want.
In cases where the assumption that C makes about a numeric
constant is not what you want, C allows you to specify the exact type
II CLD5(R LOOK AT !lATA TYPES, VARIABLES, AND EXPRESSIONS 121
~
4.3 TAKE A CLOSER LODKAT CONSTANTS
int m.a,in(void)
(
return 0 i
)
,
EXAMPLES
2. To see why you may need to explicitly tell the compiler what
type of constant you are using, try this program. For most
compilers, it will not produce the desired output. (Ifit does
work, it is only by chance. )
#include <stdio.h>
int main(void)
( .
printf("%f", 23091;
return 0;
)
•
A CLOSER LOOK AT DATA TYPES, VARJABLES, AND EXPRESSIONS 123
4.4 INfTlALIZE VARIABLES
EXERCISES
1. How do you tell the C compiler that a floating-point constant
should be represented as a float instead of a double?
2. Write a program that reads anq writes a long int value.
3. Write a program that outputs I like C using three
separate strings.
"
EXAMPLES
return 0;
)
void f (void) ;
int main(void)
(
f{);
•
t{);
t () ;
return 0;
)
void f (void)
{
int i = 10;
A CIIISEII LOOK AT DATA TYPES, VAlUABLES, AND EXPRESSIONS 125
...4 INmALiZE VARIABLES
...
return 0;
}
int myfunc(int i)
(
return' i/2;
)
Unlike many other computer languages, C lets you mix different types
of data together in one expression. For example, this is perfectly valid
C code:
char chi
int i;
float fi
double outcome;
ch = ' 0';
i = 10;
f : 10.2;
outcome = ch * i / f;
There is one additional special case: If one operand is long and the
other is unsigned int, and if the value of the unsigned int cannot be
represented by a long, both operands are converted to unsigned long.
Once these conversion rules have been applied, each pair of
operands will be of the same type and the result of each operation will
be the same as the type of bot" operands.
, EXAMPLES
int main(void)
(
int i;
float f:
i = 10;
f = 23.25;
printf(~%f~, i*f);
return 0;
128 TfACHYOURSW
c
int main(void)
(
~ short int i;
i = -10:
printfC"'d", i);
return 0;
)
DEPC~.
int main(void)
char chi
int i;
i =
1000;
ch = i;
return 0;
The reason for this is that only the low·order eight bits of i are
copied into ch .. Since this sort of assignment type conversion is not an
error in C, you will receive no error message. Remember, one reason
C was created was to replace assembly language, so it must allow all
sorts of type conversions. For example, in some instances you may
only want the low-order eight bits of i, and this sort of assignment is an
easy way to obtain them.
When there is an integer-to-character or a longer-integer to
shorter-integer type conversion across an assignment, the ba'sic rule is
that the appropriate number of high-order bits will be removed. For
example, in many environments, this means 8 bits will be lost when
going from an int to a char, and 16 bits will be lost when going from a
long to an into
When convel1ing from a long double to a double or from a double
to a float, precision is lost. When converting from a floating-point
130 TEACH YOURSELF
... C
value to an integer value, the fractional part is lost, and if the number
is too large to fit in the target type, a garbage value will result.
Remember two important points: First, the conversion of an int to a
float or a float to double, and so on, will not add any precision or
accuracy. These kinds of conversions will only drange the form in
which the value is represented. Second, some C compilers will always
treat a char variable as an unsigned value. Others will treat it as a
signed value. Thus, what will happen when a character variable holds
a value greater than 127 is implementation-dependent. If this is
important in a program that you write, it is best to declare the variable
explicitly as either signed or unsigned.
EXAMPLES
int main(void)
(
int i;
float f;
f = 1234.0098;
i = f;· / * convert to int ,.. I
printf("%f %d", f. i);
return 0;
)
int main(void)
(
short int si;
long int Ii:
A CLOSER LOOK AT DATA TVPfS, VARIABLES, AND EXPRESSIONS
4.6 UNDERSTAND TYPE CO/NfRSIONS IN ASSIGNMENTS
.,
131
U = 100000;
si = Ii; j* convert to short int */
printf("%hd", 5i);
return 0;
)
Since the largest value that a short integer can hold is 32,767, it
cannot hold 100,000. What the compiler does, however, is copy
the lower-order J 6 bits of Ii into si. This produces the
meaningless value of -31072 on the screen.
EXERCISES
int main(voidl
(
int i;
long double Id;
1d = 10.0;
i = Id;
printf'("%d", il;
)
int main(void)
(
float f;
f = 10 I 3,
printf("%f", f);
return 0;
)
132 TEACH YOURSElF
'" C
(type) value
f = 100.2;
;--- print f as an integer */
printf(~%d". (int) f);
EXAMPLES
#include <stdio.h>
#include <math.h>
int main(void)
{
double i ;
return 0;
}
UERCISES
I. Write a program that uses fo r to print the numbers 1 to 10 b"
tenths. Use a floating-point variable to control the loop.
However, use a type cast so that the conditional expression is
evaluated as an integer expression jn the interest of speed.
2. Since a floating point value cannot be used with the % operator,
how can you fix this statement?
x = 123 . 23 % 3; / * fix this statement * /
.,
134 TEACH YOURSELF
This section checks how well you have ilHegrated the material in
this chapter with that from earlier chapters.
dI.........&.II_
137
...
138 TEACH YOURSELF •
c
case 4:
case 5: a = 5:
)
type va,_name[s;ze);
·<there type is a valid C data type, var_name is the name of the array,
~nd size specifies the number of elements in the arraY) For example, to
declare an integer array with 20 elements called myarray, use this
staren1ent.
int myarray[201;
return 0 i
)
int main(voidl
{
int a1[10], a2[10];
int i;
return 0;
#include <stdio.h>
#include <conio.h>
int main(void)
(
char mess [80J;
int i;
return 0;
/ * read in numbers */
printfC"How many numbers? ");
scanf("%d", &count);
for(a=O; a<count; a++) scanf("%d", &item[a});
144 TEACH YOURSELF
'" C
return 0;
)
EXERCISES
). What is wrong with this program fragment?
#include <stdio.h>
int main(void)
int i: count[lO};
2. Write a program that reads ten numbers entered by the user and
reports if any of them match.
3. Change the sorting program shown in the examples so that it
sorts data of type float.
Exploring Armys and Strings 145
5.2 USE STRINGS
T
E STRINGS
int main(void)
{
char str[80] i
int i;
return 0;
Notice how the program uses the fact that a null is false to control the
loop that outputs the string.)
There is a potential problem with gets( ) that you need to be aware
of. The gets( ) function performs no bounds checking, so it is possible
for the user to enter more characters than the array receiving them
can hold. For example, if you call gcts( ) with an array that is 20
characters long, there is no mechanism to stop you from entering
146 TEACH YOURSELF
'" C
int main{void)
{
char str [80] ;
return 0;
)
strcpy(to, from);
Exploring _ and Strings 147
5.2 USE STRlNGS
•
It copies the contents of from to to. The contents of from are
unchanged. For example, this fragment copies the string "hello" into
str and displays it on the screen:
char str[80);
streatCto, from);
It adds the contents of from to the contents of to. It performs no
bounds checking-. so you must make sure that to is large enough to
hold its current contents plus what it will be receiving. This fragment
displays hello there.
char str[BO];
strcpy{str, "hello"};
strcat(str. " there");
printf(str);
strempes 1, s2);
It relurns zero if the strings are the same. It returns less than zero if 51
is less than 52 and greater than zero if 51 is greater than s2. The strings
are compared lexicographically; that is, in dictionary order. Therefore,
a string is less than another when it would appear before the other in a
dictionary. A string is greater than another when it would appear after
the other. The comparison is not based upon the length of the string.
Also, the comparison is case-sensitive, lowercase characters being
greater than uppercase. This fragment prints 0, because the strings are
the same:
printf("%d", strcmp("one", "one"»;
.,
148 TEACH YOURSELF
strlen(str);
The strlen( ) function does not count the null terminator. This means
that ifstrlen() is called using the string 'test', it will return 4.
EXAMPLES
1. This program requests input of two strings, then demonstrates
the four string functions with them.
#include <str1ng.h~
#include <stdio.h~
inc main(void)
return 0:
)
int main(void)
for ( ; ; ) (
printf(MOperation? ") i
gets (command);
'" C
return 0:
I
EXERCISES
#include <string.h>
#include <stdio.h>
int main(void)
{
char str[5];
return 0:
}
As you can see, to add a dimension, you simply specify its size inside
square brackets.
A two-dimensional array is essentially an array of one-dimensional
arrays and is most easily thought of in a row, column format. for
exampl~(given a 4x5 integer array called two_d, you can think of it
looking like that shown in figure 5-1. Assuming this conceptual view,
a two-dimensional array is accessed a row at a time, from left to right.
This means that the rightmost index will change most quickly when
the array is accessed sequentially from the lowest to highest memory
address)
152 TEACH YOURSElF
y
C
fiGURE 5-2
A conceptual view 0 I 2 3 4
ofa 4x5
two-dimensional 0
array
I
y
2
return 0;
)
LTO create arrays of three dimensions or greater, simply add the size
of the additional dimension)For example, the following statement
creates a 10x12x8 three-dimensional array.
float values[10) [12) [B);
EXAMPLE
int main(void)
[
int bball(4115);
int i. j:
j *display results . j
for ( i=O; i<4: i++J
for(j=O; j<S; j++) (
printf("Quarter %d. player %d, i+l. j+l ) i
return 0;
)
EXERCISES
INITIALIZE ARRAYS
Like other types of variables, you can give the elements of arrays
initial values. This is accomplished by specifying a list of values the
array elements will have.(The general form of array initialization for
one-dimensional arrays is shmvn here:
This means that i[O) will have the value 1 and i[4) will have the
value 25 .
./ (You can initialize character arrays two ways. First, if the array is not
holding a null-terminated string, you simply specify each character
using a comma-separated list. For example, this initializes a with the
letters 'A', 'B', and 'C'.
If the character array is going to hold a string, you can initialize the
array using a quoted string, as shown here:
char narne[Sl = HHerb~;
Notice that no curly braces surround the string. They are not used in
this form of initialization. Because strings in C must end with a null,
you must make sure that the array you declare is long enough to
include the null. This is why name is 5 characters long, even though
'Herb' is only 4. When a string constant is used, the compiler
automatically supplies the null terminator.)
..,... (Multidimensional arrays are initialized in the same way as
one-dimensional arrays. For example, here the array sqr is initialized
with the values 1 through 9, using row order:
int sqr[3J [3J = (
1, 2, 3,
4, 5, 6,
7, 8, 9
J;
This initialization causes sqr[O) [0) to have the value 1, sqr[O) [1) to
contain 2, sqr[O) [2) to hold 3, and so forth.)
(If you are initializing a one-dimensional array, you need not specify
the size of the array-simply put nothing inside the square brackets. If
you don't specify the size, the compiler counts the number of
initializers and uses that value as the size of the array)For example,
int pwr[] = {1, 2, 4, 8, 16, 32, 64, 128J;
'" C
•
will be automatically adjusted when you change the number of its
initializers. It also helps avoid counting errors on long lists, which is
especially important when initializing strings. For example, here an
unsized array is used to hold a prompting message.
char prompt ~~ter y~)Ur name: •i
If, at a later date, you wanted to change the prompt to "Enter your last
name:", you would not have to count the characters and then change
the array size. The size of prompt would automatically be adjusted.
/(Unsized array initializations are not restricted to one-dimensional
arrays. However, for multidimensional arrays you must specifY all but
the leftmost dimension to allow C to index the array properly. In this
way you may build tables of varying lengths with the compiler
allocating enough storage for them automatically. For example, the
declaration of sqr as an unsized array is shown here:
int sqr[J [3J = (
1, 2, 3.
4. 5. 6,
7: B. 9
J;
The advantage to this declaration over the sized version is that tables
may be lengthened or shortened without changing the array
dimensions)
EXAMPLES
2, 28,
3, 19,
4, 8,
5, 15
) ;
int server;
int i;
return . 0;
)
int main(void)
{
char str(BO) = -I like C·;
return 0;
)
158 TEACH YOURSELF
.., C
EXERCISES
int ma~n(void)
1, 1, 1,
2,4,8,
3,9,27,
4,16,64,
Next, prompt the user for a cube, look up this value in the table,
and report the cube's root and the root's square. Use an unsized
array so that the table size may be easily changed
Exploring An'eys and Strings
5.5 BUILD ARRAYS OF STRINGS
,.
159
By the same token, to output the first string, use this printf( )
statement:
printf (names! 0 J ) ;)
To access a specific string in this situation, you must specify the two
left-most indexes. For example, to access the second string in the third
list, specify animals[2)[l].)
EXAMPLES
1. This program lets you enter ten strings, then lets you display
them, one at a time, in any order you choose. To stop the
program, enter a negative number.
#include <stdio.h>
int main{void)
160 TEACH YOURSELF
'" C
(
char text [10J [80J;
int i;
do
printfC"Enter number of string (1-10) : ");
scanf("%d", &i);
1--; j* adjust value to match array index * 1
i£(i>=O && i<10) printf("%s \ n", textli);
} while (i>=O);
return 0;
}
2. You can initialize a string table as you would any other type of
array. For example. the following program uses an initialized
string table to translate between German and English. Notice
that curly braces are needed to surround the list. The only time
they are not needed is when a single string is being initialized .
/* English-to-German Translator. */
_include <stdio.h>
#include <string.h>
"house", "Haus".
"to·, ·zu·,
.... . . .
};
int main(void)
{
char engllsh[80] ;
Exploring Arrays and Strings 161
'f'
5.5 BUlW ARRA YS OF STRINGS
int i;
return 0;
)
) ;
int if j;
return 0:
)
EXERCISE
1. Write a program that creates a string table containing the
English words for the numbers 0 through 9. Using this table,
allow the user to enter a digit (as a character) and then have
your program display the word equivalent. (Hint: to obtain an
index into the table, subtract '0' from the character entered.)
. "
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
I. Write a program that inputs strings from the user. If the string is
less than 80 characters long, pad it with periods. Print out the
string to verify that you have correctly lengthened the string.
2. Write a program that inputs a string and then encodes it by
taking the characters from each end, starting with the left side
and alternating, stopping when the middle of the string has been
reached. For example, the string "Hi there" would be "Heir eth".
3. Write a program that counts the number of spaces, commas, and
periods in a string. Usey switch to categorize the characters."
4. What is wrong with this fragment?
char str[BO);
str = getchar();
--
, chapter objectives
c'
165
y
166 TEACH YOURSELF
• C
Review
Skills Check
type 'var-name;
Here, type is the base rype of the pointer. The base type specifies the
type of the object that the pointer can point to)Notice that the variable
name is preceded by an asterisk. This tells the computer that a pointer
variable is being created. For example, the following statem ent creates
a pointer·to an inreger:
int *p;
int main(void)
int *p, q;
return 0;
)
" C
int rnain{void)
(
int *p, q;
return 0;
l)
In the two simple example programs just shown, there is no reason to
use a pointer. However, as you learn more about C, you will understand
why pointers are important. Pointers are used to support linked lists
and binary trees, for example.
(The base type of a pointer is very important. Although C allows any
type of pointer to point anywhere in memory, it is the base type that
determines how the object pointed to will be treated. To understand
the importance of this, consider the follOwing fragment:
USING POINT£RS 169
."
6.1 UNDERSTAND POINTER BASICS
int q;
d o uble . . fp;
fp = &q;
the compiler will still let you use a null pointer, usually with
disastrous results)
Examples
Locatio" Contents
100 102
I-------j --"I p points to q
102 unknown .-J
Location Contents
100 102
1-----..., --"I p points to q
102 1000 .-J
2. To illustrate why you must make sure that the base type of a
pointer is the same as the object it points to, try this incor~ect
but benign program. (Some compilers may generate a warning
message when you compile it, but none will issue an actual
error message and stop compilation.)
/ * This program is wrong. but harmless. *1
.include <stdio.h>
temp = 1234.34;
p = &temp; 1 * attempt to assign q a value using * 1
q = ·Pi /* indirection through an integer pointer'" /
return OJ
)
EXERCISES
1. What is a pointer?
2. What are the pointer operators and what are their effects?
172 TEACH YOURSELF
y
C
EXPRESSIONS
executes, p will have the value 202, assuming integers are two bytes
long. By the same token, ifp had been a float pointer (assuming
4-byte floats), then the resultant value contained in ·p would have
been 204 .
The only pointer arithmetic that appears as 'normal' occurs when
char pointers are used. Because characters are one byte long, an
increment increases the pointer's value by one, and a decre!TIent
decreases its value by one.
You may add or subtract any integer quantity to or from a pointer.
For example, the following is a valid fragment:
6.2
USING POINTERS
int *p
p =p + 200;
This statement causes p to point to the 200th integer past the one to
which p was previously pointing.
Aside from addition and subtraction of an integer, you may not
perform any other type of arithmetic operations-you may not
multiply, divide, or take the modulus of a pointer. However, you may
subtract one pointer from another in order to find the number of
elements separating them)
(It is possible to apply the increment and decrement operators to
either the pointer itself or the object to which it points)However, you
must be careful when attempting to modify the object pointed to by a
pointer. For example, assume that p points to an integer that contains
the value 1. What do you think the following statement will do:
- *p++-;
Contrary to what you might think,~his statement first increments p
and then obtains the value at the new location. To increment what is
pointed to by a pointer, you must usc a form like this:
(*p) ++;)
The parentheses cause the value pointed to by p to be incremented .
v (You may cOlnpare two pointers using the relational operators.
However, pointer comparisons make sense only if the pointers relate
to each other-if they both point to the same object, for example.
(Soon you will see an example of pointer comparisons.) You may also
compare a pointer to zero to see if it is a null pointer.)
At this point you might be wondering what use there is for pointer
arithmetic. You will shortly see, however, that it is one of the most
valuable components of the C language.
174 TEACH YOURSELF
'" C
EXAMPLES
cp = &ch;
ip = &i;
fp = &f ;
dp = &d ;
/ * print the current values * /
printf {"%p %p %p %p \ n", cp, ip, fp. dp);
return 0;
)
int main(voidl
{
int .p, q;
p = &q;
q =
1;
printf("%p pl;
return 0;
)
After this program has executed, q still has the value 1, but p
has been incremented. However, if the program is written
like this:
.include <stdio.h>
int main(void)
{
int ·P. q;
p = &q;
q =
1;
printf("%p pl;
return 0;
)
EXAMPLES
cp = &ch;
ip = &L
fp = &f ;
dp = &d ;
/ * n ow increment them by o n e */
cp+"' ;
ip++;
fp++ ; ,
dp++ ;
return 0 ;
)
int main(void)
{
int *p, qi
p = &g;
g = 1;
printf("%p ~ pI ;
return 0;
I
After this program has executed, q still has the value I, but p
has been incremented. However, if the program is written
like this:
.include <stdio.h>
int main{void )
{
int *p. q;
p = &g;
q = 1;
printf("%p p);
return 0;
)
EXERCISES
p = &i;
p =P .. 8;
#include <stdio.h>
int main(void)
{
int a[lOJ = {lO, 20, 30, 40, 50, 60, 70, 80, 90, 100J;
int ""p;
return 0;
J
each row is five elements long. Therefore, to access balance [3] [1]
using a pointer you must use a fragment like this:
float .p;
p = ( float *) balance:
*(p + (3*5) + 1)
To reach the desired element, you must multiply the row number by
the number of elements in the row and then add the number of the
element within the row. Generally, with multidimensional arrays it is
easier to use array indexing rather than pointer arithmetic.
178 TIACII YOURSELF
., C
int rnain(void)
(
char str[] = ·Pointers are fun-;
char "Pi
int i;
p = str:
return 0;
}
Keep one point firmly in mind: you should index a pointer only when
that pointer pOints to an array) While the following fragment is
syntactIcally correct, It IS wrong; If you tned to execute it, you would
probably crash your computer.
char ·P. Chi
int i;
p = &ch;
for(i=O; i<lO; i++) plil = 'A'+i; /* wrong */
-(str+3) = 'c';
printf{-%c·, *(str+3»;
return 0,
)
EXAMPLES
•
1. Two ofC's library functions, toupper() andtolower(), are
cal1ed using a character argument. In the case of toupper( ),
if the character is a lowercase letter, the uppercase eqUivalent
is returned; otherwise the character is returned unchanged.
For tolower( ), if the character is an uppercase letter, the
lowercase equivalent is returned; otherwise the character is
returned unchanged. These functions use the header file
CTYPE.H. The fol1owing program requests a string from the
180 TEACH YOURSElF
'" C
user and then prints the string, first in uppercase letters and
then in lowercase. This version uses array indexing to access
the characters in the string so they can be converted into the
appropriate case.
#include <ctype.h>
#include <stdio.h>
int main{void)
(
char str[BO):
int i;
return 0:
)
int main(void)
gets(str);
p = str;
while(*p) (
*p = toupper (.p) ;
p++ ;
)
p = str; /* reset p */
while(*p) (
*p = tolower (.p) i
p++;
)
return 0;
)
#include <stdio.h>
#include <string.h>
int main{void)
(
char strl[] = ~Pointers are fun to use~;
char str2(80], *pl. ·p2;
p2 = str2;
while(pl >= strl)
·p2++ = ·pl--;
return 0;
}
EXERCISES
count = count + 2;
p = temp;
3. Write a program that inputs a string . Have the program look for
the first space. If it finds one. print the remainder of the string.
printf (p) ;
return 0;
) )
184 TtACH YOURSEl.f
~ C
it stores the string in the program's string table and assigns to p the
address of the string in the table. Therefore, when p is used in the
printf( ) statement, one two three is displayed on the screen.
(This program can be written more efficiently, as shown here:
#include <stdio.h>
printf (p) ;
return 0;
)
int main(voidl
(
char .p = ·stop·:
char str[BO);
do (
printf{-Enter a string: W);
gets(str) ;
} while (strcmp(p, str));
USING POINTIRS 135
y
6.4 uSE POINTERS TO STRING CQNSTAfv7S
return 0;
)
printf(InsDisk) ;
printf(InsDiskl;
EXERCISE
'" C
( Pointers may be arrayed like any other data type. for example, the
following statement declares an integer pointer army that has 20
elements:
,
int "'pa[20];)
EXAMPlES
"Out of range".
"Printer not turned on",
"Paper out",
"Disk full",
"Disk write error"
) ;
char 'p11121 =(
~Red Delicious", "red",
MGolden Delicious·, ~yellow·, -,
M"Hnesap~, ~red",
int i:
char apple (80 J;
return 0;
EXERCISE
I. In this exercise, you will create an 'executive decision aid.' This
is a program that answers yes, no, or maybe to a question
entered at the keyboard. To create this progral11 use an array
of character pointers and initialize them to point to these three
w·ings. 'Yes", "No', and 'Maybe. Rephrase the qlleStlOn'. Next,
input thc user's question and find the length of the string. Next,
use this formula to cmnpute an index into the pointer array:
index = length % 3
Mulflple
ind;rectlon
T
EXAMPLES
fp = &va1;
rnfp = &fp;
"""'mfp = 123.903;
printf("%f %f-, val. **mfp);
return 0;
)
•
TEACH VOURS£lF
190
• C
2. This program shows how you can input a string using gets( ) by
using a pointer to a pointer to the string.
#include <stdio.h>
int main(voidl
p = str;
mp = &Pi
return 0;
EXERCISE
E POINTERS AS PARAMETERS
• EXAMPlES
int main(void )
•
192 TEACH YOURSELF
• C
return 0;
)
printf(ft \ n~) i
char str[BOj;
return 0;
UERCISES
1. Write your own version of strcat( ) called mystrcat( ), and
write a short program that demonstrates it.
2. Write a program that passes a pointer to an integer variable to a
function. Inside that function, assign the variable the value -1.
After the function has returned, demonstrate that the variable
does, indeed, contain -1 by printing its value.
return 0;
)
p =: str;
Skills
This section checks how well you have integrated the material in
this chapter with that from eatl!~r chapters.
1. What is the advantage of using pointers over array indexing?
2. Below is a program that counts the I1Umber of spaces in a string
entered by the user. Rewrite the program so that it uses pointer
arithmetic rather than array indeXing.
#include <stdio.h>
int main(void)
(
char str(801;
• int i. spaces;
spaces = 0;
for(i=O: str(i]; i .... +)
if(strji]==' ') spaces++:
return 0;
)
chapter objectives
195
y
TEACH YOURSELF
196
.., C
p = &i;
.p = 19;
? is generated when you use an array nanle v:ithout an
\\rhc1t
index?
3. Is this fragment correct? If it is correct, explain why it works.
char *p = ~this is a string-;
strcpy(str, -ABCDEFG-);
•
printi(-%c·, *(str+2) j
not supported by the original version ofC. They were added when C was
standardized in 1989. Many consider prototypes to be the single most
important addition made to the C language since its creation. Prototypes
are not technically necessary. However, for reasons that will become
self-evident, they should be used in all programs that you write.
The general form of a function prototype is shown here:
type parameter-nameN);
#include <stdio.h>
return 0;
)
Since the old-style declaration does not inform the compiler about any
of volume( )'S parameters it is not a function prototype. Instead, it
r
simply states vl11btl1ll( g fefurn type. The trouble is that the lack of a
full prototype will allow volume( ) to be called using an incorrect
type and/or number of arguments. For example, given the preceding
program, the following will hot generate a compiler error message
even though it is wrong.
volume(120.2, 99.3); /* missing 1ast arg ttl
Since the compiler has not been given information about volume( )'s
parameters it won't catch the fact thtlt this call is wrong ..
Although the old-style fonvard declaration is no longer used in new
code, you "'ill still find it quite frequently in older programs. If you
will be updating older programs, you should consider adding
prototypes to be your first job.
When function prototypes were added to C, two minor compatibility
problems between the old version of C and the ANSI version of Chad
to be resolved. The first issue was how to handle the old-style forward
declaration, which does not use a parameter list. To do so, the ANSI C
standard specifies that when a function declaration occurs without a
parameter list, nothing whatsoever is being said ahout the parameters
to the function .. It might have parameters, it might not. This allows
old-style declarations to coexist with prototypes. But it also leads to a
question: how do you prototype a function that takes no arguments?
For example, this function simply outputs a line of periods:
void line ()
{
int i;
void line () ;
This explicitly tells the compiler that the function has no parameters,
and anv call to that function that has parameters is an error. You must
make sure to also use "oid when the function is defined. For example,
line( ) must look like this:
void line(void)
(
int i;
Since we have been using void to specify empty parameter lists since
Chapter I, this mechanism is already familIar to you.
The second issue related to prototyping is the way it affects C's
automatic type promotions. Because of some features of the
environment in which C was developed, when a non-prototyped
function is called, all integral promotions take place (for example,
characters are converted to integers) and all floats are converted to
doubles. However, these type promotions seem to violate the purpose
of the prototype. The resolution to this problem is that when a
prototype eXIsts, the types specified in the prototype are maintained,
and no type promotions will occur.
There is one other special case that relates to prototypes: variable
length argument lists. We won't be creating any functions in this book
that use a variable number of arguments because they require the use
of some advanced techniques. But it is possible to do so, and it is
sometimes quite useful. For example, both printf( ) and seanf( )
accept a variable number of arguments. To sped!)' a variable number
of argumcnts, use ... in the prototype. For example,
int myfunc(int a, ... J;
A ClaMr Look at Functions 201
7.1 UNDERSTAND FUNCTION PROTOTYPES
'"
int main(void)
{
dQUble vol:
return 0;
}
As you will see, this program will not compile because the
compiler knows that volume( ) is declared as having only three
parameters, but the program is attempting to call it with four
parameters.
2. As explained, if a function is defined before it is called. it does
not require a separate prototype. for example. the following
program is perfectly valid:
#include <stdio.h>
i = getnum();
printf(-,r-, i);
return 0;
}
1.1 UNDERSTAND RJNCTION PRDTOTYPfS
int main(void)
{
double answer;
answer = sqrt(9.0~;
printf ("%f". answe'rl;
return 0;
)
ch = get_a_char():
printf(-'c·, ch);
return 0:
)
int get_a_char(voidl
(
return 'a';
)
int main(void)
f
A CIa.... L_ at Functions 205
7.1 UNDERSTAND FUNCTION PROTOTYPfS
"
int *p;
return 0;
}
int *init(int xl
{
count = x;
double myfunc();
return 0;
DERSTAND RECURSION
Recursion is the process by which something is defined in terms of
itself. When applied to computer languages,C!'ecursion means that a
function can call itself)Not all computer languages support .recursive
functions, but C does. A very simple example of recursion is shown in
this program:
(#include <stdio.h>
int main(void)
(
recurse (0) ;
return 0;
)
void recurse(int i)
(
ifCi<101 (
recurse(i+l); / * recursive call */
pnntf C"%d" il;
)
)
9876543210
on the screen. Let's see why.
The recurse( ) function is first called with O. This is recurse( )'s
first activation. Since 0 is Ie.. than 10, recurse( ) ,then calls itself with
the value of i (in this case 0) plus I, This is the second activation of
recurse( ). and i equals I. This causes recurse( ) to be called again
using the value 2. This process repeats until recurse( ) is called with
the value 10. This causes recurse( ) to return. Since it returns to the
point of its call, it will execute the printf( ) statement in its previous
activation, print 9, and return. This, then, returns to the point of its
call in the previous activation, which causes 8 to be displayed. The
process continues until all the calls return, and the program
terminates)
208 TtACHYOURSa.f
" c
EXAMPLES
1. The recursive program described above can be altered to print
the numbers 0 through 9 on the screen. To accomplish this,
only the position of the printf( ) statement needs to be
changed, as shown here:
.include <stdio.h>
int main(void)
(
recurse (0) j
return 0;
)
void recurselint il
"CIaM<~"~" 209
7.2 UNDERSTAND RECURSION
"
(
ifli<lO) (
printfl"%d" i);
recurse (i+1) j
)
}
int main(void)
(
char str[BO)j
return n:
}
int main(void)
(
fl (30);
return 0;
)
"
void fl(int a)
(
H(a) f2(a-l);
., printf('%d " a);
)
void f2(int b)
(
printf(· ... );
H (b) fl (b-l) ;
)
on the screen. Its output is caused by the way the two functions
fI ( ) and f2( ) call each other. Each time fI ( ) is called, it
checks to see if a is zero. If not, it calls f2( ) with a-I. The f2( )
function first prints a period and then checks to see ifb is zero . .
Ifnot, it calls fI( ) with bol, and the process repeats.
Eventually, b is zero and the function calls start unraveling,
causing fI ( ) to display the numbers 0 to 30 counting by twos.
211
~
7.3 TAKEACLOSERLOOKATP/WIMETERS
nurn! = 100:
num2 = 800;
return 0:
)
temp wi;
==
*i = *j;
*j = temp;
) )
, Since pointers to the two integers are passed to the function , the actual
values pointed~ by the arguments are exchanged.
As you know,(when an array is used as an argument to a function ,
only the address of the array is passed, not a copy of the entire array,
which implies call-by-reference. This means that the parameter
declaration must be of a compatible pointer type. There are three
".-~.
1.3 TAKE A CLOSER LOOI! AT PNIMIf1EIIS
fl (count) ;
f2 (count);
f3 (count) ;
return 0;
)
EXAMPLE
return 0;
}
int main(void)
(
int i;
return OJ
)
do (
scanf (" %d num );
M
,
} while(;num<min I I ;num>max);
SS ARGUMENTS TO main(}
Assuming you use a text editor called EDTEXT, then this line causes
the file TEST to be edited.
EDTEXT TEST
return 0;
}
This is a test
is one string.
If you need to pass a command-line argument that does, in fact,
contain spaces, you must place it between quotes, as shown in this
example:
The names of argv and argc are arbitrary-you can use any names
you like. However, argc and argv are traditional and have been used
since C's origin. It is a good idea to use these names so that anyone
reading your program can quickly identify them as the command-line
parameters. •
One last point: the ANSI C standard only defines the argc and argv
parameters. However, your compiler may allow additional parameters
to maine ). For example, some DOS or Windows compatible compilers
allow access to environmental infonnation through a command-line
argument. Check your compiler's user manual.
. EXAMPLES
-
1. When you pass numeric data to a program, that data will be
received in its string form. Your program will need to convert
it into the proper internal fonnat using one or another of C's
standard library functions. The most common conversion
functions are shown here, using their prototypes:
int atoiCchar ·str);
i = atoi(argv[l);
1 = ato1(argv[2));
d = atof(argv[3));
return 0:
)
return 0;
)
if (arge! =2) (
printf("Usage: CONVERT <ounces>\n");
printf("Try Again");
)
else (
"-
pounds; atof(argv[l]) / 16.0;
printf!-'f pounds·, pounds);
)
return 0;
)
i f (arge! ;2) {
printf (·Usage: CONVERT <ounces:>\n-); "
printf ("Try Again-) ;
)
•
ex~t(l); /* stop the program *'
pounds; atof(argv[l]) / 16.0;
printf ( • \f pounds', pounds);
.,
220 WlCH YOURSlI.f
c
return -0;
)
type parameterN;
(
function-code
I
Notice that the declaration is divided into two parts. Within the
parentheses, only the names of the parameters are specified. Outside
the parentheses, the types and names are specified. For example ,
given the following modem declaration
float f(char ch, long size. double rnaK)
(
)
222 TEACH YOURSELF
'" C
One other aspect of the old-style declaration is that you can specify
more than one parameter after the type name. For example, this is
perfectly valid:
myfunc (i. j. k)
int i, j, k;
{
EXAMPLE
int main(voidl
(
printfC-area is %d-, area(lO. 13»);
return 0;
}
int area(l. w)
int 1. w;
(
return 1 .. w.
)
A CIo_1.Dok at FunctIons 223
7.5 COMPARE OLD·STYl.E TO MODERN FUNCT10N PARAMETER DECLARATKJNS '"
Notice that even though the old form of parameter declaration is
used to define the function, it is still possible to prototype the
function.
EXERCISE
1. Convert this program so that Cto_m( ) uses the old-style
declaration form.
#include <stdio.h>
return 0;
)
double f_to_m{double fl
(
return f I 3.28;
)
1. Write a program that allows access only if the user enters the
correct password as a command-line parameter. If the user
enters the right word, print Access Pennitted; otherwise print
. Access Denied.
2. Create a function caned 8triniLup( ) that transforms the string
it is caned with into uppercase characters. Demonstrate its use
in a program. (Hint. use the toupper( ) function to convert
lowercase characters into uppercase.)
A Closer Look at Functions
,.
225
7.5 COMPARE OLD-STYLE TO MODERN FUNCT10NPARAMETfR DEClAAAnONS
chapter objectives
227
~
228 TEACH YOURSELF
• C
Notice that this line does not end in a semicolon. Each time the
macro-name is encountered in the progranl, the associated
character-sequence is substituted for il) For example, consider
this program:
*include <stdio.h>
int main(void)
(
int i;
return 0;
)
(Keep one thing clearly in mind: At the time of the substitution, 100 is
simply a string of characters composed of a I and two as. The
230 TfACH YOURSELF
... C
preprocessor does not convert a numeric string into its internal binary
format. This is left to the compiler.)
(The macro name can be any valid C identifier. Thus, macro names
must follow the same naming rules as do variables. Although macro
names can appear in either upper- or lowercase letters, most
programmers have adopted the convention of using uppercase for
macro names. This makes it easy for anyone reading your program to
know when a macro name is being used.)
(There must be one or more spaces between the macro name and
the character sequence. The character sequence can contain any type
of character, including spaces. It is terminated by the end of the line.)
Preprocessor directives in general and #define in particular are not
affected by C's code blocks. That is(whether you define a macro name
outside of all functions or within a function, once it is defined, all code
after that point may have access to it. For example, this program
prints 186000 on the screen.
#include <stdio.h>
void f (void) ;
int mpin(void)
(
#define LIGHTS PEED 186000
f!) ;
return 0;
)
void f (void)
printf("%ld", LIGHTSPEED);
reason, these values are usually specified using macro names. The
macro names are defined inside the header file that relates to each
specific function. You will see an example of this in the next section.
The second reason macro substitution is important is that it can
help make it easier to maintain programs. For example, if you know
that a value, such as an array size, is going to be used several places in
your program, it is better to create a macro for this value. Then if you
ever need to shange this value, you simply change the macro
definition. A'll references to it will be changed automatically when the
program is recompiled.
EXAMPLES
1. Since a macro substitution is simply a text replacement, you can
use a macro name in place of a quoted string. For example, the
following program prints Macro Substitutions are Fun.
#include <stdio.h>
int main(void )
{
printf (FUN);
return 0;
)
#define SMALL 1
#define MEDIUM SMALL.!
#define LARGE MEDIUM+!
return 0;
)
EXERCISES
printf(STR) ;
int main(void)
(
printf("This is a test.");
return 0;
)
CONSOLE va 233
8.2 EXAMfNE CHARACTER AND STRING INPUT AND O/.JTPUT
"
int getchar(void);
int pUti:har(int ch);
EXAMPLES
int main(voidl
(
char chi
do (
ch = getchar ( ) ;
pu tchar ( , . ' ) ;
while(ch != '\n');
return 0;
}
return 0;
)
on the screen.
EXERCISES
putchar(str) :
•
• C
Both functions use the header file CONIO.H. The getche( ) function
waits until the next keystroke is entered at the keyboard. When a key
is pressed, getche( ) echoes it to the screen and then immediately
returns the character. The character is read as an unsigned char and
elevated to into However, your routines can simply assign this value to
a char value. The getch( ) function is the same as getche( ), except
that the keystroke is not echoed to the screen.
Another very useful non-ANSI-standard function commonly
supplied with a C compiler is kbhit( ). It has this prototype:
int kbhit(void);
The kbhit( ) function also requires the header file CONlO.H. This
function is used to determine whether a key has been pressed or not.
If the user has pressed a key, this function returns true (nonzero), but
does not read the character. If a keystroke is waiting, you may read it
with getche( ) or getch(). If no keystroke is pending, khhit( )
returns false (zero).
For some compilers. the non-standard i/O functions such as
getche( ) are not compatible with the standard i/O functions such
as printf( ) or seanf( ). When this is the case, mixing the two can
cause unu.sui\1 program behavior. Most troubles caused by this
incompatibility occur when inputting information (although problems
could occur on output). If the standard and non-standard 110
functions are not compatible in your compiler, you may need to use
non-standard versions of scanf( ) and/or printf( ), too. These ar~
called cprintf( ) and cscanf( ) .
The cprintf( ) function works like printf( ) except that it does not
translate the newline character (\n) into the carriage return, Iinefeed
pai~ as does the printf( ) function. Therefore, It is necessary to
explicitly output the carriage return (\r) where desired. The cscanf( )
function works like the seanf( ) functiOn. Both cprintf( ) aDd .
cscanf( ) use the CONIO.H header file. The cpdJltf( ) and C8C8nf( )
Junctions are expressly designed to be compatible with .,ach( ) and
getche( ), as well as other non-standard I/O functions.
EXAMPLES
int mainevoid)
{
char Chi
do (
ch = getch();
cprintf(·%c". toupper(ch»;
} while(ch != ' q ' };
return 0;
)
amount = 0.20;
cprintf( "Printing 5-percent tax table\n\r");
cprintf("Press a key to stop.\n\n\r");
do (
cprintf(-amount: 'f. tax: %f \n\r-, amount.
amount-O.OS);
if(kbhit(» break;
amount = amount + 0.20;
} while(amount < 100.0);
return 0:
)
DEBe. .
Although both gets( ) and puts( ) were introduced earlier, leI's take a
closer look at them now. Their function prototypes are
These functions use the header file STDlO.H-. The gets( ) function
reads characters entered at the keyboard until a carriage return is read
(i.e., until the user presses ENTER). It stores the characters in the array
CON8OL£ va 238
'"
EXAMPLES
I. This program shows how you can use the return value of gets( )
to access the string holding the input information. Notice that
this program also confirms that no error has occurred before
attempting to use the string.
'include <stdio.h>
int main(void)
(
char "p. str[BO];
return 0;
}
2. If you simply want to make sure that gets( ) did not encounter
an error before proceeding, you can place gets( ) directly inside
an if statement, as illustrated by the following program:
'include <stdio.h>
int main(void)
(
char str[80];
240
•
printf (-Enter a string: .);
if(gets(str)) /* if not null */
printf(~Here is your string: %5·, str);
return 0;
)
Here, there is no array defined into which gets( ) can put the
string.,This will result in a program failure.
'4. This program outputs the words one, two, and three on three
separate Jines. using puts( ).
#include <stdio.h>
int main(void)
{
puts Vone");
puts(ntwo") ;
puts(ftthree") ;
return 0;
)
EXERCIRS
return 0;
}
STER printf()
Code Fonnat
%c Character
%d Signed decimal integers
<¥oi Signed decimal integers
%e Scientific notation Oowercase 'e')
OfoE Scientific notation (uppercase 'F)
%f Decimal floating point
%g Uses Ofoe or Ofof, whichever is shorter
%G Uses %E or 0/01, whichever is shorter
0100 Unsigned octal
%s String of characters
%u Unsigned decimal integers
%x Unsigned hexadecimal Oowercase letters)
OfoX Unsigned hexadecimal (uppercase letters)
Ofop Displays a pointer
Ofon The associated argument is a pointer to an integer into which the
number of characters written so far is placed.
010010 Prints a % sign
The prinlf() Formal Specifiers ."
• C
#include , <stdio.h>
int main{V01!tt
(
l>rintfl"%.5d\n", 10);
printfl"S%.2f\n", 99.95);
printf("%.lOs", -Not all of this will be printed\n-j;
return 0;
}
00010
$99.95
Not all of
int ii
return 0;
}
Part of the output from this program is shown here. Notice how
the columns are aligned. (Remember, if you try the program,
you will probably see different numbers.)
10982 130 346
7117 11656 1090
22948 6415 17595
14558 9004 31126
18492 22879 3571
26721 5412 1360
27119 25047 22463
13985 7190 31441
30252 27509 31214
19816 14779 26571
17995 19651 21681
13310 3734 23593
15561 21995 3979
11288 18489 16092
5892 8664 28466
5364 22766 13863
20427 21151 17639
8812 25795 100
12347 12666 15108
int main(voidl
{
printf ("%d %0 %x %X\n" , 90, 90. 90, 90);
printf("%e U\n", 99.231, 99.231);
return. 0;
)
90132 Sa 5A
9.92310e+01 9.92310E+01
4. The following program demonstrates the %n specifier:
.include <stdio.h>
int main(void)
{
246 TtACH YOURSW'
'" C
-
int i;
return 0;
)
100 123.230000
15 characters output so far
EJlERCISU
.ode Meaning
c Read a single character
d Read a decimal integer
Read a decimal mteger
e Read a floating-point number
f Read a floating-point number
g Read a floating-point number
Read an octal number
Read a string
Read a hexadecimal number
Read a pointer
n Receives an integer value equal to the number of characters read so far
%u Read an unsigned integer
%[ 1 Scan for a set of characters
newline, This means that you cannot easily use seanf( ) to read input
like this into a string:
this is one string
this input
555-2345
will cause seanf( ) to assign 555 to first, discard the ., and assign
2345 to second. Since the hyphen is not needed, there is no reason to
assign it to anything. Hence, no associated argument is supplied.
You can specify a maximum field width for all specifiers except %e,
for which a field is always one character, and %n, to which the
concept does not apply. The maximum field width is speCified as an
unsigned integer, and it immediately precedes the format specifier
character. For example , this limits the maximum length of a string
assigned to str to 20 characters:
sca n f ( - %2 0 s· , str);
EXAMPLES
#include <stdio.h>
'*printfC"Enter
Enter "this is a test" */
a string: ");
scanf (. %5·, str);
printf (str);
return 0;
)
int main(voidl
(
char str(80];
printf (str);
return 0:
}
int main(void)
(
char strlaO);
return 0;
)
s ..... itch(op) {
case '.': printf("%d-, i+j);
break;
case '-': printf("'d-, i-j);
break;
case 'I': if{j) printf(-'d-, i/j):
break;
case '.' .: printf(-'d-, i*j);
)
return 0;
)
return 0;
)
If you run this program and enter the number 12345, i will be
assigned 123, and j will have the value 45 . The reason for this is
that scanf( ) is told that i's field is only three characters long.
The remainder of the input is then sent to j.
6. This program illustrates the effect of having non-whitespace
characters in the control string. It allows you to enter a decimal
value, but it assigns the digits to the left of the decimal point to
one integer and those to the right of the decimal to another. The
decimal point between the two %d specifiers causes the decimal
point in the number to be matched and discarded.
'include <stdio.h>
int rnain(void)
(
int i. j;
return 0;
)
EXERCISES
1. Write a program that prompts for your name and then inputs
your first, middle, and last names. Have the program read no
more than 20 characters for each part of your name. Finally,
have the program redisplay your name.
2. Write a program that reads a floating-point number as a string
using a scanset.
3. Is this fragment correct? If not why not?
char ch;
3. What is a scanset?
4. Write a program, using scanf( ), that inputs your first name,
birth date (using the format mml dd/yy), and telephone
number. Redisplay the information on the screen to verify that
it was input correctly.
5. What is one advantage to using puts( ) over printf( ) when
you only need to output a string? What is one disadvantage to
puts( )?
6. Write a program that defines a macro called COUNT as the
value 100. Have the program then use this macro to control a
for loop that displays the numbers a through 99.
7. What is EOF, and where is it defined?
Cumulative
Check
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
1. Write a program that allows you to enter the batting averages for
the players on a little league team. (Assume there are exactly 9
players.) Have the user enter the first name and batting average
of each player. Use a two-dimensional character arrav to hold
the names and a one-dimensional double array to hold the
batting averages. Once all the names are entered, have the
program report the name and average of the players with the
highest and lowest averages. Also, have the program display the
team average.
2. Write a program that is a simple electronic library card catalog.
Have the program display this menu:
Card Catalog:
1. Enter
2. Search by Author
3. Search by Title
4. Quit
Choose your selection:
CONSOLE 110
8.6 MASTER scanf()
.,
255
If you choose Enter, have the program repeatedly input the name,
author, and publisher of a book. Have this process continue until the
user enters a blank line for the name of the book.
For searches, prompt the user for the specified author or title and
then, if a match is found, display the rest of the information. After you
finish this program, keep your file, because in the next chapter you
wi11learn how to save the catalog to a disk file.
'.
'.
9
File I/O
chapter objectives
257
'"
.
258 TfACH YOURSELF
Most C compilers supply two complete sets of file 110 functions. One is called
the ANSI file system (sometimes called the buffered file system). This file
system is defined by the ANSI C standard. The second file system is based on
the original UNIX operating environment and is called the UNIX-like file
system (sometimes called the unbuffered file system). This file system is not
defined by the ANSI C standard. The ANSI standard only defines one file
system because the two file systems are redundant. Further, not all
environments may be able to adapt to the UNIX-like system. For these
reasons, this book only discusses the ANSI file system. For a discussion of the
UNIX-like file system, see my book C: The Complete Reference (Berkeley,
CA, Osborne/McGraw-HilI).
•
File I/O 259
9.1 UNDERSTAND STREAMS
NDERSTAND STREAM S
Before we can begin our discussion of file 1/0, you must understand
two very important concepts: the stream and the file. The C I/O system
supplies a consistent interface to the programmer, independent of the
actual I/O device being used. To accomplish this, C provides a level of
abstraction between the programmer and the hardware. This abstraction
is called a strean1':(The actual device providing I/O is called a file.
Thus, a stream is a logical interface to a file. As C defines the term file,
it can refer to a disk file, the screen, the keyboard, memory, a port, a
file on tape, and various other types of I/O devices. The most common
form of file is, of course, the disk file. Although files differ in form and
capabilities, all streams are the same. The advantage to this approach
is that to you, the programmer, one hardware device will look much
like any other The stream automatically handles the differences.
A stream is linked to a file using an open operatton. A stream is
disassociated from a file using a close operation)
There are two types of streams: text and binary. A text stream
contains ASClI characters. When a text stream is being used, some
character translations may take place. For example, when the newline
character is output, it is usually converted into a carriage return, !inefeed
pair. For this reason, there may not be a one-to-one correspondence
between what is sent to the stream and what is written to the file.
A binary stream may be used with any type of data. No character
translations will occur, and there is a one-to-one correspondence
between what is sent to the stream and what is actually contained
in the file.
One final concept you need to understand is that of the CUlTent
location. The current location, also referred to as the CUlTent position,
is the location in a file where the next file access will occur. For
example, if a file is 100 bytes long and half the file has been read, the
next read operation will occur at byte 50, which is the current location.
To summarize: In C, disk I/O (like certain other types of I/O) is
performed through a logical interface called a stream. All streams have
similar properties, and all are operated on by the same I/O functions,
no matter what type of file the stream is associated with. A file is the
••
260 TEACH YOURSElF
• C
actual physical entity that receives or supplies the data. Even though
files differ, streams do not. (Of course, some devices may not support
random-access operations, for example, so their associated streams
will not support such operations either.) .
Now that you are familiar with the theory behind C's file system, it
is time to begin learning about it in practice.
The fopen( ) fpnction, like all the file-system functions, uses the
header STDIO.H:(rhe name of the file to open is pointed to by fname.
It must be a valid file name, as defin~d by the operating system. The
string pointed to by mode determines how the file may be accessed.
The legal values for mode as defined by the ANSI C standard are shown
in Table 9-1. Your compiler may allow additional modes)
.../ (If the open operation is successful, fopen( ) returns a valid file
pointer. The type FILE is defined in STDIO.H. It IS a structure that
holds various kinds of information about the file, such as its size, the
current location of the file, and its access modes. It essentially
identifies the file)(A structure is a group of variables accessed under
one name. You will learn about structures in the next chapter, but you
do not need to know anything about them to learn and fully use C's
file system.)(The fopen( ) function rerurns a pointer to the structure
associated with the file by the open process. You will use this pointer
with all other functions that operate on the file. However, you must
never alter It or the object it pomts to)
...... G!fthe fopen( ) function fails, it returns a null pointer. The header
STDlO.H defines the macro NULL, which is defined to be a null pointer.
It is very important to ensure that a valid file pointer has been
remrned . To do so, check the value returned by fopen( ) to make
sure that it IS not NULL)for example, the proper way to open a file
called my file for text input is shown in this fragment:
9,2
-
AiellO
MASTER FILE-SYSTEM BASICS
.
261
FILE Tfp;
I
Mode Meaning
I'r" Open a text file for readIng.
It
I'W Create a text file for writing.
I'a" Append to next file.
Open a binary file for reading.
"wb lt
Create a binary file for writing.
"ab" Append to a binary file.
"r+1t Open a text file for read/write
"w+" Create a text file for read/write
"a+" Append or create a text file for read/write.
IIr+b" Open a binary file for read/write. You may-also use "rb+".
I'w+b ll
Create a binary file for readiwrite.'(b~-niily '~iso u~e "wb+".
"a+b" Append or create a binary file fo~ read/write. You may ~Iso use "ab+".
, .....
The Legal Values for Mode :y. " " . ..... '.
TABLE 9-1
, ' "
. '.'.
-'
262 TEACH YOURSELF
" C
The fcJose( ) function closes the file associated with fp, which must
be a valid file pointer previously obtained using fopen( ), and
disassociates the stream from the file. In order to improve efficiency,
most file system implementations write data to disk one sector at a
time. Therefore, data is buffered until a sector's worth of information
has been output before the buffer is physically written to disk. When
you call fcJose( ), it automatically writes any information remaining
in a partially full buffer to disk. This is often referred to as flushing the
buffer.
You must never call fcJose( ) with an invalid argument. Doing so
will damage the file system and possibly cause irretrievable data loss.
The fcJose( ) function returns zero if successful. If an error occurs,
EOF is returned)
J'(Once a file has been opened, depending upon its mode, you may
read and/or write bytes (i.e., characters) using these two functions:
The fgetc( ) function reads the next byte from the file described by
fp as an unsigned ehar and returns it as an integer. (The character is
returned in the. low-order byte.) If an error occurs, fgete( ) returns
EOF. As you should recall from Chapter 8, EOF is a negative integer
(usually -1). The fgete( ) function also returns EOF when the end of
the file is reached. Although fgete( ) returns an integer value, your
program can assign it to a ehar variable since the low-order byte
contains the character read from the file.
The fputc( ) function writes the byte contained in the low-order
byte of eh to the file associated with fp as an unsigned char. Although
ell is defined as an int, you may cal1 it using a char, which is the
common procedure. The fpute( ) function returns the character
written if successful or EOF if an error occurs)
Historical note: The traditional names for fgete( ) and fpute( ) are
getc( ) and pute( ). The ANSI C standard still defines these names,
and they are essential1y interchangeable with fgete( ) and fputee ).
One reason the new names were added was for consistency. Al1 other
ANSI file system functio" names begin with 'f: so 'r was added to
FlI.1I0 263
9.2
-
MASTER RLE-SYSTEM BASICS
~
getc( ) and putc( ). The ANSI standard still supports the traditional
names, however, because there are so many existing programs that
use them. Ifyoll see programs that use getc( ) and putc( ), don't
worry. They are essentially different names for fgetc( ) and fputc( ).
~. EXAMPLES '
int main(void)
{
char str(801 = "This is a file system test. \n";
FILE "'fp;
char .p;
int i:
p++ ;
fclose(fp) ;
264 TEACH YOURSW
" C
return 0;
)
In this version, when reading from the file, the return value of
fgetc( ) is assigned to an integer variable called i. The value of
this integer is then checked to see if the end of the file has been
reached_ For most compilers, ho,,-ever, you can simply assign
the value returned by fgetc( ) to a char and still check for EOF,
as IS shown in the follo\,·.. ing version:
#include <s~dio.h>
#include <std~ib.h>
}
p++
}
fcloselfp} ;
fclose (fp) ;
return 0;
}
int main(void}
(
char str(801 = "This is a file system test. \n~;
FILE *fp;
char ch, *p;
for!;;) {
if«ch = fgetc'fpl I -- EOF) break;
putchar(ch) ;
',.
fclose (fp) ;
return 0;
fDol you. Here's what is happening. First, inside the if, the
return value of fgetc( ) is assigned to ch. As you may recall, the
assignment operation in C is an expression. The entire value of
(ch = fgetc(fp)) is equal to the return vaiue offgetc().
Therefore, it is this integer value that is tested against EOF.
Expanding upon this approach, you will normally see this
program written by a professional C programmer as follows:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char strl8D] = "This is a file system test.\n";
File 1/0 267
~
9.2 MASTER FILE-SYSTEM BASICS
FILE "'fp;
char ch, "'p;
fclose (fp) ;
return 0;
)
FILE: *fp;
char chi
return 0;
)
2. Write a program that reads a text file and counts how many
times each letter from 'A' to 'Z' occurs. Have it display the results.
(Do not differentiate between upper- and lowercase letters.)
3. Write a program that copies the contents of one text file to
another. Have the program accept three command-line arguments.
The first is the name of the source file, the second is the name
of the destination file, the third is optional. If present and ifit
equals 'watch," have the program display each character as it
copies the files; otherwise, do not have the program display any
screen output. If the destination file does not exist, create it.
As you know, when fgetc( ) returns EOF, either an error has occurred
or the end of the file has been reached , but how do "vou know which
event has taken place? Further if you are operating on a binary file, all
values are valid. This means it is possible that a byte will have the
same value (when elevated to an int) as EOF, so how do you know if
valid data has been returned or if the end of the file has been reached?
The solution to these problems are the functions feof( ) and ferror( ),
whose prototypes are shown here:
The feof( ) function returns nonzero if the file associated with fp has
reached the end of the file. Otherwise it returns zero. This function
works for both binary files and text files. The ferror( ) function
returhs nonzero if the file associated with fp has experienced an error;
othefW'ise, it returns zero.
Using the feof( ) function, this code fragment shows how to read to
the end of a file:
FILE *fp;
'" C
This code works for any type of file and is better in general than
checking for EOF. However, it still does not provide any error
checking. Error checking is added here:
FILE *fp;
Keep in mind that ferrore ) only reports the status of the file system
relative to the last file access. Therefore, to provide the fullest error
checking, you must call it after each file operation.
The most damaging file errors occur at the operating-system level.
Frequently, it is the operating system that intercepts these errors and
displays its own error messages. For example, if a bad sector is found
on the disk, most operating systems will, themselves, stop the
execution of the program and report the error. Often the only types of
errors that actually get passed back to your program are those caused
by mistakes on your part, such as accessing a file in a way inconsistent
with the mode used to open it or when you cause an out-of-range
condition. Usually these types of errors can be trapped by checking
the return type of the other file system functions rather than by
calling ferrore ). For this reason, you will frequently see examples of
C code in which there are relatively few (if any) calls to ferrore ). One
last point: Not all of the file system examples in this book will provide
full error checking, mostly in the interest of keeping the programs
short and easy to understand. However, if you are writing programs
for actual use, you should pay special attention to error checking.
File I/O 271
9.3 UNDERSTANDfeof() ANDfenor()
EXAMPLES
1. This program copies any type of file, binary or text. It takes two
command-line arguments. The first is the name of the source
file, the second is the name of the destination file. If the
destination file does not exist, it is created. It includes full error
checking. (You might want to compare this version with the
copy program you wrote for text files in the preceding section.)
/* Copy a file. */
#include <stdio.h>
#include <stdlib.h>
• C
if(fclose(from)==EOF) (
printf{-Error closing source file.\n·);
exit(1);
)
iflfcloseltoi==EOFi (
printf(-Error closing destination file.\nM);
exit(lJ;
)
return .0;
)
2. This program compares the two files whose names are specified
on the command line. It either prints Files are the same, or it
displays the byte of the first mismatch. It also uses full error
checking.
'* Compare files. *j
#include <stdio.h>
#include <stdlib.h>
1 = 0;
same = 1;
'* compare the fi1es'*,
while(!feof(fpl» (
chl = fgetc(fpl);
if (ferror ( fpl» (
printf '-Error reading first file.\nW);
exit(l); •
ch2 = fgetc(fp2);
if(ferror(fp2» (
printf(-Error reading second file.\n-);
exit(l) ;
}
if(chl!=ch2) .(
printf("Files differ at byte number 'lu", l);
same 0:
'II:
break;
}
1++;
}
if (same) printf("Files are the same.\n");
if(fclose(fpl)==EOF} (
printf(-Error closing first file.\ne):
exit(l):
}
if (fclose(fp2)==EOF) (
printf (-Error closiJ"".g second file. \n-) :
exit(l);
274 lJACH YOURSEl.F
. ,.,-
c
return 0;
}
EXERCIIES
1. Write a program that counts the number of bytes in a file (text
or binary) and displays the result. Have the user specify the file
to count on the command line.
2. Write a program that exchanges the contents of the two files
whose names are specified on the command line . That IS , given
two files called FILE! and FlLE2, after the program has run ,
F!LE! will contain the contents that originally were in FlLE2,
and FILE2 will contam FILE! 's original contents. (Hint: Use a
temporary file to aid in the exchange process.)
../ (When working with text files, C provides four functIOns that make file
operations easier. The first two are called fputs( ) and fgets( ) , which
write a string to and read a string from a file, respectively . The ir
pmtotypes are
The fgets( ) function reads characters from the file associated with
fp into the string pointed to by str until num-l characters have been
read , a newline character is encountered, or the end of the file is
reached. In any case, the string is null-terminated. Unlike its related
function gets( ), the newline character is retained. The function
returns str if successful and a null pointer if an error occurs.
The C file system contains two very powerful functions similar to
two you already know. They are fprintf( ) and fscanf( ). These
functions operate exactly like printf( ) and seanf( ) except that they
work with files. Their prototypes are:
EXAMPLES
return 0;
)
return 0;
)
278 TEACH YOURSELF
'I' C
EXERCISES
i = 100;
i f ( fwri te ( .. i.
2. 1. fp) ! = 1) (
printf(·~Tite - error occurred.\n M ) ;
exit(1) ;
)
fclose(fp) ;
H(fread("i. 2. 1, fp) != 1) (
printf (RRead error occurred. \nR);
exit(l);
)
printfC-i is %d-, i);
fclose (fp) ;
RIoVO 281
T
9.5 LEARN ro READ AND WRITE BlNAJlY £lATA
return 0;
}
sizeol(type)
or
sizeol var_name;
For example, if floats are four bytes long and f is a float variable, both
of the following expressions evaluate to 4:
sizeof f
sizeof(float)
When using sizeof with a type, the type must be enclosed between
parentheses. No parentheses are needed when using a variable name,
although the use of parentheses in this context is not an error.
By using sizeof, not only do you save yourself the drudgery of
computing the size of some object by hand, but you also ensure the
portability of your code to new environments. An improved version of
the preceding program is shown here, using sizeof.
#include <s tdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
282 TtACH YOIlRSW
~ c
int i;
1. ::: 1 00 ;
--
if(fwrite(&i. sizeof(intl, 1, fp) != 1) {
print! (MWrite error occurred. \n-);
exit(1) ;
)
fclose (fp) ;
return 0;
-' )
EXAMPLES
double d(10] • (
10.23. 19.87. 1002.23. 12.9. 0.897.
11.45. 75.34. 0.0. 1 . 01. 87 5 .875
) ;
int main(void)
(
int ii
FILE *fPi
return 0;
)
2 ••
y
,
The array is cleared between the write and read operations only
to 'prove' that it is being filled by the &eIId( ) statement.
2. The following progIam does the same thing as the first, but here
only one call to fwrite( ) and fread( ) is used because the
entire array is written in one step. which is much more
efficient. This example helps illustrate how powerful these
functions are.
'include <stdio.b>
'include <stdlib.b>
double d[lOJ = {
10.23. 19.87. 1002.23. 12.9. 0.897.
11.45, 75.34. 0 . 0. 1.01. 875.875
);
int mainevoid)
{
int i;
FILE 'fp;'
exit(l) ;
)
~close(fp) ;
return 0;
.)
EXERCISES
Here, fp is associated with the file being accessed. The value of offset
determines the number of bytes from origin to make the new current
188 lEACH YOURSELF
.., C
position. ongin must be one of these macros, shown here with their
meanings:
Origin Meaning
SEEKJ)ET Seek from start of file
SEEK_CUR Seek from current location
SEEK_END Seek from end of file
EXAMPLES
#include <stdio.h>
#include <stdlih.h>
returr. 0;
)
'" C
long loci
FILE • in, ·out;
char chi
•
/ * see if correct number of command line arguments */
i f large! =3 l I
printf(-Usage: revcopy <source> <destination>.\n-);
exit(1);
}
return 0;
}
3. This program writes ten double values to disk. It then asks you
which one you want to see. This example shows how you can
randomly access data of any type. You simply need to multiply
the size of the base data type by its index in the file.
iinclude <stdio.h>
iinclude <stdlib.h>
FIoIJO 2118
-
9.6 UNDERSTAND IWIDOM ACCESS '"
double d[101 = {
10.23, 19.87, 1002.23, 12.9, 0.897,
11.45, 75.34, 0.0, 1.01, 875.875
} ,
int main(void}
{
long Icc;
double value;
FILE "'fp;
fclose (fp) ,
fclose(fp) ,
return 0;
}
290 T£ACH YOURSELF
'" C
EXERCIIU
1. Write a program that uses fseek( ) to display every other byte
in a text file. (Remember, you must open the text file as a
binary file in order for fseek( ) to work properly.) Have the
user specify the file on the command line.
2. Write a program that searches a file, specified on the command
line, for a specific integer value (also speCified on the command
line). If this value is found, have the program display its
location, in bytes, relative to the start of the file.
Here, oldname points to the original name of the file and newname
points to its new name. The function returns zero if successful and
nonzero if an error occurs.
You can erase a file using remove( ). Its prototype is
This function will erase the file whose name matches that pointed to
by file-name. It returns zero if successful and nonzero if an error occurs.
You can position a file's current location to the start of the file using
rewind( ). Its prototype is
It rewinds the file associated with [p. The rewind( ) function has no
return value, because any file that has been successfully opened can
be rewound.
RleIlO 281
.., .
9.7 LEARN ABOUT VARIOUS FlU-SYSTEM FUNCnONS
It flushes the buffer of the file associated with {p. The function returns
zero if successful, EOF if a failure occurs. If you call fflush( ) using a
NULL for {p, all existing disk buffers are flushed.
EXAMPLES
int main(void)
{
char fname[BO};
return 0;
)
• C
(
FILE *fp;
/* show it once * 1
whil,.l! feof I fp) )
putcharlgetclfp»;
rewind ( £p) ;
1 * show it twice • I
fcloselfp) ;
return 0;
)
fflush(fp) ;
int main(void)
(
if (rename ( "myfi Ie. txt", ·yourf ile. txt") )
- - ---
file 1/0 293
9.8 LEARN ABOUT THE STANDARD STREAMS
'"
printf ("Rename failed. \n") ;
else
printf (" Rename successful. \n ~ ) ;
return 0;
}
EXERCISES
EXAMPLES
int main(voidl
return 0;
)
return 0;
}
" C
int main(void)
(
char str[lO);
int i;
return 0;
}
EXERCISES
Skills Check
2. Write a program that copies a text file. Have the user specify
both file na~es on the command line. Have the copy program
convert all lowercase letters into uppercase ones.
3. What do fprintf( ) and fscanf( ) do?
4. Write a program that uses fwrite( ) to write 100 randomly
generated integers to a file called RAND.
5. Write a program that uses fread( ) to display the integers stored
in the file called RAND, created in Exercise 4.
6. Using the file called RAND, write a program that uses fseek( )
to allow the user to access and display the value· of any integer
in the file.
7. How do the "console' I/O functions relate to the file system?
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
ch....... ableed...
299
"
300 TtACIf YOUIISfI.f
'" C
N
. ~
Review
Skills Check
1. Write a program that copies a file. Have the user specifY both
the source and destination file names on the command line.
Include full error checking.
2. Write a program using fprintf( ) to create a file that contains
this information:
this is a string 1230.23 IFFF A
struet tag-name {
type member I ;
type member2;
type f!lember3;
I¥pe memberN;
} variable-list;
The keyword struct tells the compiler that a structure type is being
defined. Each type is a valid C type . The tag-name is essentially the
type name of the structure, and the variable-list is where actual
instances of the structure are declared. Either the tag-name or the
variable-list is optional, but one must be present (you will see why
shortly) . The members of a structure are also commonly referred to as
fields or elements) This book will use these terms interchangeably.
( Generally, the information contained in a structure is logically
related. For example, you might use a structure to hold a person's
address. Another structure might be used to support an inventory
program in which each item's name, retail and wholesale cost, and the
quantity on hand are stored. The structure shown here defines fields
that can hold card-catalog information:
struct catalog (
c har name [ 40] ; / ' author name ' /
char title[40] ; / ' title ' /
char pub[40] ; / ' publisher ' /
unsigned datei / ' copyright date ' /
unsigned char edi / ' edition ' /
) card;
Here, catalog is the type name of the structure. It is not the name
of a variable. The only variable defined by this fragment is card. It is
important to understand that a structure declaration defines only a
logical entity, which is a new data type . It is not until variables of that
type are declared than an object of that type actually exists. Thus,
catalog is a logical template; card has physical realitYJigure 10-1
fiGURE 10-1
~_n~rum~e_____~~bc.Y=~=-___________?~~~______~
How the etmI
structure variable ~~ti~·tl7e~____~40~b~Yt~~__________--(~~
appears in ~~p_u_b____~4~O~b~Y_t~ ______- ,__-J\ \~________~
memory date 2 bytes I
(assuming 2-byre ed Ibte I
integers)
T
Notice that the & goes before the structure name, not before the
member name.0n a similar fashion, these statements input the
author'S name and output the title:
gets{card.name);
printf(~%s·, card.~itle);
(once you have defined a structure type, you can create additional
variables of that type using this general form:
STRUCTUAES 1IMo'- 303
~
10. I WoSTfR STRUCTURE BASICS
In actual practice, however, you will usually want to specify the tag name)
(Structures can be arrayed in the same fashion as other data types.
For example, the following structure definition creates a ! DO-element
array of structures of type catalog:
struct catalog cat[lOO];
varl.a = 10:
varl.f = 100.23;
var2 = varl;
After this fragment executes, var2 will contain exactly the same thing
as varl)
EXAMPLES
struct s_type {
int i;
char chi
double d;
char str[BO}:
} 5;
int main(void)
(
printf(-Enter an integer: .);
scanf ( • %d: ., &s . i) ;
printf(-Enter a character: .);
scanf(- %c~. &s.ch):
printf(·Enter a flo~ting point numbe=: .);
scanf("'lf", &s.d);
printf("Enter a string: .);
STRUCTURES AND UNIONS 305
10.1 MASTER STRUCTURE BASICS .,
return 0;
)
2. When you need to know the size of a structure, you should use
the sizeof compile-time operator. Do not try to manually add'up
the number of bytes in each field. There are three good reasons
for this. First, as you learned in the preceding chapter, using
sizeof ensures that your code is portable to different
environments. Second, in some situations, the compiler may
need to align certain types of data on even word boundaries. In
this case, the size of the structure will be larger than the sum of
its individual elements. Finally, for computers based on the
8086 family of CPU. (such as the 80486 or the Pentium), there
are several different ways the compiler can organize memory.
Some of these ways cause pointers to take up twice the space
they do when memory is arranged differently.
When using sizeof with a structure type, you must precede
the tag name with the keyword 8truct, as shown in this program:
tinclude <stdio.h>
struct s_type {
int i;
char ch:
int *p;
double d;
} S;
int rnain{void)
(
return 0;
)
" C
how the entire structure array is written and read from disk in a
single operation.
/* An electronic card catalog. */
.include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct catalog (
char name (80 J ; ,.,. .,
author name .,
char title[801, title
," publisher
char pub[80] ,
unsigned date; ," copyright "' "'
date
," edition
]
unsigned char ed,
cat [1dAX] , "'
int top = 0; /* last location used */
do (
choice =. menu();
switch (choice) (
case 1: enter();
break,
'* enter books */
CAse 2: author_search();
break;
'* search by author */
} while(choicel=S);
return 0;
)
printf(NCard catalog:\n");
printE(" 1. Enter\n~);
printE(" 2. Search by Author\n");
printE(" 3. Search by Title\n");
printE(" 4. Save catalog\n");
printE(" 5. Quit\n");
do (
printf{~Choose your selection: ");
gets (str);
i = atai (str);
printE("\n") ;
) whUeli<l II i>5);
return i;
)
/* Search by author. */
void author_search(voidl
{
char name[BO);
int i, found;
found = D.
for(i=O; i<top; i++)
if(!strcmp.{narne. cat[ij.name») {
display (i) ;
found =
1;
printf("\n") ;
;* search by title. */
void title_search(voidl
{
char title[8D];
int i, found;
printf("Title: 10);
gets (title);
found = 0;
for(i=O; i<top; i++)
if{!strcrnp(title. cat{i}.title) {
display (i) ;
found = 1;
printf ( .. \n");
)
if{!found} printf("Not Found\n");
)
STRIJCllJRfS AND_
'0. , MASTER STRUCTURE BASICS
fclose (fp) ;
}
fclose (fp) ;
)
fclose (fp) ;
)
10.1 MASTER STRUCTURE BASJCS
fclose ( fp) ;
}
int i;
i = 10;
312 _'fUP f
... C
B.i = 100;
B.j = 101;
return 0;
)
at .....:t a_type (
int i;
double d;
);
varl ~ fO;
printf("d 'f', varl.i, varl.d);
return 0;
)
temp. i = 100;
temp.d = 123.23; •
return temp;
)
STRUCTURES AND UNIONS 313
"I'
lal MASTER STRUCTURE BASICS
struct s_type {
int i;
double d:
};
int main(void)
{
struct s_type varl;
varl.i = 99;
varl.d = 98.6;
f (varl);
return 0;
}
.:1', . . . . . .
long 1;
char str[aO];
} 5;
~ = 10:
3. On your own, examine the header file STDIO.H and look at how
the FILE structure is defined.
Remember ( When accessing a member usirig a structure variable, use the dot operator.
When accessing a member using a pointer, use the arrow operator. )
EXAMPLES
struct s_type {
int it
char str[aO];
s. *p;
int main(void)
(
p = &5;
return 0;
316 TEACH YOURSELF
" C
int main(void)
(
struct tm *systime;
time_t 't;
t = time (NULL) ;
systime = localtime(&tl;
return 0;
J
Time is 10:32:49
Date: 03115/97
EXERCISES
p.a = 100;
struct worker (
char narne[80];
int aV9_uni ts-per_hour: •
int aV9_errs-per_hour;
) ;
struct asm_line {
int product_code;
double material_cost;
STRUCTURES AND UNIONS 319
10.3 WORK WITH NESTED STRUCTURES
As you see, the structures are accessed from the outer to the inner.
This is also the general case. Whenever you have nested structures,
you begin with the outermost and end with the innermost.
, EXAMPLE
struct book_type (
unsigned date; /. copyright date ./
unsigned char ed; /. edition ' f
unsigned pages; f' length of book ' f
)
320 TEACH YOURSElf
~ C
struct catalog {
char name[80] ; /* author name *j
char title[80]; /- title */
char pub[80]; /- publisher -/
struct book_type book; /* mechanical info wi
) cat [MAX] ;
int main(voidl
{
int choice;
do {
choice = menu () ;
5wi tch (choice) (
case 1: enter(); '* enter books */
break;
case 2: author_search(); /* search by author */
break;
case 3: title_search(); /* search by title */
break;
case 4.: save();
)
} while(choice!=51;
returr. 0;
)
printf("Card catalog:\n");
printf(" 1. Enter\n");
printf{" 2. Search by Author\n");
printf{" 3. Search by Title\n");
printf'" 4.. Save catalog\n");
printf'" 5. Quit'n");
do {
10.3
STRUCnJRES AND UNIONS
WORK WITH NESTED STRUCTURES
,.
321
return i;
)
/* Search by author. */
void author_search (void)
{
char name [ 80] ;
int i, found;
found = 0;
for(i=O; i<top; i++)
if(!strcmp(name. cat{i] .narne» {
display(i) ;
found = 1;
printf,-'n M
) ;
printftMTitle: .);
gets{':.ltle);
fCl1.:.nd = 0;
void load(void)
(
FILE ·fp;
return;
}
fclose (fp) ;
}
" C
EXERCISE
EXAMPLES
1.( It is not nece~sary to name every bit when using bit-fields. Here,
for example, is a structure that uses bit-fields to access the first
and last bit in a byte.
struct b_type {
unsigned first: 1;
int : 6;
unsigned last: 1;
};
The use ·of unnamed bit-fields makes it easy to reach the bits
you are interested in.)
2. To see how useful bit-fields can be when working with Boolean
data, here is a crude simulation of a spaceship flight recorder.
By packing all the relevant information into one byte,
comparatively little disk space is used to record a flight.
/* Simulation of a 100 minute spaceship
. /
flight recorder .
#include <stdlib.h>
#include <stdio.h>
display(flt_recd) :
fwrite(&flt_recd, sizeof flt_recd, 1, fp) i
)
fcloselfp) :
return 0:
)
" C
EATE UNIONS
union tag-name {
type member 1;
type member2;
type member3;
(union u_type (
int i;
charc{2];
double d;
} samplei
t-I- - - - - - - - d
t-c[O) + c[I)-1
in
I I I
330 TEACH YOURSElf
'" C
( To access a member of a union, use the dot and arrow operators just
as you do for structures. For example, this statement assigns 123.098
to d of sample:
samp1e.d = 123.098;
If you are accessing a union through a pointer, you must use the arrow
operator. For example, assume that p points to sample. The following
statement assigns i the value 101:
p->i = 101;)
EXAMPLES.
I. Unions are very useful when you need to interpret data in two
or more different ways. For example, the encode( ) function
shown below uses a union to encode an integer by swapping its
two low-order bytes. The same function can also be used to
decode an encoded integer by swapping the already exchanged
bytes back to their original positions.
#include <stdio.h>
int main(void)
(
int i;
return 0;
)
crypt.num = i;
j *swap bytes */
ch = crypt.e(O];
crypt.e[O] = crypt.e[l];
crypt.e(l] = chi
10 encoded is 2560
i decoded is 10
struct sample (
unsigned a: 1;
unsigned b: 1;
332 nACH YOURSELF
." C
unsigned c, 1 ;
unsigned d, 1;
unsigned e, 1 ;
unsigned f' 1;
unsigned g' 1;
unsigned h, 1;
) ;
union key_type {
char chi
struct sample bits;
key; ,
int main(void~
(
printf("Strike a key: ~);
key.ch = getche();
printf (~\nBinary code is: "l;
return 0;
Strike a key: X
Binary code is: 0 1 0 1 1 0 0 0
EXERCISES
1. Using a union composed of a double and an 8-byte character
array, write a function that writes a double to a disk file, a
character at a time. Write another function that reads this value
from the file and reconstructs the value using the same union.
(Note: If the length of a double for your compiler is not 8 bytes,
use an appropriately sized character array.)
2. Write a program that uses a union to convert an int into a long.
Demonstrate that it works.
char b;
float bali
} myvar, .p;
p = &myvar;
p.a = 10;
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
program that copies one file to another. Assign the return value
of fgetc( ) to a union that contains an integer and character
member. Use the integer element to check for EOF. Write the
character element to the destination file. Have the user specify
both the source and destination tile names on the command line.
3. What is wrong with this fragment?
Sl:.ruct s_type {
int a;
int b: 2;
int c: 6;
} vari
337
••
338 TEACH YOURSELF
'" ' C
svar->i = 100;
5. What is a bit-field?
ADVANCED DATA TYP£S AND OPERATORS 339
11. J USE THE STORAGE ClASS SPECJRERS
"
( C defines four type modifiers that affect how a variable is stored. They are
auto
extern
register
static
These spe cifiers precede the type name) Let's look at each now.
( The specifier auto is completely unnecessary)It is provided in C to
allow compatibility with its predecessor, B.Qts use is to declare
automatic variables. Automatic variables are simply local variables,
which are auto by default. You will almost never see auto used in any
C program')
Although the programs we have been working with in this book are
fairly short, programs in the real world tend to be quite long. As the
size of a program grows, it takes longer to compile. For this reason,~
allows you to break a program into two or more files. You can
separately compile these files and then link them together. This saves
compilation time and makes your projects easier to work with)CThe
actual method of separate compilation and linking will be explained in
the instructions that accompany your compiler.) When working with
multiple source files there is, however, one issue that needs to be
addressed. As a general rule, global data can only be defined once.
However,~lobi\l data may need to be accessed by two or more files
that form a program. In this case, each source file must inform the
compiler about the global data it uses. To accomplish this you will
need to use the keyword extern. To understand why, consider the
following program, which is split between two files :
FILE #1:
#include <stdio.h>
int count;
void f1 (void) ;
int main(void)
{
int i;
•
rou:H YOUASB.F
C
return 0;
}
FILE #2:
'include <stdlib.h>
void fl(void)
(
count = rand () ;
}
If.you try to compile the second file, an error will be reported because
count is 'not defined. However, you cannot change fILE #2 as follows:
.include <stdlib.h>
int count;
void fl(void)
(
' count = rand();
J
void fl(vclidJ
ADVANCED DIITA TYPES AND _TORS 341
11.1 USE TIlt; STOAAGE ClASS SPfClRERS •
(
count ='rand();
) )
( Although rarely done, it is not incorrect to use extern inside a
function to declare a global variable defined elsewhere 10 the same
file . For example, the following is valid:
#include <stdio.h>
int count;
lnt main(void)
(
extern int count; /* this refers to global count *1
count = 10;
printf(-%d 8
, count);
return 0;
)
The reason you will rarely see this use of extern is that it is .
redundant. Whenever the compiler encounters a variable name not
defined by the function as a local variable, it assumes that it is global.)
(One very important storage-class specifier is register. When you
specify a register variable you are telling the compiler that you want
access to that variable to be as fast as possible)In early versions of C,
register could only be applied to local variables (including formal
parameters) of types int or char, or to a pointer type. It caused the
variables to be held in a register of the CPU. (This is how the name
register came about.) By using a register of the CPU, extremely fast
access times are achieved.(ln modern versions of C, the definition of
register has been broadened to include all types of variables and the
requirement that register variables must be held in a CPU register
was removed. Instead, the ANSI C standard stipulates that a register
variable will be stored in such a way as to minimize access time. In
practice, however, this means that register variables of type int and
char continue to be held in a CPU register-this is s~iI1 the fastest way
to access them.
No matter what storage method is used, only so many variables
can be granted the fastest possible access time. For example, the CPU
II
has a limited number of registers. When fast-access locations are
342 TEACH YOURSElf
" C
void f (void) ;
int main(void)
(
int i;
return 0;
)
void f(void)
(
static int count = 0;
count++;
printf("count is %d\nM, count);
)
count is 1
count is 2
ADVANCBl OATA TYPES AND DP£RATORS 343
",
//./ USE THE STORAGE CLASS SPECIFIERS
count is 3
count is 4
count is 5
count is 6
collnt is 7
\
count is B
count is 9
count is 10
As you can see, count retains its value between function caHs. The
advantage to using a static local variable over a global one is that the
static local variable is still known to and accessible by only the
function in which it is declared.)
<'!he static modifier may also be used on global variables. When it is,
it causes the global variable to be known to and accessible by only the
functions in the same file in which it is declared. Not only is a function
not declared in the same file as a static global variable unable to
access that global variable, it does not even know its name. This
means that there are no name conflicts if a static global variable in
one file has the same name as another global variable in a different file
of the same program. For example, consider these two fragments,
which are parts of the same program:
FilE #1 FilE #2
int count; static int count;
EXAMPLES
clock_t clock(void);
int main(void)
(
~ register int j:
int k;
clock_t start, finish;
start = clock();
for l k=O; k<lOO; k++l
for(j=O; j<32000 ; j++l;
finish = clock() ;
printf (-Register 'loop: tId ticKs \ n-, finish - start );
return 0;
I
ADVANCW DATA TYPES AND OPERATDRS 345
void f2 (void) :
void f (void) ;
void f (void)
(
register int i, j;
c
void f2(voidl
(
register int j. k;
a = 0;
lee = 0,
fprintf(~System IniLialized~);
first = 0;
)
Because first is static, it will hold its value between calls. Thus,
the initialization code will be executed only the first time the
function is called.
4. Another interesting use for a local static variable is to control a
recursive function. For example. this program prints the
numbers 1 through 9 on the screen:
#include <stdio.h>
void f (void) ;
re turn 0;
}
ADVANCUI DATA TYPES AND OPERATORS 347
~
11.' USE THE STORAGE ClASS SPEC/FifRS
void f (void)
(
static int stop=O:
stop++;
if(stop==10) return;
printf("%d ", stop);
f(); /* recursive call *1
)
FILE #1:
fiinclude <stdio.h>
char str[80];
void getname(void);
return 0;
)
FILE #Z,
'include <stdio.h>
void getname(void)
(
printf("Enter your first name: .. ,; .
gets (str);
)
TEACH YOURSElF
C
EXERCISES
do ("
printf t -Enter a value: .);
scanf ("M', &i);
m = 0;
for(j=O; j<i; j++)
for (k=Oi k<100i k++ )
m = k + mi
while t i>O) ;
return 0;
)
p = &i;
ADVIINGlD DATA TYPES AND OPERATORS 348
1 1.2 USE THE ACCESS MOD/FlEAS
'"
EXAMPLES
int main(void)
{
const int i = 10;
350 TEACH YOURSELf
... c
return 0;
}
int main(void)
{
Canst int i : 10;
return 0;
}
'include <stdio.h>
pr..... str(str) ;
return 0;
}
int main(void)
(
char str [80 1 ;
return 0;
)
EXAMPLES
1. This short program creates an enumeration consisting of the
parts of a computer. It assigns comp the value CPU and then
displays its value (which is 1). Notice how the enumeration tag
name is used to declare comp as an enumeration variable
. separately from the actual declaration of computer.
i n t ma i n (v oi d )
{
enum compu ter c a mp ;
3&4 TfACH YOURSnf
'" C
comp = CPU;
p.r intf(-'d-, comp);
return 0;
}
tp = rand () % 4;
switch (tp I (
case car: printf(·car*):
break;
case train: printf(·train*);
break;
case airplane: printf(*airplane-);
break;
case bus: printf{*bus·);
}
return 0;
}
AOVANC£D DATA TVPfS AND _TORS 355
..,
11.3 DEFINEENUMERATIONS
int main(void)
{
printf ("Press a key to select transport: ");
while(!kbhit(» rand();
getch(); j * read and discard character */
•
tp = rand!) % 4;
printf(~%s·, trans {tp] ):
return 0;
)
EXERCISES
make = GM;
printf{"car is %s", make);
( In C you can create a new name for an existing type using typedef.
The general form of typedef is
int main{void)
smallint i;
return 0;
J)
CKeep two points firmly in mind: First, a typedef does not cause the
original name to be deactivated. For example, in the program, signed
char is still a valid type. Second, you can use several typedef
statements to create many different, new names for the same type)
ADVANCED DATA TYPU AND DPEAATORS 317
y
11.' UNDERSTAND typOdeI
. ( T~ere are basically two reasons to use typedef. The first is to create
portable programs. For example, if you know that you will be writing a
program that will be executed on computers using 16-bit integers as
well as on computers using 32-bit integers, and you want to ensure
that certain variables are 16 bits long in both environments, you might
want to use a typedef when compiling the program for the 16-bit
machines as follows:
typedef int myint;
Then, before compiling the code for a 32-bit computer, you can change
_the typedef statement like this:
typedef short int myint;
EXAMPLES
depth d;
EXERCISES
(These operators work with character and integer types; they cannot be
used with floating-point types.)
The AND, OR, and XOR operators produce a result based on a
comparison of corresponding bits in each operand. The AND operator
sets a bit if both bits being compared are set. The OR sets a bit if either
of the bits being compared is set. The XOR operation sets a bit when
either of the two bits involved is 1, but not when both are 1 or both are
O. Here is an example of a bitwise AND:
ADVANCED DATA TYPES AND OPERATORS
11.5 USE C'S BfTWISf OPERATORS
,.
359
10100110
& 0011 1011
00100010
Notice how the resulting bit is se{, based on the outcome of the
operation being applied to the corresponding bits in each operand.
The 1's complement operator is a unary operator that reverses the
state of each bit within an integer or character.
EXAMPLES
int main(voidl
(
int i;
i = 101);
printf("initial value of i: %d\n-, il;
i = i ;, 21987;
printf(-i after first XOR: %d\n", i);
i = 21987;
i A
return 0;
)
return 0;
)
ch = 'a';
ch = -Chi
printf("\n") ; •
return 0;
}
When you run this program, you will see that the state of bits in
ch are reversed after the operation has occurred.
N
return 0;
}
int rnain(void)
(
short i;
.'
.'
362 TEACH YOURSElF
.,. C
i :: 1;
i=iI32768;
printf("%hd", il;
return 0;
)
It displays - 32 ,767.
EXERCISES
1. One very easy way to encode a file is to reverse the state of each
bit using the N operator. Write a program that encodes a file
using this method. (To decode the file, simply run the program
a second time.) Have the user specify the name of the file on
_ -the command line.
2. A better method of coding a file uses the XOR operation
combmed wah a user-defined key. Write a program that
encodes a file using this method. Have the user speCJfy the file
to code as "'ell as a single character key on the command line.
(To decode the me, run the program a second time using the
Silme key.)
value« number-ot-bits
value» number-ot-bits
The integer expression specified by """,ber-oJ-bits determines how
many places to the left or right the bits within value are shifted. Each
left-shift causes all bits within the specified value to be shifted left one
position and a zero is brought in on the right. A right-shift shifts all bits
to the right one position and brings a zero in on the left. (Unless the
number is negative, in which case a one is brought in.) When bits are
shifted off an end. they are lost.
A right shift is equivalent to di\'idmg a number by 2, and a left shift
is the same as multiplying the number by 2. Because of the internal
operation of virtually all CPUs, shift operations are usually faster than
their equivalent arithmetic operations.
EXAMPLES
void show_binary(unsigned ul ;
int main(void)
{
unsigned short u;
u = 45678;
show_binary (ul ;
u =U « 1;
show_binary (ul ;
u = U » 1;
show_binary (ul ;
return 0;
}
void show_binary(unsigned u}
(
unsigned n;
pri.ntf("\n"I,
}
101100100110tll0
01 1.001 001 1 011 1 00
0011001001101110
Notice that after the leti shift. a bit of information has been lost.
When the right shift occurs, a zero is brought in. As stated
"arlier, bits that are shiftl'd off one end are lost.
2. Since a right shift is the same as a division by two, but faster,
the sbow_binary( ) function can be made more efficient as
shown here:
void sh~_binary(unsigned u)
(
unsigned n;
for(n=32768: n: n=n»l)
if(u & nl printf("l "I,
else printf"(" 0 "I,
printf("\n"l;
}
ADVANCED DATA TYPES AND OPERATORS 365
117 UNDERSTAND THE? OPERATOR
"
ElWICISES
1. Write a program that uses the shift operators to multiply and
divide an integer. Have the user enter the initial value. Display
the result of each operation.
2. C does not have a rotate operator. A rotate is similar to a shift,
except that the bit shifted off one end is inserted onto the other.
For example, 1010 0000 rotated left one place is 0100 0001.
Write a function called rotate( ) that rotates a byte left one
position each time it is called. (Hint, you will need to use a
union so that you can have access to the bit shifted off the end
of the byte.) Demonstrate the function in a program.
EXAMPLES
#include <stdio.h>
int main(void)
(
int i;
i=i>0?1:-1;
printf{"Outcome: %d M
, i);
return 0;
int main(void)
int i;
while(!kbhit(» rand();
i = rand() %2 ? 1: 0;
it (i) printf{"Heads");
else printf ("Tails");
return 0;
int main(void)
(
while(!kbhit(» rand();
return 0;
)
var op = expression;
+ - • / % « » & I
There must be no space between the operator and the equal sign. The
reason you will want to use the shorthand form is not that it saves you
a little typing effort, but because the C compiler can create more
efficient executable code.
EXAMPLES
int main(voidl
(
int i. j, k;
i = j =k = 99;
return 0;
)
2. The next program counts to 98 by twos. Notice that it uses C
shorthand to increment the loop-control variable by two each
iteration.
#include <stdio.h>
int main(void)
(
int i:
/* count by 25 */
for(i=O: i<100: i+=2)
printf(-%d -, i);
return 0;
}
int main(void)
(
int i = 1;
i «= 3; /* multiply by 2, 3 times *j
printf("%d", i);
return 0;
}
EXAMPLES
int main(void)
(
int i, j;
/* count to 49 */
for(i=O, j=100: i<j; i++. j--)
printfl"%d", ii,
return 0;
)
ADVANCED DATA TVl'£S AND OPERATORS 371
/1.9 UNDERSTAND THE COMMA OPERATOR
return 0;
}
Because the comma tells the compiler to 'do this and this: the
program runs the same with the comma after getchar( ) as it
would had a semicolon been used. Using a comma in this way is
considered extremely bad form, however. It is possible that an
unwanted side effect could occur. (This use of the comma
operator does make interesting coffee-break conversation,
however! Many C programmers are not aware of this interesting
twist in the C syntax.)
EXERCISES
Highest . ( [ 1 ->
•
- + - ++ (type cast) • & sizeof
/ %
+ -
« »
< <= > >=
-- .-
1-
&
&&
II
?:
; += -= *= /= etc.
Lowest
1001 0110
11101010
tre program will report that bits 7, 1, and 0 match. (Use the
bitwise operators to solve this problem.)
6. What do the « and » operators do?
7. Show how this statement can be rewritten:
c=c+l0i
This section checks how well you have integrated the material in
this chapter with that from earlier chapters.
4. Using the program you developed for Chapter 10, Section 10.3,
ElIerCise 1, optimize the program by selecting appropriate local
variables to become register types.
12
The ·C Preprocessor
and Some Advanced
Topics
375
....
376 TIACH YOURSELF
c
i = i * 2;
Although you have been using #define and #inc1ude for some time,
both have more features than you've read about so far. Each is
examined here in detail.
In addition to using #define to define a macro name .that will be
substituted by the character sequence associated with that macro, you
can use #define to create [zmctio>1-1ike macros. In a function-like
,.....
~,.j,)d...
macro, arguments can be passed to the macro when it is expanded by
the preprocessor. For example, consider this program:
#include <stdio.h>
,,; ,,'
,,",,,,,
int main{void)
(
int sum;
return 0;
}
The line
is transformed into
sum = 10+20;
by the preprocessor. As you can see, the values 10 and 20 are
automatically substituted for the parameters i and j.
378 TfACH YOURSELF
y
C
int main{void)
(
int r;
return 0;
)
#include <filename>
#include "filename"
So far, all the example programs have used the first form. TI1e
reason for this will become apparent after you read the following
descriptions.
THE C PREPROCESSOR AND SOME ADVANCED TOPICS 379
12.' LEARN MORE ABOLR fdeflne AND *include
If you specif'y the file name between angle brackets, you are
instructing the compiler to search for the file in some implementation-
•
defined manner. For most compilers, this means searching a special
directory devoted to the standard header files. This is why the sample
programs have been using this form to include the header files
required by the standard library functions. If you enclose the file
name between quotation marks, the compiler searches for the file in
another implementation-defined manner. If that search fails, the
search is restarted as if you had specified the file name between angle
brackets. For the majority of compilers, enclosing the name between
quotation marks causes the current working directory to be searched
first. Typically, you will use quotation marks to include header files
that you create.
EXAMPLES
int main( vo i d)
{
l
printf("%d\n", MAX(l, 2));
printf("%d\n", MAX(l, -1));
return 0;
)
int main(void)
(
printf("This is a test~);
return 0;
}
int rnain(voidl
(
printf("This is a random number: %d-, rand();
return 0;
}
381
TIll C PAEPROClSSORANO SOME ADVIIHCEO TOPICS
122 UNDERSTIWOCONDmONAI. COMPILAnON
..,
#if
#else
#elif
#endif
#ifdef
#ifndef
-.-, This section examines these directives.
'.'
The general form of #if is shown here:
#if constant-expression
statement-sequence
#endif
-
382 TEACH YOURSW
#if constant-expression
statement-sequence
#else
statement-sequence
#endif
Notice that there is only one #endif. The #else automatically
terminates the #ifblock of statements. If the constant-expression is
false, the statement or statements associated with the #else are
compiled.
You can create an if-else-if ladder using the #elif directive,
as shown here:
# if constant-expression-!
statement-sequence
#elif constant-expression-2
statement-sequence
#elif constant-expression-3
statement-sequence
#endif
As soon as the first expression is true, the lines of code associated with
that expression are compiled, and the rest of the code is,skipped.
Another approach to conditional compilation is the #ifdef directive.
It has this general form:
#ifdef macro-name
statement-sequence
#endif
defined macro-name
If macro-name is defined, then the outcome is true. Otherwise, it is
I false. FOT example, the following two preprocessor directives are
equivalent:
# ifdef WIN) 2
#if defined WIN32
You can also apply the I .operator to defined to reverse the condition.
EXAMPLES
return 0:
I
'define DEBUG
'*iflargc!=3)
see if correct number of command line arguments
I
*/
return 0;
,,
while(!feof(in» {
THE C PREPROCESSOR AND SOME ADVANCED TOPICS 387
12,2 UNDERSTAND CONDITIONAL COMPILAnON •
ch = fgetc (in) ;
DEBUG == 1 II DEBUG == 3
putchar feb) ;
Itendif
ch = *argv(31 A chi
/tif DEBUG >:: 2
'IO~fr, putchar (eh) ;
illy ntaIii1 #endif
miroml, if(!feof(in» fputc(ch, out);
,glelll )
fclose (in) ;
fclose(outl;
return 0;
)
••
..-."" ...:
;
4. The following fragment illustrates the "elif. It displays NUM IS
.:::; 2 on the screen .
#define NUM 2
tiE NOM == 1
printf("NUM is 1");
#ellf NUM == 2
printf ("NUM is 2");
_€~'.~ t
#elif NOM == 3
printf{"NUM is )N);
#eliE NOM == 4
printf(~NUM is 4");
#endif
•
5. Here, the defined operator is used to determine if
TESTPROJECT is defined .
'include <stdio.h>
#define TESTPROJECT 29
" C
I'"eturn .0 :- __
}
#end i f
EXERCISES
#ifdef !MIKE
#endif
#error effor-message
_ C PIIEPROCUSOR AND SOME IIDVANCED TOPICS 381
12.3 LEARN ABOUT terror, fundef. tHne. AND #pragma
"
#undef macro-name
r- If the macro-name is currently undefined, #undef has no effect. The
fIC·
principal use for #undef is to localize macro names.
When a C compiler compiles a source file , it maintains two pieces of
" information: the number of the line currently being compiled and the
l.
name of the source file currently being compiled. The #line directive
is used to change these values. Its general form is
Here , line-nUll1 becomes the number of the next line of source code ,
and filename becomes the name the compiler will associate with the
source file. The value ofline-num must be between 1 and 32,767. The
filename may be a string consisting of any valid file name. The principal
use for #line is for debugging and for managing large projects.
The #pragma directive allows a compiler's implementor to define
other preprocessing instructions to be given to the compiler. It has this
general form:
- #pragma instructions
-
lill #pragmas depends on how your compiler was implemented.
EXAMPLES
i :Ie 10 ;
.error This is an error message.
printf( - 'd-, i, : /* this line will not be compiled * 1
return 0;
)
Idefine DOG
.undef cpo
'ifdef DOG
printfC MThis line is not compiled . 'n-);
.endif
return 0:
}
"'
*line 1000 -myprog.c·
#error Check the line number and fi~e name.
return 0;
)
EXERCISE
month/day/year
The __TIME__ macro defin~s a string that contains the tim~ the
compilatlOn of a program began. The string has this general form:
hours:minutes:seconds
'EXAMPLES
int main(void)
(
printf(PCompil i ng %5, line: %d, o n %5, at ~s·,
__ FILE __ • __ LINE __ • __ DATE__ •
__ TIME __ I;
return 0;
)
The main use of these macros is to create a time and date stamp,
which shows when the program was compiled.
2. As you learned in the previous section, you can use the #line
directive to change the number of the current line of source
code and the name of the file. When you do this, you are
actually changing the values of __LlNE__ and __FILE__ . For
example, this program sets __ LlNE__ to 100 and _ "':FILE__ to
myprog.c:
#include <st~io_h>
int main/void)
(
#line 100 ~myprog.c~
printf(-Compiling %s, line, %d, on %5, at %5",
__ FILE __ • __ LINE __ . __ DATE __ •
___ TIME __ I:
return 0;
)
..,
3M
EXAMPLES
int main(vqid)
(
int value:
value = 10;
return 0;
)
count! = 10;
count2 = 20;
i l = 99;
i2 = -10;
126 UNDEIISTIWD FUNCT10N POIN1fRS
output(count);
output (i) ;
return 0:
)
#define JOIN(a, b) a •• b
int main(void)
{
pr i ntf (J'OIN( • one • -two·»;
return 0;
)
I!
return 0;
)
scanf("%d", &Op);
) while(op<O II op>3 ) ;
return 0;
)
i nt subtract(int a, int b)
(
return a-b;
)
int main(void)
(
int sort[lOO], i;
return 0;
)
'" C
EXlRCISfS
void 'bsearch (consl VOid ' key, const void ' array, slze_t number. size_t Size,
Inl (, comp)(const void ' a, const void ' b));
•
All the pa rameters to b search( ) arc the same as for q sort ( )
except the first. \\'hieh is a pOInter to kelj, the object bc:ing
,,,ught. The comp( ) fun, tlon operates the same for bscarch( )
", it does for qsort( ) .
.\lnd;fy the prugraln In L... dlr'pl~ 3 so that anf"r the iiff<-ly is
sOIlPd the tl~er IS prompted to cntpr a number :\'C\t. using
hscarch( ). search the s()rH~d arr.JY and repan ji a nla~ch is
found
3. Add a function call~d modulus( ) to the tinal verSion of the
.nithmctic progranl In Example 2. Ha\'e the functIOn return the
result of a % h . Ada tll1S optIOn to the menu dnd fully integrate
it lnW the p rogcam.
lies hetv,"een your program and the stack. Since this is a finite area, an
illloc.1t1On request can fail when memory is exhausted.
When a program terminates, all allocated memory is automatically
released.
EXAMPLES
exit(l) ;
)
int main(voidl
(
char *p;
p = malloe (80);
ifl!p) (
printf ("Allocation Failed");
exit{l);
)
ret.urn 0;
)
int ma::.n(·,fOid)
(
char .~.
~,
long 1;
1 = 0;
THE C PREPROCESSOR AND SOME ADVANCED TOPICS 401
12. 7 MASTER DYNAMfC ALLOC4 nON
"
do (
p = rnalloc{lOOO);
iElp) 1 += 1000;
} while{p);
:~
return 0;
}
i nt main(vo id )
{
int i;
d ouble *p;
FILE '"fp;
exit(l) ;
}
I '
'f
exit (1);
fclose (fp) ;
return 0;
EXERCISES
'p = mallocllO);
gets (p) ;
,.
408 TEACH YOURSELF
Skills Check
This section checks how well you have integrated the material in
this ch<lptcr with that from "<lrlier ch<lpters.
Demonstrate
, that your macro version works in a program.
3. On your own, look over the programs that you have written in
the course of working through this book. Try to find places
where you can;
.. Use conditional compilation.
• Replace a short function with a f~tion.like macro.
.. Replace statically allocated arrays with dynamic arrays.
... Use function pointers.
4. On your own, study the user's manual or online documentation
for your C compiler, paying special attention to the description
of its standard library functions. The C standard library contains
several hundred library functions that can make your
programming tasks easier. Also, Appendix A in this book
discusses some of the most common library functions.
5. Now that you have finished this book, go back and skim through
each chapter, thinking about how each aspect of C relates to the
rest of it. As you will see, C is a highly integrated language, in
which one feature complements another. The connection
between pointers ahd arrays, for example, is pure elegance.
6. C is a language best learned by doing! Continue to write
programs in C and to study other programmers' programs. You
will be surprised at how quickly C will become second nature!
7. Finally, you now have the necessary foundation in C to a1\ow
you to move on to C++;C'sobject-orientedextension. If C++ .
programming is in your future, proceed to Teach Yoursel{C++,
11~
(Berkeley, CA, Osborne/McGraw-Hill). It picks up where this
book leaves off.
.-
A
Some Common C
Library Functions
411
'f'
412 1tACII YOURSElF
c
The C standard library has a rich and varied set of string- and
character-handling functions. In C, a string is a null-terminated array
of characters. The declarations for the string functions are found in th
header file STRlNG.H. The character functions use CTYPE.H as their
header file.
Because C has no bounds-checking on array operations, it is the
•
programmer's responsibility to prevent an array overflow
_ _ cL_fUIIClIONI .13
AI STRJNG ANa aW!.ocmI FUNCTIONS
"
-......
len~Uli: The character functions are declared with an integer parameter.
~the While this is true, only the low-order byte is used by the function.
~~ Generally, you are free to use a character argument because it will
il.'j automatically be elevated to int at the time of the call.
ttru:\
lil'!dft! *Include <ctype.h>
~tfJ1ntt Int isalnum(i"t ch)i
Example This program checks each character read from stdin and
reports all alphanumeric ones:
.include <ctype.h>
.include <stdio.h>
int main(void)
{
char chi
for ( ; ;) (
ch = getchar()i
if(cn==' ') break;
ifCisalnumCch» printf(-%c is alphanumeric\n-, chI;
)
return OJ
)
*Include <ctype.h>
Int ISJtIpha(int ch)i
'include <ctype.h>
#include <stdio.h>
int main(void)
(
char ch;
fori;;) (
ch = getchar();
if(ch==' ') break;
if(isalpha(ch» printf(-%c is a letter\n-, ch);
)
return 0;
)
#include <ctype.h>
int iscntrl(int ch);
Example This program checks each character read from stdin and
reports all control characters:
#include <ctype.h>
#include <stdio.h>
int main(void)
(
char chi
for!;;) (
ch = getchar();
iflch==' ') break;
if(iscntrl{ch) )
printf(·~c is a control character\n-, ch):
)
return 0;
)
SOME COMMON C ~ RINCYIONS 415
AI STRING AND ClWlACWI FUNCTIONS •
.,
#include <ctype.h>
int isdigit(int ch);
Example This program checks each character read from stdin and
reports all those that are digits:
#include <ctype.h>"
#include <stdio.h>
fori;;) (
ch = getchar () ;
if (ch==' .) break;
if(isdigit(ch» printf(M%c is a digit\n-, ch);
)
return 0;
)
#include <ctype.h>
Int Isgraph(int ch);
int main(void)
{
char chi
418 TEACH YOURSW
c
for (;;) (
ch = getchar();
if(ch==' ') break;
if(isgraph(ch» ,
. printf (·'c is a printing character\n-, ch);
)
return 0;
)
.Include <ctype.h>
int lalower(lnt ch);
EnmpIe This program checks each character read from stdin and
reports all those that are lowercase letters:
'include <ctype.h>
'include <stdio.h>
for (;;) {
ch c getchar () ;
if (c:h=-' .) break;
H(hlO'j>er(chl) printf(·'c is lowercase\n· ,. chI;
)
return 0;
)
jJlndude <ctype.h>
Int IsprintOnt ch);
for ( ; ;) (
ch = getchar () ;
if(ch=='Q') break;
if(isprint(ch» printf(-'c is printable\n-, ch);
)
return 0;
)
.include <ctype.h>
Int Ispunct(lnt 00);
Example This program checks each character read from stdin and
reports all those that are punctuation:
.include <ctype.h>
'include <Std10.h>
forI;;) (
ch = getchar();
if(ch==' ') break;
if(ispunct(ch» printf{-'c is punetuation\n-, ch);
}
.1.., TtACHYOURSW
c
return 0;
)
#include <ctype.h>
int isspace(int 00);
bample This program checks each character read from stdin and
reports all those that are whitespace characters:
_include <ctype.h>
.include <stdio.h>
int main(void)
(
char chi
for I; ; I (
ch = getchar();
if{isspace(ch)) printf("\c is . . .1hitespace \n ... chI;
if(ch==' 'J breakj
)
return 0:
)
#include <ctype.h>
int isupper(Jnt ch);
bample This program checks each character read from stdin and
reports all those that are uppercase letters:
#include <ctype.h>
#include <stdio.h>
SOME COMMON C UBRARY FUNcnONS
for I ;; I I
eut,ri ch ;; getchar():
if(ch==' ') break;
if(isupper(ch)) printf("%c is uppercase\n", ch);
}
,·,
1••• return 0;
}
#include <ctype.h>
int isxdigit(int ch);
Example This program checks each character read from stdin and
reports all those (hat are hc,,-adenma\ digits.
•
~include <ctype.h>
#lr".ciude <stdio.h>
int main{vo1d)
(
char eh;
for I ; ; I [
ch ~ getchar () i
if (ch=;;:' ') break;
if(isxdigit(ch» printf("~c is hexadecimal \n-, ch);
}
return 0;
}
420
.., TEACH VOURSELF
C
mnclude <string.b>
char ·stn:8t(char ·""1, const char .str2);
DeIu..,., The strcat{ ) function concatenates a copy of str2 to strl
and tenninates strl with a null. The null terminator originally e nding
slrl is overwritten by the first character of str2. The string str2 is
untouched by the operation. The atrcat( ) func.tion returns strl .
Example Th is program append, the Illst StI mg lead from stdin to the
second . For exampl e. assum ing the user p-nters hello and the re . the
progra m will pr int there hello .
• inc l ude <string.h>
' i nc l u de <stdio.h>
in t ma i n (VOl d )
{
char 51 801. s21801;
strcat(s2. 51);
print f (52) ;
return 0 ;
)
.incIude <string.b>
char °strchr(const char 'str, int ch);
int main(void)
char .p;
p =
strchr( "th~s is a test", ' ');
print f (p) ;
rE>tur-n )
#include <String.h>
int strcmp(const char 'strl, const char 'str2);
Result Meaning
less than a SlrT is less than sIr2
a SlrT is equal to sIr2
greater than a slrT is greater than SIr2
'" C
lE-!.:.urn _.
,\
#include <String.h>
char 'strcpy(char 'str1, const char 'str2);
Example The following code fragment will copy 'hello' into string sir·
C!1ar stt" [80: ;
s!.:.!:"cpy(str, -hello");
#include <string.h>
size_t strlen(const char 'str);
#include <Stdio.h>
char 'strstr(const char 'str1, const char 'str2);
*include <strinq.h>
.include <stdio.h>
lnt main(void)
(
char *Pi
printf (pi:
return 0;
)
.include <string.h>
char °strtok(char ·slrl, con .. char 0str2);
printf(p) ;
do (
P = strtok( '\0', .. Of);
if(pl printf('i's·, pi;
424 TIACII VOURSRF
... C
}whilelp};
return 0;
}
#include <ctype.h>
int tolower(int ch);
#include <ctype.h>
int toupper(int ch);
E MA THEMATICS FUNCTIONS
ANSI C defines several mathematics functions that take double
arguments and return double values. These functions fall into the
following categories:
All the math functions require that the header MATH.H be included
in any program that uses them. In addition to declaring the math
functions, this header defines a macro called HUGE_VAL. If an
operation produces a result that is too large to be represented by a
double, an overflow occurs, which causes the routine to return
HUGE_VAL. This is called a ra>1ge error. For all the mathematics
functions, if the input value is not in the domain for which the
function is defined, a domai>1 error occurs .
." All angles are specified in radians.
#include <math.h>
double acos(double arg);
•
Description The acos( ) function returns the arc cosine of argo The
argument to acos( ) must be in the range -1 through 1; otherwise a
domain error will occur. '.
int rnain(void)
(
double val = -1.0;
do (
printf(~arc cosine of %f is %f\n". val, acos(val);
va l +:-; 0.1;
} while(val<=l,O);
return 0;
}
#inclUde <math.h>
double asin(double arg);
Description The asin( ) function returns the arc sine of argo The
argument to asin( ) must be in the range -1 through 1; otherwise a
domain error will occur.
426 TEACH YOURSELF
." C
int main(void)
double va!=-l.O:
do (
printf("arc sine of %f is %f\n", val, asin(val»:
val += 0.1:
} while(val<=1.0);
return 0;
}
#include <math.h>
double atan(double arg);
int main(void)
(
double val=-l.O;
do (
printf("arc tangent of %f is %f\n-, val. atan(val» i
val += 0.1;
} while(val<=1.0);
return 0;
SOME COMMON C LIBRARY FUNCTIONS 427
A2 THE MATHEMATICS FUNCTIONS
"
#include <math.h>
""
~,
....
.~
double atan2(double y, double x);
int main(void)
(
double y=-l.O;
do (
printf(".;I,tan2 of %f is %f \ n", y, atan2(y, 1.0»;
y += 0.1;
} while{y<=1.0);
, -. return 0;
I ~
}
•
#include <math.h>
double ceil (double num);
ftlnclude <math.h>
double cos(double erg);
Dat:IfptIon The cos( ) function returns the cosine of argo The value
of arg must be in radians.
do (
printf( · cosine of %f is %£ \ n-, val. cos{val»:
val += 0.1;
) while(val<=l.O);
return 0;
}
•
ftinc:lude <math.1I:;>
double cosh(double erg);
do (
print£(-hyperbolic cosine of \f is %£\n-, val . cosh{val
val += 0 . 1;
/
SOME COMMON C UBAARY FUNcnONS 429
~
A2 THE MATHEMAnCS FUNGnONS
) whilelval<=l.O);
return 0;
)
#include <math.1I>
•
double exp(double arg);
#include <math.1I>
double fabs(double nurn);
Example This program prints the numbers 1.0 1.0 on the screen:
.include <math.h>
.include <stdio.h>
int main{void)
(
printfl·%1.lf %1.lf·, fabsl1.0) , ' fabsl-1.0»;
return 0;
)
#include <math.1I>
double floor(double nurn);
#include <math.1I>
double log (double num);
Example This program prints the natural logarithms for the numbers
I through 10:
#include <math.h>
#include <stdio.h>
int main(void)
{
double val=l.O;
do {
printf ("%f %f\n", val. log (val» ;
val++;
} while(val<11.0);
return 0:
)
#include <math.1I>
double log10(double num);
Example This program prints the base 10 logarithms' for the numbers
I through 10:
#include <math.h>
#include <stdio.h>
,
SOME COMMON C UBRARY FUNCTIONS 431
A2 THE MATHEMAnCS FUNcnONS
do (
printf(·%f %fln·, val, loglO(val»;
val++;
} while(val<11.0);
return 0;
)
#include <math.h>
double pow(double base, double exp);
•
Description The pow( ) function returns b(lSe raised to the exp power
e
(base ,/). A domain error may occur if base is 0 and e,<p is less than or
equal to O. A domain error will occur if base is negative and exp is not
an integer. An overflow produces a range error.
do (
printf{-%f· pow(x, y»);
y++:
} while{y<ll);
return 0;
)
#include <math.h>
double sin(double arg);
Description The sine ) function returns the sine of argo The value of
arg must be in radians.
432 1IACH YOURSELF
" c
int rnain(void)
{
double val=-l.O;
do (
printf(-sine of %f is %£\n-, val, sin(val»;
val += 0.1;
} while(val<=l.O):
return 0:
}
#include <rnath.h>
double sinh(double arg);
do [
printf(-hyperbolic sine of %f is %£\n-, val, sinh(val»i
val += 0.1;
} while(val<=l.O):
return 0;
}
#include <math.h>
double sqrt(double num);
#include <math.h>
double tan(double 8rg);
Description The tan( ) function returns the tangent of argo The value
of arg must be in radians.
int main(void)
{
double va!=-l.O;
do (
printf(-tangent of %f is %f\n H , val, tan(val»:
val += 0.1;
} while(val<=1.0);
return 0;
}
#include <math.h>
double tanh (double arg);
*include <math.h>
*include <stdio.h>
do (
print f("tanh of %f is %f\n", val, tanh(val»;
-,?-1 += 0.1;
j '""hi Ie (val<=l.0) i
return 0;
}
The time and date functions require the header TIME. H for their
prototypes. This header file also defines four types and two macros.
The type time_t is able to represent the system time and date as a
long integer. This is called the calendar time. The structure type tm
holds date and time broken down into its elements. The tm structure
is defined as shown here:
struct tm {
int tm_sec; /- seconds, 0-61 -/
int tm_min; /- minutes. 0-59 -/
int trn_houri/- hours, 0-23 "/
int tm_mday; /- day of the month, 1-31-/
int tm_man; /- months since Jan, 0-11 -/
int tm-year; /- years from 1900 -/
int tm_wday; /- days since Sunday, 0-6 -/
int
int
tm-yday; /- days since Jan 1, 0-365 ,.-
tm_isdst; /- Daylight Saving Time indicator -/
};
.',..
'-
available. When the date and time are represented in this way, they
are referred tD as broken-down time.
The type c1ock_t is defined the same as time_to The header file
also defines size_to
The macros defined are NULL and CWCKS_PER_SEG.
#include <time.h>
char *asctime{const struct tm ·ptr);
For example:
int main(void)
{
struct tm "ptri
time_t It;
It = time(NULL);
ptr = !ocaltime{<l;
printf(asctime{ptr»;
return 0 i
)
.
438~_F
.include <time.h>
clock_t clock(void);
int main(void)
(
int i;
return 0;
I
.include <time.h>
char ·ctime(const time_t ~me);
function is called. If you wish to save the contents of the string, you
need to copy i~ elsewhere.
&le This program displays the local time defined by the system:
.include <time.h>
.includ~ <stdio.h>
It = tirne(NULLl;
printf {.ctime (&1 t) ) ;
return ai
)
#include <time.h>
double difftime(time_t time2, time_t time1);
Example This program times the number of seconds that it takes for
the empty for loop to go from 0 to 500000.
#include <time.h>
.include <stdio.h>
#include <time.h>
strut tm 'gmtime(const time_t *time);
Example Thi~
program prints both the local time and the Coordinated
Universal Time of the system:
#include <time.h>
#include <stdio.h>
t time (NULL) ;
=
local = localtime(&t);
printf(~Local time and date: %5·, asctime(local»);
coordinated = gmtime(&t l ;
priotf(·Coordinated Universal time and date: %5·,
asctime(coordinated» ;
return 0:
}
#include <time.h>
struct tm 'Iocaltime(const time_t 'time);
Example This program prints both the local time and the Coordinated
Universal time of the system:
#include <tirne.h>
#include <stdio.h>
t = time (NULL) ;
local = loca!time(&t) i
printf(~Local'time and date: %s~, asctime(local));
local = gmtime(&t);
printf(~Coordinated Universal time and date: %5".
asctime(local)) ;
return 0:
}
#include <time.h>
time_t time(time_t ·systime);
Example This program displays the local time defined by the system:
#include <time.h>
#include <stdio.h>
440 TEACH YOURSElF
c
int main{void)
(
struct tm *ptri
time_t It;
It = time(NULL);
ptr = !ocaltime(<);
printf(asctime(ptr» ;
return 0,
)
There are two primary ways a C program can store information in the
main memory of the computer. The first uses global and local
variables-including arrays and structures. In the case of global and
static local variables, the storage is fixed throughout the runtime of
your program. For dynamic local variables, storage is allocated on the
stack. Although these variables are efficiently implemented in C, they
require the programmer to know in advance the amount of storage
needed for every situation. The second way information can be stored
is with C's dynamic allocation system. In this method, storage for
information is allocated from the free memory area (called the heap)
as it is needed. '
The ANSI C standard specifies that the header information
necessary to the dynamic allocation system is in STOLIB.H. In ~is
file, the type size_t is defined. This type is used extensively by the
allocation functions and is essentially the equivalent of unsigned.
#include <stdlib.h>
void 'calloc(size_t num, size_~ size);
float "'get_rnem(void)
(
float "'Pi
p = calloc(lOQ, sizeof(float)};
iflJp) (
p.rintf{-Allocation error - aborting.\n~);
exi t ( 1 ) ;
001 )
C:. return p;
)
#include <stdlib.h>
'iIi1/' void free(void 'ptr);
{
char ·str[lOO];
int i;
return 0;
)
linclude <stdlib.h>
void *malloc(size_t size);
struct addr (
char name (40);
char street (40);
char city(40) ;
char state(3);
r.har zip(lO) ;
SOM£ COMMON C ~ FUNCOONI ..:I
A< DYNAMIC ALLOCATION •
) :
#include <Stdlib.h>
void ·realloc(void ·ptr, size_t size);
int main(void)
(
char *p;
p = malloc(17);
444 _eH VOURSlLf
c
if(!p) (
printf(-Allocation error - aborting.\n");
exit(l);
}
p = realloc(p,lB);
if(!p) (
printf(·Allocation error - aborting.\n");
exit(1) ;
}
printf (p) ;
free (p) ;
return 0;
)
ISCELLANEOUS FUNCTIONS
The functions discussed in this section are all standard functions that
don't easily fit in any other category.
#include <stdlib.h>
void abort(void);
return 0;
}
#include <stdlib.h>
int abs(int num);
int get_abs(void)
(
char num[80];
gets (num) ;
return abs(atoi(num»;
}
#include <stdlib.h>
double atof(const char • str);
-
,"
Description The atof( ) function converts the string pointed to by str
into a double value. The string must contain a valid floating-point
number. If this is not the case, the returned value is O.
The number may be terminated by any character that cannot be
part of a valid floating-point number. This includes whitespace
characters, punctuation (other than periods), and characters other
than 'E' or 'e'. Thus, if atof( ) is called with "lOO.OOHELLO", the value
100.00 will be returned.
.,
448 TIACII YOURSElf
int main(void)
(
char nurnl(80) , nurn2[80);
return 0;
)
#include <stdlib.h>
int atoi(const char ·str);
gets (num2l :
prin~f("The sum is: %d", atoi(numl) + atoi(num2»);
return 0;
)
#include <stdlib.h>
long atol(const char ·str)j
Exemple This program reads two long integer numbers and displays
their sum:
~include <stdlib.h>
#include <stdio.h>
int main(void)
(
char numl{BO), num2{BO);
return 0 ;
)
448 TfACH YOURS£LJ'
c
#include <stdlib.h>
void ·bsearch(const void ·key, const void ·base,
size_t nurn, size_t size,
int(*cornpare)(const void ., const void .));
int main {v o id )
{
char Chi
char *P i
SOME COMMON C UIIWIY FUNCTIOIII
A5 MISCELlANEOUS RJNC7IONS
do (
printfC-Enter a character: -);
scanfC-%c%*c-,&ch);
ch = tolower CchI ;
p = bsearch(&ch, alpha, 26, 1, comp);
if(p) printf('is in alphabet.\n');
else printfC-is not in alphabet.\n");
) while (p) ;
return 0;
)
#include <Stdlib,h>
void exit(int status);
do (
printf (-Enter names (El \n");
printfC"Delete name (D)\n·);
printf(·Print (P)\n");
printf('Ouit (Q)"\n');
) whilellstrchr('EDPQ',toupper(ch)));
if(ch=='Q') exit(O);
return ch:
}
#include <stdlib.h>
long labs(long num);
gets (numl ;
return labs(ato!(num»;
}
#include <setjmp.h>
void longjmp(jmp_buf envbuf, int val);
void f2 (void) ;
int main(void)
(
char first=!;
int i;
printf("! ");
i = setjmp(ebuf);
i f (first) (
first = ! firpt:
f2 () ;
printf{"this will not be printed");
}
printf("%d-, i);
return 0;
}
void f2(void)
{
printf('2 .);
longjmp(ebuf, 3);
}
.include <atdlib.h>
void qsot1(void ·base, size_t num, size_t size,
int("compare)(const void·, const. void"»;
Less than 0
•
If erg I is less than arg2
o If argl is equal to tRg2
Greater than il . If erg I is greater than erg2
&le This program sorts a list of integers and displays the results.
'include <stdlib.h>
'include <stdio.h>
int num[lO}' {
1,3, 6, 5. 8, 7, 9, 6, 2, 0
};
int i:
return 0;
}
*include <stdIIb.h>
Int rand(void);
return 0;
)
#include <Setjmp0h>
int setjmpOmp_buf envbuO;
int main(void)
(
char first=!;
int i;
printflol °1;
i = setjrnp(ebuf);
iflfirstl (
first = !first;
f2 I I;
printf(-this will not be printed-);
)
printfIO%dO,il;
return 0;
)
void f2(void)
(
printfl02 °1;
SOME COMMON C UBIWIY FUNCTIONS
A5 ftl/SCELIANEOUS FUNGnONS
longjmp(ebuf, 3);
)
#include <stdlib.h>
void srand(unsigned seed);
Example This program uses the system time to randomly initialize the
rand( ) function using srand( ):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
return 0;
)
B
C Keyword Summary
457
•
. . . TEACH YOURSELF
" . C
- ' N ERE are 32 keywords that, when combined with the formal
C syntax, form the C language as defined by the ANSI C
standard. These keywords are shown in Table B-1.
All C keywords use lowercase letters. In C, uppercase
and lowercase are different; for instance, else is a keyword,
ELSE is not.
An alphabetical summary of each of the keywords follows:
auto
auto is used to create temporary variables that are created upon entry
into a block and destroyed upon exit. For example:
#include <stdio.h>
'include <conio.h>
.. ~ .
int mainlvoid)
{
fori;;} {
iflgetche(}=='a'} (
auto int t;
return 0;
l
break
break is used to exit from a do, for, or while loop, bypassing the
normal loop condition. It is also used to exit from a switch statement.
An example of break in a loop is shown here :
while Ix<lOO I (
x = get_oew_x ( );
if (kbhit( )) break ; / * key hit on keyboard * /
process (x) i
}
Here, if a key is presse~, the loop will terminate no matter what the
value of x is .
In a switch statement, break effectively keeps program execution
from "falling through" to the next case. (Refer to the switch section for
details.)
case
char
const
The const modifier tells the compiler that the contents of a variable
cannot be changed. It is also used to prevent a function from
modifying the object pointed to by one of its arguments.
460 TlACH YOURSELF
... C
continue
continue is used to bypass portions of code in a loop and forces the
conditional expression to be evaluated. For example, the following
while loop will simply read characters from the keyboard until an sis
typed:
while(ch=getche())
if(ch != ' 5 ' ) continue; j * read another char */
process (chl;
)
The call to process( ) will not occur until ch contains the character s.
default
default is used in the switch statement to signal a default block of
code to be executed If no matches are found in the switch. See the
switch se ction .
do
Th" do loop is one of three loop constructs i!\'ailahJe in C. The geJl('ral
form of the do loop is
do (
. statement block
) while(condition);
If only one statement is repeated, the braces are not necessary, but
they add clarity to the statement. The do loop repeats as long as the
condihon is true.
The do loop is the only loop in C that will always have at least one
iteration because the condition rs tested at the bottom of the loop.
A common use of the do loop is to read disk files. This code will
read a file until an EOF is encol1nte,rcd.
do (
ch = getc (fp) ;
if(!feof(fp)) printf("%c", chl:
while(!feof(fp));
c~-4&l
...
double
double is a data type specifier used to declare double-precision
floating-point variaDles. To declare d to be of type double you would
write the following statement:
double di
else
enum
The enum type specifier is used to create enumeration types. An
enumeration is simply a list of named integer constants. For example,
the following code declares an enumeration called color that consists
of three constants: red, green, and yellow.
#include <stdio.h>
int main(void)
(
c = red;
if (c==red) printf(~is red\n");
return 0;
}
extern
The extern data type modifier tells the compiler that a variable is
defined elsewhere in the program. This is often used in conjunction
with separately compiled files that share the same global data and are
l'nked together. In essence, it notifies the compiler of a variable
without redefining it.
As an example, if first were declared in another file as an integer,
the following declaration would be used in subsequent files:
extern int first;
TEACH YOURSa.F
float
float is a data type specifier used to declare floating-point variables. To
declare f to be of type float you would write:
f loat f;
for
If the statement block is only one statement, the braces are not
necessary .
Although the for allows a number of variations, generally the
l11itialization is used to set a counter variable to its starting value . The
condition is generally a relational statement that checks the counter
variable against a termination value , and the increment increments (or
decrements) the counter value. The loop repeats until the condition
be comes false.
The following code will print hello ten times.
for ( t=O; t<10; t++) printf { ~Hello \ n·);
goto
The goto causes program execution to jump to the label specified in
the goto statement. The general form of the goto is
goto label;
label:
All labels must end in a colon and must not conflict with keywords or
function names. Furthermore, a goto can branch only within the
current function, and not from one function to another.
The following example will prim the message right but not the
message wrong:
goto labl;
printf(~wrong·l ;
labl,
printf ("right");
if
The general form of the if statement is
if(condition) (
statement block 1
) .
else {
statement block 2
}
If single statements are used, the braces are not needed. The else is
optional.
The condition may be any expression. If that expression evaluates to
any value other than 0, then statement block 1 will be executed;
otherwise, if it exists, statement block 2 will be executed.
The following code fragment can be used for keyboard input and to
look for a 'q' which signifies 'quit.'
ch = getche () :
i f (ch=='q') (
printf(~Progr~~ Terminated-}i
exit (0);
)
else proceed( ) ;
int
int is the type specifier used to declare integer variables. For example,
to declare count as an integer you would write
int count;
4&4 T£ACII VOURSEU
c
long
long is a data type modifier used to declare long integer and long
double variables. For example,·to declare count as a long integer you
would write
long int count;
register
The register modifier requests that a variable be stored in the way
that allows the fastest possible access. In the case of characters or
integers, this usually means a register of the cpu. To declare i to be a
register integer, you would write
register int i;
return
The return statement forces a return from a function and can be used
to transfer a value back to the calling routine. For example, the
following function returns the product of its two integer arguments.
int mul(int a, int b)
(
retunJ. a '*b;
)
short
short is a data type modifier used ·to declare small integers. For
example, to declare sh to be a short integer you would write
short int sh;
signed
sizeof
The sizeof keyword is a compile-time operator that returns the length
of the variable or type it precedes. If it precedes a type, the type must
be enclosed in parentheses. For example,
printf (~%d·, sizeof (short int»;
static
The static keyword is a data type modifier that causes the compiler to
create permanent storage for the local variable that it precedes. This
enables the specified variable to maintain its value between function
calls. For example, to declare lase time as a static integer, you would
write
static int last_time;
static can also be used on global variables to limit their scope to the
file in which they are declared.
struct
The struct statement is used to create aggregate data types, called
structures, that are made up of one or more members. The general .
form of a structure is
strue! struct-name {
type member' :
type member2 ;
type member N ;
} variable-list;
" c
switch
The switch statement is C's mUlti-path branch statement. It is used to
route execution in one of several ways. The general form of the
statement is
switchCint-expression) {
case constant I: statement-set I;
break;
case constant2: statement-set 2 ;
break;
typedef
For example, to use the word 'balance' in place of 'float,' you would
write
typedef float balance:
union
union union-name {
type memberT :
type member2 :
type member N ;
: } variable-list;
••• ..,
unsigned
The unsigned type modifier tells the compiler to create a variable that
holds only unsigned (Le ., positive) values. For example, to declare big
to be an unsigned integer you would write
unsigned int big;
void
volatile
The volatile modifier tells the compiler that a variable may have its
contents altered in ways not explicitly defined by the program.
Variables that are c}!anged by the hardware, such as real-time clocks,
interrupts, or other inputs are examples.
while
while(condition) {
statement block
}
469
~
470 TEACH YOURSELF
c
W'NDOWS PROGRAMMING
PERSPfCTlVE
program, you can run them all. Of course, in actuality, most useful
programs will still require some sort of training in order to be used
effectively, but at least this instruction can be restricted to what the
program does, not how the user must interact with it. In fact, much of
the code in a Windows application is there just to support the user
interface.
Before continuing, it must be stated that not every program that
runs under Windows will necessarily present the user with a Windows-
. style interface. It is possible to write Windows programs that do not
take advantage of the Windows interface elements. To create a
Windows-style program, you must purposely do so. Only those
programs written to take advantage of Windows wi1llook and feel like
Windows programs. While you can override the basic Windows design
philosophy, you had better have a good reason to do so, because the
users of your programs will, most likely, be very disappointed. In
general, any application programs you- are writing for Windows should
utilize the normal Windows interface and conform to the standard
Windows design practices.
Windows is graphics-oriented, which means that it provides a
Graphical User Interface (GUI). While graphics hardware and video
modes are quite diverse, many of the differences are handled by
Windows. This means that, for the most part, your program does not
need to worry about what type of graphics hardware or video mode is
being used.
Let's look at a few of the more important features of Windows.
you can make it current, which means putting it on top of all the other
open windows. You can enlarge or shrink a window, or move it about
on the screen. In short, Windows lets you control the surface of the
screen the way you control the items on your desk.
While the'ldesktop' model forms the foundation of the Windows user
interface, Windows is not limited by it. In fact, several Windows
interface elements emulate other types of familiar devices, such as
slider controls, spin controls, property sheets, and toolbars. Windows
gives you, the programmer, a large array of features from which you
may choose those most appropriate to your specific application.
TIlE I/IIOUSE
Windows allows the use of the mouse for almost all control,
selection, and drawing operations. Of course, to say that it allows the
use of the mouse is an understatement. The fact is that the Windows
interface was designed for tile mot/se-it allows the use of the keyboard!
Although it is certainly possible for an application program to ignore
the mouse, it does so only in violation of a basic Windows design
principle.
thing that makes menus valuable is that they are largely automated.
Instead of having to manage menu selection manually in your
program, you simply create a standard menu-Windows will handle
the details for you.
A dialog box is a special window that allows more complex
interaction with the application than that allowed by a menu. For
example, your application might use a dialog box to request a file
name. With few exceptions, non-menu input is accomplished via a
dialog box.
E WIN32 API
the most part, the functions are called by the same name and are used
in the same way. However, even though similar in spirit and purpose,
the two APIs differ because Win32 supports 32-bit addressing while
Winl6 supports only the 16-bit, segmented-memory model. Because of
this difference, several of the older API functions have been widened
to accept 32-bit arguments and return 32-bit values. A few API
functions have had to be altered to accommodate the 32-bit archi-
tecture . API functions have also been added to support preemptive
multitasking, new interface elements, and other enhanced features.
Because modern versions of Windows support 32-bit addressing, it
makes sense that integers are also 32 bits long. This means that types
int and unsigned are 32 bits long, not 16 bits, as is the case for
Windows 3.1. If you want to use a I6-bit integer, it must be declared as
short. Windows provides portable typedef names for these types, as
you will see shortly.
fiGURE C-l System menu icon Title 1\1 inim ize box
The elements of a Maximize box
standard window <;:\o,sebox
...
Border _ _-oj
Vertical
scroll bar
All windows have a border that defines the limits of the window; the
borders are also used when resizing the window. At the top of the
window are several items. On the far left is the system menu icon
(also called the title bar icon). Clicking on this box displays the system
menu. To the right of the system menu icon is the window's title . At
the far right are the minimize, maximize, and close boxes. The client
area is the part of the window in which your program activity takes
place. Most windows also have horizontal and vertical scroll bars that
are used to move information through the window.
WlnMaln(J
WINDOW ClASSES
allocate CPU time as .it sees fit rather than waiting for your
application's time slice to end.)
As you will soon see, Windows programs do not make extensive use
of standard C data types, such as int or char'. Instead, all data types
used by Windows have been typedefed within the WINDOWS.H file
and/or its related files. The WINDOWS.H file is supplied by your
Windows-compatible compiler and must be included in all Windows
programs. Some of the most common types are HANDLE, HWND,
BYTE, WORD, DWORD, UINT, LONG, BaaL, LPSTR, and
LPCSTR. HANDLE is a 32-bit integer that is used as a handle. As you
will see, there are a number of handle types, but they are all the same
size as HANDLE. A handle is simply a value that identifies some
resource. Also, all handle types begin with an H. For exampl.e, HWND
is a 32-bit integer used as a window handle. BYTE is an 8-bit unsigned
character. WORD is a 16--bit unsigned short integer. DWORD is an
unsigned long integer. UINT is a 32-bit unsigned integer. LONG is
another name for long. BOOL is an integer; this type is used to
indicate values that are either true or false. LPSTR is a pointer to a
string, and LPCSTR is a const pointer to a string.
In addition to the basic types described above, Windows defines
several structures. The two that are needed by the skeleton program
are MSG and WNDCLASSEX. The MSG structure holds a Windows
message, and WNDCLASSEX is a struchlre that defines a window
class. These structures will be discussed later in this appendix.
A WINDOWS SKELETON
'" C
.
FIGURE C-2 Window, ')~ .. I..t".. j " f - j-
The window
. produced by the
Windows skeleton
T
As you can see by looking at the program, cbSize is assigned the size
of the WNDCLASSEX structure. The hlnstance field is assigned the
current instance handle as specified by hThislnst. The name of the
window class is pointed to by IpszClassName, which points to the
string "MyWin' in this case. The address of the window function is
.' assigned to IpfnWndProc. No default style is specified, and no extra
information is needed.
All Windows applications need to define a default shape for the
mouse cursor and for the application's icons. An application can define
its own custOln version of these resources or it may use one of the
built-in styles, as the skeleton does. In either case, handles to these
resources must be assigned to the appropriate members of the
WNDCLASSEX structure. To see how this is done, let's begin
with icons.
A modern Windows application has at least two icons associated
with it: one standard size and one smalL The small icon is used when
the application is minimized and it is also the icon that is used for the
system menu. The standard icon is displayed when you move or copy
an application to the desktop. Typically, standard icons are 32 by 32
bitmaps and small icons are 16 by 16 bitmaps. The style of each
icon is loaded by the API function Loadlcon( ), whose prototype is
shown here:
must use NULL for the first parameter and specify one of the
following macros far the second:
The function returns a value that identifies the window class. A TOM
is a typedef that means WORD. Each window class is given a unique
value. /pWClass must be the address of the WNDCLASSEX structure.
CREATIIIG A ""'''DOW
HWND CreateWindow(
LPCSTR IpClassName, 1* name of window class '/
LPCSTR IpWinName,1* title of window '/
DWORD dwStyle, /' type of window '/
int X. int Y.I* upper-left coordinates '/
488 TtACH YOURSElF
'" C
The final part of the skeletal WinMain( ) is the message loop. The
message loop is a part of all Windows applications. Its purpose is to
receive and process messages sent by Windows. When an application
is running, it is continually being sent messages. These messages are
488 TEACH YOURSElF
~
C
stored in the application's message queue until they can be read and
processed. Each time your application is ready to read another message,
it must call the API function GetMessage( ), which has this prototype:
111 MSG, the handle of the window for which the message is intended
is contained in hwnd. All Win32 messages are 32-bit integers, and the
message is contained in message. Additional information relating to
each message is passed in wParam and IParam. The type WPARAM
is a typedeffor UINT, and LPARAM is a typedeffor LONG.
The time the message was sent (posted) is speCified in milliseconds
in the time field.
The pt member will contain the coordinates of the mouse when the
message was sent. The coordinates are held in a POINT structure,
which is defined like this:
typedef struct tagPOINT {
LONG x, y;
) POINT;
E WINDOW FUNCTION
The second function in the application skeleton ,is its window function.
In this case, the function is called WindowFunc( ). but it could have
any name you like. The window function is passed the first four
members of the' MSG structure as parameters. For the skeleton,
the only parameter used is the message itself. However, actual
applications will use the other parameters to this function.
The skeleton'S window function responds to only one message
explicitly: WM_DESTROY. This message is sent when the USer
terminates the program. When this message is received, your program
must execute a call to the API function PostQuitMessage( ). The
argument to this function is an exit code that is returned in
msg.wParam inside WinMain( ). Calling PostQuitMessage()
Ci!uses a WM_QUIT me.ssage to be sent to your application, which
causes GetMessage( ) to return false. thus stopping your program.
Any other messages received by WindowFunc( ) are passed to
Windows, via a call to DefWindowProc( ), for default processing.
This step is necessary because all messages must be dealt with in one
fashion or another.
490 TfACH YIlUASElS
'" C
You may have heard or read about definition files. For 16-bit versions
ofWjndows, such as 3.1, progtams need to have a definition file
associated with them. A definition file is simply a text file that
specifies certain information and settings required by a Windows 3.1
program. However, because of the 32-bit architecture (and other
improvements) of modern versions of Windows, definition files are no
longer needed.
MING CONVENTIONS
-'
Before concluding this appendix, a shan comment on the naming of
functions and variables needs to be made. Several of the variable and
parameter names in the skeleton program and its description probably
seemed rather unusual. This is because they follow a set of naming
con~ntions that was invented for Windows programming by
Microsoft. For functions , the name consists of a verb followed by a
noun . The first character of the verb and noun is capitalized.
For variable names, Microsoft chose to use a rather complex system
of embedding the data type into the name. To accomplish this, a
lowercase type prefix is added to the start of the variable's name. The
name itselfbegins with a capital letter. The type prefixes are 6hown in
Table C-l. Frankly, the use of type prefixes is controversial·and is'not
universally supported. Many Windows programmers use this method,
but many do not . You are free to use any naming convention you like.
LEARN MORE
c
..." lIACIIYOURSaF
C
APTER 1
ERCISES
2 . • include <stdio.h>
num • 1000;
printf(-'d is the value of num-, num};
return 0;
}
ERCISES
2. 'include <stdio.h>
return 0;
}
£RCISES
1. linclude <stdio.h>
scanf("\d", &len);
return 0;
}
2. linclude <stdio.h>
int main(voidl
(
printf(·Number of seconds in a year: .):
printf("\f",' 60.0 • 60.0 • 24.0 • 365.0);
return 0;
}
2. #include <stdio.h>
int main(void)
(
oneIl:
two () ;
·1. --
c
return 0;
)
ERCISES
2. linclude <stdio. h>
return Or
)
int convert(void)
(
int dollar.:
ERCISES
.
1. 'include <stdio.h>
return 0;
}
1. tinclude <stdio.h>
3. 'include <stdio.h>
. . . 1IACH YOURSW'
" C
cups = o_to_c{ounces):
printf{"'d cupS", cups)/
return 0;
}
int o_to_c(int 0)
{
return 0 I 8;
}
. . . . . CHAPTER 2
I
-498
21 EXERCISES ~
return 0;
)
return 0;
)
XERCISES
return 0;
)
ERCISES
1. 'include <stdio.h>
int main(void)
(
int a, b. op;
return 0:
)
return 0;
)
ERCISES
1. linclude <stdio.h>
int main(void)
(
int a, b. op;
if(op==O) ( J* add *J
printf("Enter first number: .);
scanf ("\d", &a);
printf(·Enter second.number: ·)i
scanf("\d", &b),
printf(·'d·, a+b);
)
else { ,- subtract -,
printf,"Enter first number: .);
scanf("'d", &a);
printf("Enter second number: ~);
scanf ("'d", &b);
printf("'d", a-b);
)
return 0;
)
fRelSES
,
1. 'include cstdio.~>
int lIIain(yoid)
(
int i; .
" C
return 0;
}
2. 'include <stdio.h>
return 0:
}
3. iinclude <stdio.h>
int mainevoid)
( :
t
int num, i;
ERCISES
1. 'include <stdio.h>
return 0:
}
MIlt •
• include <stdio.h>
return 0;
}
'include <stdio.h>
return 0;
}
int main(void)
{
a := 1;
a++;
b := ai
b--;
printf ("'d \d", a, b);
return 0;
}
..."
ERCISES
1. .include <stdio.h>
return 0;
)
2. • include <stdio.h>
return 0;
)
ISES
1. The loop prints the numbers 0 through 99.
2. Yes .
•
3. No, the first is true, the second is false.
int 'main(void)
{
int magic; /* mag~c number *'
int guess: ,- user's que •• -,
int i:
magic = 1325:
guess = 0;
if(guess == magic) {
printf(-RIGHT!-):
printf(- %d is the magic number.\n-, magic);
)
else (
printf(- ... Sorry, you're wrong ... -);
if(guess > magic)
printf (- Your guess i . too high. \n-) ;
else printf(- Your guess is too low.\n-);
)
)
return 0;
)
2. 'include <stdio.h>
total = 0:
for (i=rooma: i>O; i--) {
printf('Enter length: '):
Bcanf(-'d-, &len):
" c
return 0;
}
int main(void)
(
int answer, count;
int right, wrong:
right = 0;
wrong = 0:
if(answer == count+count) (
printf ( " Rillht ! " ) ;
..,right++1
}
else (
printf(*Sorry. you're wrong . • );
printf(-The answer is 'd. ., count+count);
wrong.+;
}
}
re.turn 0;
}
5. 'include <stdi6.h>
for(i=l; i<=100; i •• ) (
printf("'d\t", i);
-1107
REVIEW SJ(JLLS CHECK ~
iflli%5)==0) printfl"'n");
)
return 0:
)
APTER 3
W , SKILLS, CHECK
1, C's relational and logical operators are <, >, < =, > =, ! =, = =,
I, &&, and II,
2, A block of code is a group oflogically connected statements, To
make a block, surround the statements with curly braces,
3, To output a newline, use the \n backslash character code,
4. #include <stdio.h>
int main(void)
1
int i;
return 0:
)
5 . • include <stdio.h>
'" C
return 0;
}
6. count++;
/* or */
++count;
ERCISES
1. 'include <stdio.h>
'include <conio.h>
printf(·Enter 10 letters.\n-);
return 0;
)
2. 'include <stdio.h>
printf(~'n");
return 0;
}
ERCISES
1. The else relates to the first if; it is not in the same block as
the second.
2 .• include <stdio.h>
if(ch=='C') (
printf(-Enter radius of circle: -);
scanf(-'f-, .radius);
print£(-Area is: 'f-, 3.1416*radius*radius);
}
else it(ch.~'S') (
printf("Enter length of first ~ide: ");
scanf(-'d-, &sl);
printf(-Enter length of •• cond side: -);
Icanf(-'d-, &82);
printf("Area i.: 'do, al-.2);
}
elaeif(ch=='T') (
printf("Enter length of baa.; ");
acanf{-'d-, &al);
printf("Enter height: ");
scanf("'d", ~s2);
printf("Area is: 'do, (al-.2}/2);
}
~-,
c
return 0;
}
XERCISES
,
1. #include <stdio.h>
• return 0;
}
2. 'include <stdio.h>
fore ; i: i--)
3 .• include <stdio.h>
int main(void)
(
int i;
return 0;
}
•
1. 'include <stdio.h>
while (nurn) (
printf(-\nEnter distance: .);
scanf ("\t", &dist) I.
•
printf(~Enter average speed: -)~
scanf (-'f-, &speed);
num--;
}
return 0;
}
2. tinclude c'stdio. h.
'include <conio.h>
·,2
.,
ch = getche();
while(ch!='\r') (
printf(-'t-, ch-l);
ch = getche () ;
I
return 0;
} •
ERCISES
1. UDelude <stdio. h>
dol
printf("Liters: 'f\n", gallons·3.7854);
} while(gallons!=O);
return 0:
I
int main('lOid)
{
int choice;
do (
printf(-Enter the number of the choice (1-5): .);
scanf(·'d-, &choice);
} while(choice<1 I I choice>5);
return 0;
)
s
1. /* This program finds the prime numbers from
2 to 1000.
"I
tinclude <stdio.h>
int main(void)
(
int i, j, prime;
return 0;
)
2. 'include <stdio.h>
'include <conio.h>
int rnain(void)
(
int i:
char chi
.,
&14 TEACH YOURSElF
return 0;
}
XERCISES
return 0;
}
ERCISES
1. .include <8tdio.h>
return 0;
)
XERCISES
int main(void)
(
char ch;
int digit, punc, letter;
digit = 0;
punc = 0;
letter = 0;
do (
ch = getche () ;
switchCch) (
case '1' !
case • 2' !
case • 3' :
case '4' :
case ' 5 • :
case '6' :
case • 7' !
case • 8' :
case '9' :
case • O· :
digit++;
break;
case , , .
case , , , ..
case .? :
case • ! • :
·
case ...
- ._- -"'"
case 'i':
punc+-+;
break;
default:
letter+"';
)
while(ch!=' \ r') ;
printf(- \ nDigits: %d \ n-, digit) i
printf(-Punctuation: %d\n-, punc);
printf{-Letters: %d\n-, let~er);
return 0;
)
ERCISES
I. #include <stdio.h>
int main(void)
int i;
i = 1;
jump_label,
if(i>=11) goto done_label:
printf(-'d -, il;
i+-+;
goto jump_label;
done_label: printf{-Done-);
return 0;
)
1. #include <stdio.h>
#include <conio.h>
int main(void)
{
char Chi
- .&17
MAS1!RY SKJLLS CHECK '"
return 0;
}
2. #include <stdio.h>
int main(voidl
(
int i:
if(!i) printf("zero");
else i£(i<O) printf("negative");
else printf ("positive") i
return 0;
}
5. /* for *1
far(i=1: i<11: i++) printf("td" i):
1* do *1
i = 1:
do {
printf ("M ", i):
i++:
} whileCi<11);
/* while */
i=1:
while (i<11) {
printf("%d" i);
1518 TfACM YOIlRIInF
c
i++;
)
1. #include <stdio.h>
#include <conio.h>
int main(void)
{
char chi
return 0;
)
int rnain(void)
(
int i, j, k;
return 0;
)
APTER ..
1. int i;
forei=1; i<11: i++) printf(-'d to il; -
i = 1;
do {
printfl"%d" i);
i++i
) while ( i<ll);
i ::!: 1 :
while I i<l1l {
printfl"\d" il.
i++;
)
2. switchlchl {
case 'LI! load();
breaK;
case ·s· : save () ;
break;
case • E' ~ enter();
break;
case '0' : display II ;
break;
case 'Q' : quit ();
break;
)
3. 'include <stdio.h>
linclude <conio.h>
&20 T£ACII YOURSELF
~
C
do (
ch = getche{);
} while(ch!='\r');
return 0;
)
do (
printf("Convert \ n\n R ) ;
printf ( -l. feet to meters\n");
printf("2. meters to feet\n"):
printf'-3. ounces to pounds\n - ):
printf(-4. pounds to ounces\n-);
printf("5. Quit\n \ n");
do (
printf("Enter the number of your choice: .);
scanf("'d", &i);
) while(i<D II i>5);
return 0;
}
XERCISES
1. unsigned short int lac_counter ;
2. #include <stdio.h>
printft-Enter distance: .) ;
scanf("'lu·, &distance}:
,return 0;
}
XER·CISES
void soundspeed(void);
double distance;
soundspeed ( ) ;
return 0;
)
void soundspeed(void)
(
printf(·Travel time: 'f", distance I 1129);
)
return 0;
)
ERCISES
return 0 ;
)
3 . #include <stdio.h>
return OJ
)
ERCISES
return 0;
4.6 .-.,'-- .
]. :bn~lu de <stdio.h>
~ - .rn 0;
unsigned
long
short
signed
They are used to modifY the base type so that you can obtain
variables that best fit the needs of your program.
2. To define an unsigned constant, follow the value with a U. To
define a long constant, follow the value with an L. To specifY a
long double, follow the value with an L.
3 . floa.t balance = o. 0;
4. When the C compiler evaluates an expression, it automatically
converts all chars and shorts to into
5. A signed integer uses the high-order bit as a sign flag. When the
bit is set, the ilUm»er is negative, when it is cleared, the number
is positive. An unsigned integer uses all bits as part of the
number and can represent only positive values.
6. Global variables maintain their values throughout the lifetime of
the program. They are also accessible by all functions in the
program.
7. #include <stdio.h>
int series(void);
return 0;
)
int series(void)
{
num = (num'146B) % 467;
return num;
}
1. The fragment is not valid because to C, both 'A' and 65 are the
same thing, and no two case constants can be' the same.
2. The reason that the return value of getc\tar( ) or getche( ) can
be assigned to a char is because C automatically removes the
high-order byte.
3. No. Because i is a signed integer, its maximum value is 32,767.
Therefore, it will never exceed 33,000,
APTER 5
•
3. 'include <stdio.h>
return 0:
}
XERCISES
J. The array count is being overrun. It is only 10 elements long,
but the program requires one that is 100 elementi long.
2 .• include <stdio.h>
printf(-Enter 10 numbers:\n·);
for(j=O; j<lO; j++) 5canf("\d", &i[j]);
,.
U8 TEACH YOUIISllf
return 0;
}
3. *include <stdio.h>
/* read in numbers */
printf(-How many numbers? ·)i
scanf(-'d-, &count);
for{a=O; a<count; a++) scanf{-'f-, &item[a]);
return 0;
}
ANSWERS 529
5.2 EXERCISES
int main(void)
(
char str[BO];
int i;
return 0;
)
2. The string str is not long enough to hold the string 'this is a test".
3. #include <stdio.h>
#include <string.h>
for ( ; ; ) (
printf("Enter a string: ~);
gets (str) ;
if(!strcmp(str, -quit"» break;
strcat (str, "'n") j
/* prevent an array overrun */
if(strlen(bigstr}+strlen(str) >= 1000) break;
strcat(bigstr. str);
)
printf (bigstr) ;
return 0;
)
&eo T£ACH YOURSElf
" C
ERCISES
1. 'include <stdio.h>
int mainevoid)
(
int three_d(3J [3J [3J;
int i. j, k. x;
x = 1;
for(i=O; i<3; i++l
for(j=O; j<3; j++)
for(k=O; k<3; k++) (
three_d[iJ [j) [kJ = Y.;
x++;
printf("%d ", three_d[iJ [jJ [kJ) ;
)
return 0;
J
2. #include cstdio.h>
int main(void)
(
int three_d[3J [3J [3J;
int i, j, k. sum;
ERCISES
int main(vcid)
(
int cube[) [3) = (
1, 1. 1,
2, 4, 8,
3, 9, 27,
4, 16, 64,
5, 25, 125,
6, 36, 216,
7, 49, 343,
8, 64, 512,
9, 81, 729,
10, 100, 1000
) ;
int num, i;
return 0;
)
532 TEACH YOURSElF
• C
EXERCISE S
1 #include <stdio.h>
#include <conio.h>
int rnain(void)
(
char digits[10J [10J = (
Rzero", "one", "two", "three",
"four" "five", "six", "seven",
"eight", "nine"
) ;
char nurn;
num - '0';
TI<L'"":l :::
return 0;
,
inr. main(void)
int statsl201. i. J;
int mode, count, oldcount. oldmode;
oldcount ::: 0;
1* find the mode * /
_533
MASlFRY SKlUS alECK
return 0;
)
5. #include <stdio.h>
#include <string.h~
int main(voJ.d)
(
char str[aO];
do (
printf("Enter a string: M);
gets(str) ;
} while(strcmp("quit-, str»;
return 0;
)
#include <stdio.h>
#include <string.h>
int mal.n(void)
{
ehar diet[) [2) [40) = {
534 TtACIf YOURSW
" c
'* =
i
look up the word */
OJ
/* search,while null string not yet encountered */
while(strcrnp(dict[iJ [0), "" )) (
H(!strcrnp(word. dict[i) [OJ)) {
printf ("meaning: %5·, dict [i] [1 J ) ;
break;
)
i++j
)
H(!strcrnp(dict[i}[OJ. "")
printf(-Not in dictionary\n");
return 0;
)
1. #include <stdio.h>
#include <string.h>
int main(void)
(
char str[80];
int i;
printf(str} ;
return 0;
}
linclude <stdio.h>
"include <string.h:>' ·
/ * code it '*/
1=0 : j = strlen(str) - 1:
whil"e (i<=j) {
if ( i < j) printf("'c%c·, str[i], str[j]) .
else printf ("%c·, str[i}};
i++; j--:
)
return 0;
}
3. linclude <stdio.h>
*include <string.h>
int main(void)
(
char str[80];
int spaces, periods. commas;
int i:
spaces = 0;
commas = 0;
periods = 0;
1lACII YOUIIIIEI.F
return 0;
)
•
4. The getchar( ) function returns a character, not a string.
Hence, it cannot be used as shown. You must use geta( ) to
read a string from the keyboard.
S. /. A simple game of Hangman */
•
'include <stdio.h>
#include <string.h>
do (
printf("'s\n", temp);
printf(·F~ter your guess: .):
ch = getchar () ;
printf("'n"):
printf("'s\n", temp};
printf ("You guessed the word and used %d guesses". count);
•
return 0;
}
APTER 6
1 .• include <stdio.h>
int main(void)
{
int num[lO}. i, even, odd:
even = 0; odd = 0;
for(i=O; i< 10; i++) {
if{num[i]%2} odd = odd + num[i];
else even = even + num(i];
}
return 0;
}
2. #include <stdio.h>
_include <string.h>
int ma.in(void)
{
char pw[BO};
int i;
gets (pw) ;
if(!strcrnp(~Tristan·. pw» break;
)
return 0;
)
3. The array, name, is not big enough to hold the string being
assigned to it.
4. A null string is a string that contains only the null character.
S. The strcpy( ) function copies the contents of one string into
another. The strcmp( ) function compares two strings and
returns less than zero if the first string is less than the second,
zero if the strings match, or gteater than zero if the first string is
greater than the second.
6. /* A Simple computerized telephone book. */
#include <stdio.h>
#include <string.h>
"Ralph", "555-2347".
"Tom". "555-8396",
""
) ;
int main(void)
(
char name[BO);
int i;
printf("Name? ");
gets (name) ;
ERCISES
int main(void)
(
int i. "'P;
p = &i;
return 0;
)
XERCISES
EXERCISES
'" C
3. #include <stdio.h>
•
int main(void)
(
char str(BO). ·Pi
p = str;
printf (p) ;
return 0;
)
XERCISE
I. #include <stdio.h>
int main(void)
(
char ·one = .. one" ;
char "'two = .. two" ;
char ·three = "three" :
return O·,
)
· ANSWERS &41
66 EXERCISE
"
ERCISE
1. jinclude <stdio.h>
#include <string.h>
int main(void)
{
char *p[3] = {
"yes". "no",
"maybe - rephrase the question"
}
char str[80];
printf(p[strlen(str) % 3]):
return 0;
}
1. #include <stdio.h>
int main(void)
(
int i. 'p, **mp;
p = &i;
rnp = &p;
**mp = 10;
printf("%p %p %P", &i, p, mp);
return 0;
}
TEACH YOURSELF
C
ERCISES
1. #include <stdio.h>
#include' <string.h>
int main(void)
{
char str[80};
int main(void)
{
int i;
f I&i I;
return 0;
}
-15113
CUMIJU< 77Vf SJ<1f.LS CHECK ~
2. *include <stdio.h>
p = &i;
*p = 100;
printf("%d", il;
return 0 j
)
*(str+2)
*(p+2)
6. 108
2. iinclude <stdio.h>
gets (str) ;
spaces = 0;
p = str;
while (.p) (
if(*p==' , ) spaces++;
p++ ;
}
return 0;
}
APTER 7
double d. 'p;
p = &d:
'p = 100.99;
return 0;
}
return 0;
}
i = 0:
while{'p) {
i++:
p++;
}
return i:
}
".
WICH YOURSELF
C
XERCISES
1. #include <stdio.h>
double avg();
return 0;
)
double avg ()
{
int i;
double sum, nUID;
sum =
0.0;
for(i=O; i<10: i++) {
printf(-Enter next number: .);
scanf("%lf', &num);
sum = sum + num;
)
return sum I 10.0:
)
2. #include <stdio.h>
double avg(void);
return 0;
}
double avg(void)
{
int i;
double sum, num;
sum = 0.0;
7.2
ANSWERS
EXERCISES
.,
547
1. 'include <stdio.h>
return 0;
)
int factCint i}
(
i£(i==l) return 1;
else return i ,.. fact(i-l):
}
return 0;
548 TEACH YOIJASW'
• C
ERCISES
1. No. The function myfuN:( ) is being called with a pointer to
the first parameter instead of the parameter itself.
2. tinclude <stdio.h>
int main(void)
(
char strI80];
return 0;
)
1. 'include <stdio.h>
'include <string.h>
ANI\1J_
7.4 EXERaSES
tinclude <stdlib.h>
if(argc!=3) {
printf("You must specify two drgurnents . OJ;
exit(l) ;
}
i = strcmp(arqv[ll,
argv[2]);
if(i < 01 printf("'s > %5", argvl2}, argvlll I;
else if(i > 0) printf(-'s > %5·, argv[l], argv[2);
else printf(-They are the same-);
return 0:
}
2. 'include <stdio.h>
'include <string.h>
'include <itdlib.h>
return 0;
}
3. 'include <stdio.h>
'include <string.h>
'include <stdlib.h>
exit(l);
)
if(!strcmp('add', argv[l]))
printf("f', atof(argv[2]) + atof(argv[3]));
else if(!strcmp('subtract', argv[l]))
printf("f', atof(argv[2]) - atof(argv[3]));
else if(!strcmp('multiply', ArgYll]))
printf("f', atof(argv[2]) • atof(argv[3]));
if(!strcmp('divide', argv[l]))
prirtf("f', atof(argv[2]) I atof(argv[3]));
return 0;
J
ERCISE
1. _include <stdio.h>
return 0;
J
-
M.<STERY SKJUS CHECK
..,
•
return 0;
S. 'include <stdio.h>
linclude <stdlib.h>
ifCargc!=2) {
printfC·You need to specify a string·);
exit(l);
}
p " argv(l);
whileC*p) {
printf{-'c·, (*p)+l);
p++;
}
return 0;
)
return 0;
)
ANSWERS 553
CUMUlATIVE SlQLLS CHECK
2. *include <stdio.'h>
• include <ctype.h>
int main(void)
(
char str [) = "this is a test" ;
string_up (str) ;
printf (str);
return 0;
)
3 . • include <stdio.h>
int main(void)
(
double nums[) = (1.0. 2.0. 3.0. ~.O. 5.0.
6.0. 7.0. ' 8.0. 9.0. 10.0);
avg(nums. 10);
return 0;
)
temp = nurn-1;
HAPTER 8
int main(void)
(
printf("%f-, hypot(12.2, 1!f.21);
return 0;
)
h = 51*s1 + 52*52;
return sqrt (h) ;
)
555
B. 1 EXERCISES
...
return 0;
)
6. #include <stdio.h>
return 0;
)
ERCISES
1. #include <stdio.h>
#Qefine COUNTBY 3
return 0;
)
XERCISES
1. #include <stdio.h>
int main(void)
{
int i;
do {
i = getchar ( ) ;
if(i~=EOF) (
printf(-Error on input.-);
break;
)
if(putchar('. ')~~EOF) (
printfC-Error on output.-);
break;
)
) while ( (char) i 1~ '\n');
return 0;
)
-
as EXEIICISES
.,
557
1. 'include <conio.h>
'include <stdio.h>
ch ~ getch I ) ;
printfl"'d", chI;
ret.urn OJ
)
2. 'include <stdio.h>
'include <conio.h>
return 0;
)
RCISES
•
2. No. The program is incorrect because gets{ ) must be called
with a pointer to an actual array.
RCISES
1. 'include <stdio.h>
int main(void)
(
558
"
unsigned long i;
return 0;
}
3. printf("%.2f", 1023.03};
ERCISES
,
1. .include <stdio.h>
return 0;
}
2. #include <stdio.h>
int main(void)
{
char nwnI80];
return 0;
}
int main(void)
MSt:1US
M4S7FRY SKlUS alECK
.,
5511
(
char ,trIBD);
double d;
int L num;
return 0;
)
5. #include <stdio.h>
int main{void)
(
unsigned u;
return 0;
)
4 .• include <stdio.h>
return 0;
}
int mainlvoid)
(
int i;
for(i=O: i<COUNT;i++)
printf("td ", i);
return 0;
)
1. linclude <stdio.h>
high = 0.0,
low = 1000.0,
team_avg = D.O.
for(i=O: i<9: i++' (
if(b_avg(iJ>high) (
h = i;
high = b_avg(iJ,
)
if (b_avg[i]<low) {
1 = i;
low = b3v9(iJ,
)
team_avg = team_avg+b_avg[i);
)
printf("The high is %s %f\n", name(hJ, b_avg(hJ I ,.
printf("The low is %s %f\n", name(lJ, b_avg(lJI'
printf(·T~e team average is %f", team_avg/9.0l;
return 0:
)
2. Note: There are many ways you could have written this
program. This one is simply representative.
/* An electronic card catalog. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void enter(void):
int main(void)
{
lnt choice;
do (
choice = menu();
switch (choice) (
case 1: enter(); /* enter books */
break;
case 2: author_search(); /* search by author */
break:
case 3: title_search(); ;* search by title */
break:
)
} whileCchoice!=4);
return 0;
}
do (
printfC"Choose your selection: ");
gets (str);
i = atai (str);
printfC"'n") ;
} while(i<l II i>4};
ANSWERS B83
CUMULATIVE SKILLS CHECK
return i;
)
,' }
top = i;
/* Search by author. *j
void author_search (void)
(
char name[80);
int i, found;
printf' -Name: .. );
gets (name) ;
found = 0;
for(i=O; i<top; i++)
if (! strcmp{name. names (i) » (
display 1i) ;
found = 1;
printf I" \n") ;
}
j* Search by title.·;
void title_search (void)
{
char title[BO];
TEACH YOURSW
int i. found;
printf("Title: ");
gets (title);
found = 0;
for(i=O; i<top; i++)
if( !strcmpCtitle, titles[i]» (
display (i) ;
found = 1;
printf("\n") ;
)
ifC!found) printfC-Not Found\n-);
)
APTER 9
int main(void)
{
-- ...•
int i, count;
count 0; =
for(i=2; i<1001; itt)
'if(isprime(i)) {
printf ("%lOd". i);
count++;
if (count==4) (
printfC-\n-);
count = 0;
)
)
return 0;
)
int isprime(int i)
(
int j;
4. 'include <$tdio.h>
, 0:
ret\lrn '
5 . • inol\lde' .s~dio.h>
int main(voi<:l)
{
char str[80};
188 1EACII YOURSn1
• C
return 0:
)
XERCISES
1. #include' <stdio.h>
#include <stdlih.h>
fclose(fp) ;
return 0;
)
2. 'include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int count[26]:
FILE *fp;
char ch:
int i:
whilellch=fgetclfp)) !=EOF) (
ch = toupper(ch);
if(ch>='A' && ch<='Z') count[ch-'A')++;
}
fcloselfp) ;
return 0;
)
3. / * Copy a file. */
#include <stdio.h>
.include <stdlib.h>
#include <string.h>
return 0;
) - .
ERCISES
1. #include <stdio.h>
'include <stdlib.h>
unsigned count;
count = 0:
while (! feof (ip» (
fgetc (fp) ;
if (ferror(fp» {
printf (-File error. \n· ) :
exit(l) ;
J
count++ ;
}
return 0;
}
/* copy f1 to temp */
while (! feof (fl» (
ch = fgetc(fl);
if(!feof(fl» fputc(ch, temp);
}
fclose (f1) ;
/* open first file for output *j
if((fl = fopen(argv[1}, "wb"»==NULL) (
pr:ntfC-Cannot open first file.\n-);
exit(!);
}
/* copy £2 to £1 */
while(!feof(f2» (
ch = fge·tc (f2) ;
if(!feof(f2» fputc(ch, £1);
}
fclose(f2);
fclose(temp) ;
1* copy temp to £2 *1
while(!feof(ternp» {
ch = fgetc(temp);
if(!feof,ternp» fputc(ch, f2);
}
571
...
fclose(fl) ;
fclose (f2) ;
fcloseCtemp) ;
return 0;
)
int loc=Di
do (
choice = menu();
switch (choice) {
case 1: enter();
break:
case 2: find();
break;
case 3: save ( ) ;
break:
case 4: load();
J
} while(choice!=5):
return 0;
1IAaIYOURSB.F
C
do (
• printfC"Enter your choice: .);
gets(str);
i = atai (str);
printfC"'n") ;
} while(i<l II i>S};
return i;
}
void enter(void)
{
for(;lec<100; lac++"} {
H(loc<lOO) (
printf("Enter name and phone number:\n");
gets(names[loc]):
if(!*names[loc) break;
gets(numbers[loc);
}
}
}
void find(void)
(
char name[80j;
int i:
if(!strcmp(name, names[i])}
printf(-%s %5\n-, names[i), numbers[i]):
)
loc = 0;
while ( ! feaf (fp» (
fscanf(fp, "%S%5", names [loc] , numbers[loc]);
lac++;
)
fclose (fp) ;
)
2. 'include <stdio.h>
#include <stdlib.h>
'include <ctype.h>
char str[BO];
int count;
count = 0;
while ( ! feof (fp)) (
fgets(str. 79. fp);
printfC-%s", str);
count++;
if (count==23) {
printf ("More? (y\n) .);
gets (str);
if{toupper(*str)=='N') break;
count = 0:
}
}
}
..
fclose(fp) ;
return 0;
if (argc<3) (
printf(nUsage: copy <source> <destination>\n-);
exit(l);
)
if (fclose(from)==EOF) (
printf(~Error closing sourc~ fi1e.\n·);
exit(!) ;
I
if(fcl.ose(to)==EOF) (
printf{"Error closing destination fi1e.\n");
exit(l) ;
I
return 0;
I
ERCISES
d ~ 1.0;
for(i=O; d!=O.O && i<32766; i++) {
printf("Enter a number (0 to quit): .);
scanf("%lf", &d);
fwrite(&d, sizeof d, 1 , fpl);
)
fclose(fp1);
fclose (fp2) ;
return 0;
)
2. #include <stdio.h>
#include <stdlib.h>
idose (£pl) ;
£c1ose(fp2) ;
return OJ
)
ERCISES
1. 'include <stdio.h>
.include <stdlib.h>
if(argc!=2) (
printf(-You must specify the file.\n·);
exit(l);
}
fclose (fp) ;
return 0;
}
2 .• include <stdio.h>
linclude <stdlib.h>
if(argc!=3) {
prin-tf (·Usage: find <filename> <value>-);
exit(l) ;
}
val = atoi(argv[2}};
felose(fp) ;
-878
9.B EXERCISE
.,
return 0:
1
1. #include <stdio.h>
.include <stdlib.h>
linclude <ctype.h>
int main(void)
(
char fname[BO];
return 0;
1
ERCISE
*'
linclude <stdio.h>
int main(void)
{
char Chi
1. 'include <stdio.h>
'include <stdlib.h>
'include <ctype.h>
.
int main(int argc, char -argv[])
(
FILE tip;
char str(BO);
fclose (fp) ;
return 0;
)
return 0;
}
" c
fc10se (fp) ;
return 0;
}
5. 'include <stdio.h>
jinclude <stdlib.h>
int main(void)
(
FILE '*fp;
int i. nurn;
fc 1ose(fp) ;
return 0;
}
6. 'include <stdio.h>
'include <stdlib.h>
int main{void)
{
,
FILE *fp;
long i;
-583
CUMUlATIVE SKIU.S CHECK
"
int num:
fclose 1fp) ;
return 0;
)
do (
choice = menu():
switch (choice) {
case 1: enter(); /* enter books */
break;
case 2: author_search(); /* search by author */
break:
case 3: title_search(); 1* search by, title */
break;
case 4: save();
}
} while(choice!=5);
return 0 i
}
printf{-Card Catalog:\n-);
printf(- 1. Enter\n-):
printf (. 2. Search by author\n·);
printf(" 3. Search . by Title\n");
printf(- 4. Save catalog\n-);
printf(" 5. Quit\n");
do (
printf(·Choose your selection: .);
gets (str) ;
i =
atoi(str);
printf (" \n") ;
} while(i<l II i>5);
return i;
}
___•.
CUMUlATIVE SKlUS CHECK
found: 0;
for(i=O; i<top; i++)
if{ ! strcmp {name, names (i) » {
display (i) ;
found: 1;
printf ( "\n" ) ;
)
j* Search by title. */
void title_search(void)
(
char tit1e[80);
int i, found:
print£(IOTitle: .):
gets(tit1e) ;
...
., TfACH YOURS£lF
C
found = 0;
for(i=O: i<top; i+.)
if(!strcmp(title, titlesli)) (
display (i) ;
found = 1;
printf (" In") ;
)
if(lfound) printf{~Not Found\n-);
)
fclose I fp) ;
}
,
1* save the catalog file. */
void save(void)
(
FILE 'fp;
fclose(fp) ;
)
• c
)
fclose (from) :
fclose (to) ;
return 0;
)
HAPTER 10
1. 1* Copy a file. *1
'include <stdio.h>
#include <stdlib.h>
if(fclose(froM)=~EOF) {
printf (-Error closing source file. \n-);
exit(l);
)
if(fclose(to)·=gQF) (
printf(-Error closin~ destination file.\n-):
exit(l) ;
)
retuI11 0;
)
2. linclude <sedio.h>
'inc1ud$ <stdlib.h>
fclose(fp) ;
return 0;
)
3. #include <stdio.h>
'include <stdlib.h>
int main(vOid)
{
FILE -fPi
int countC20J, i;
/* open file */
if «fp = fopen ("TEMP", "wb"» ==NULL) {
printf (·Cannot open file. \n.) ;
exit(1);
)
fclose (fp) ;
return 0;
)
4. 'include <stdio.h>
.include <stdlib.h>
1* open file */
if({fp = fopen{"TEMP", "rb"»==NULL) (
printf("Cannot open file.\n");
exit (1);
)
fclose(fp) ;
return 0;
)
5. stdin, stdout, and stderr are three streams that are opened
automatically when your C program begins executing. By
default they refer to the console, but in operating systems that
support 110 redirection, they can be redirected to other devices.
6. The printf( ) and scanf( ) functions are part of the C file
system. They are simply special case functions that
automatically use stdin and stdout.
XERCISES
*include <stdio.h>
iinclude <string.h>
.include <stdlib.h>
struct phone_type {
char name (40J ;
int areacode;
char number (9 J ;
) phone (MAXJ ;
int loc=O;
do {
choice = menu ( ) :
switch (choice) (
case 1: enter();
break:
case 2: find () :
break;
case 3: save () :
break;
case 4: load () :
)
) while(choice!=S):
return 0:
)
void enter(void)
{ ,
char temp (80J :
if(!*phone(loc).name) break;
printf(-Enter area code: .);
gets (temp);
phone {loc] .areacode = atoi(temp);
printf!"Enter number: .);
gets (phone [loc] . number) ;
)
)
)
void find{void}
(
char name [801 ;
int i;
loe = 0;
while (! feof (fp» (
fseanf(fp, "'s%d's", phone[loe) . name,
&phone{loc1.areacode. phone[loc] .number);
loc++;
)
felose (fp) :
)
FILE "fp;
int i;
ERCISES
t =time (NULL) ;
systime = localtime(&t);
return 0;
)
ERCISES
struct address {
II char street(40];
char city[40J;
char state[3];
char zip[12J;
) ;
struct phone_type {
char name [40J ;
int areacode;
char number [9] ;
struct address addr;
) phone [MAX] ;
int 10c=0;
do (
choice = menu( );
1tACH YOURSELF
C
switch (choice) {
case 1: enter ( );
break;
case 2: find( );
• break;
case 3: save ( ):
break;
case 4: load( ) ~
)
} while(choice!=5);
return 0;
)
do (
printfC-Enter your choice: .);
gets (str);
i = atoi (str) ;
printf (. \n· ) ;
) while(i<l II i>S);
return i;
•
)
void enter(void)
{
char tempI80];
gets Ctemp) ;
phone{loc] .areacode = atoi(temp);
printfC-Enter number: .);
gets Cphone [locJ .number);
void find(void)
{
char name[80};
int i:
void load(voidl
(
FILE *fPi
void saveCvoid)
(
FILE *fp;
int i;
XERCISES
1. 'include <stdio.h>
int mainCvoid}
(
int a, 3 ;
int b, 3;
int c, 2;
) bvar;
bvar.a =: -1;
bvar.b = 3;
bvar.c = 1;
printfC·'d %d %d-, bvar.a, bvar.b, bvar.c};
return 0;
)
'0.5 EXEIfCIS£S
...
...
ERCISES
1. tinclude <stdio. h>
'include <stdlib.h>
union u_type (
'double d;
unsigned char c [8) ;
) ;
uwriteClOO.23, fp);
d = ureadCfp);
printfC"'lf", d);
return 0;
)
var.d = num;
forli=O; i<8; i++) fputc(var.c{i], fp);
)
rewind (fp) ;
for(i=O; i<8; i++) var.c[iJ = fgetc(fp);
return var.d:
)
2. *include <stdio.h>
int rnain(void)
{
union t_type {
long 1:
lnt i:
} uvar;
,
uvar.l = OL; /* clear 1 */
uvar.i = 100;
printf(~%ld", uvar.l ) ;
return 0:
j
struct s_type {
char name [40 J ;
'!.!<l"""
_ ~S. . .
.,.,.n £!!!
MASIERY SKJUS CI/ECIC ~
return 0;
}
struct s_type {
char name[40l;
char phone[14l;
int hours,
double wage;
) emp[l.O];
802
y
int rnain(void)
(
FILE ·fp;
int ii
fclose (fp) ,
return 0;
J
uvar.i :: 99;
return 0;
}
NJ.aa 80S
CUMUVoTM SK1U.S a£CK ~
1. 'include <stdio.h>
struct B_type {
int i;
char chi
double d;
} var1, var2;
struct_swap(&varl, &var2);
return 0;
}
temp = *i:
*i = *j;
*j =- temp;
)
2. j* Copy a file. *j
'include <stdio.h>
jlinallJl;le <stdlib.b>
,
.-- - - .... 1
, • ••
'" /* open des.tl.llt\tlOll flle *1
.' if «to = fop;'n(argv[2}. "..b" "==NULL) {
printf ("Cannot opell d.e,stin.ation {ile. \n") ;
exit (11;
) ., ,
. ,
,* copy the file
t
"
*' -•
,
Eo'
" for ( ; i ) (
uvar. i = £getc (from) ;
if (uvar.i==EOF) break;
fputc (uvar. ch, to);
• ~ j:;') <> Co
fclose (from) ;
fclose(tol; ,
return 0; •
)
••
',.. "1 -
3. You cannot use a structure as an argument to ·acanf( ).
However, you can use a structure element as an argument, as
shown here.
.
c
scanf("'d·, &var.a):
. ,
\ ... -- --~
s~ruct B_type (
• ,
}
char str(80);
var; 1 • •
U
, ,•
11 • , L
.
return 0;
}
i £
, ,,
APTER 17.
"
,
'1: ,
•, int cu.be:
o 1
• C
nu..(i-l).~ - i·i,
nuaa(i-l).CUbe - i·i·i,
}
return 0,
}
2. 'include <stdio.b>
union i_to_c (
char c(2):
ahort int i:
} ic:
return 0;
)
ERCISES
1. The best variables to make into resIatm" types are k and m,
because they are accessed most frequently.
"NO;I;;.S~.;.; ~
1102 ~
2. linclude <stdio.h>
return OJ
}
XERCISES
1 . linclude <stdio.h>
return 0;
}
2. 'include <stdio.h>
int main(void)
{
'11111111 _I_RIB'
... C
return 0:
)
temp == to;
return temp:
)
ERCISES
,
2. e~um money {penny, nickel. quarter, half_dollar. dollar}:
int rnain(void)
{
UL count;
count = 3~2323;
return 0;
}
RCISES
1. 'includ~ <stdio.h>
'include <stdlib.h>
if(argc!=3) (
printf(-Usage: code <in> <out>\p~);
exit (1);
) .'
if «in = fopen (argv [1] , "rb")) ==NULL) (
printf{-Cannot open input file.\n-);
exit(l);
}
fclose(in) ;
fclose{out) ;
return 0;
}
810
"
if(argc!=4) !
printf(~Usage: code <in> <out> <key>\n-):
eXit(l);
}
fclose (in) ;
fclose (ou t) ;
return 0;
}
3. a. 0000 0001
b. lUI lUI
c. lUI 1101
4. char chi
NISWIIIS 811
• 11.6 EXERCISES
ERCISES
1. linclude <stdio.h>
int main(void)
(
int i, j, k;
j=i«l ;
k. = i » I,
printf("%d doubled, %d\n", i, i);
printf("'d halved, 'dO, i, k);
return 0;
}
2. 'include <stdio.h>
-
void rotatelunsigned char ·e);
int main(void)
(
unsigned char ch;
int i;
ch = 1;
for(i=O: i<16; i++) (
rotate (&ch) ;
printf("'u\n", ch):
}
612 lEACH YOURSELf
" C
return 0:
)
rot.ch[O] = ·c;
'*rot.ushift rot.u
=
integer left
« 1;
*/
XERCISES
1. Itinclude <stdio.h>
int rnain(void)
(
int i. j, answer;
answer = j ? i/j: 0;
printfC"'d", answer);
return 0;
)
2. x &= Yi
3. #include <stdio.h>
int main(void)
(
int i;
return 0;
}
int main(void)
(
int i, j, k;
return 0;
}
2. 3
any variable it precedes may have its value changed in ways not
explicitly specified by the program.
3. ftinclude <stdio.h>
sum = 0;
for(i=l; i<101; i++)
swn = sum i;
return 0;
}
4. Yes, the statement io valid. It creates another name for the ~'pe
long double.
s. 'include <stdio.h>
'include <coniOth>
mask = 1;
forCi=O; i<8; i++) {
i f « ....sk " chI I "" (....sk " ch2 I I
printf("bits td the same\n", il;
mask «= 1;
)
return 0;
}
6. The < < and> > are the left and right shift operators,
respectively.
'~ -- -- ,
A.W\tIERS . , .
C/JMIJlA 77IIE SIOUS CHECK '"
7 . c >= 10;
1. 'include <stdio.h>
ch = 100;
show_binary (ch) ;
t1 = chi
t2 = ch i
tl «= 4:
t2 »= 4;
ch = t1 I t2;
show_binary(ch);
return 0;
}
void show_binar-y(unsigned u)
{
unsigned n;
2 . #include <stdio.h>
'include <8tdlib.h>
i f (argc! =2) (
printf(~Usage: code <in>\n-);
exit(l);
)
fclose (in) ;
return 0:
)
'include <stdio.h>
'include <string.h>
'include <stdlib.h>
atruct address {
char street[40];
char city[40];
-
CUMUlA7l1if SJ(JUS CHECK
817
"
do (
choice ;:: menu () ;
switch(choice) (
case 1: enter{);
break;
case 2: find ( ) ;
break;
case 3: savel);
break;
case 4: load () ;
)
• } while(choice!=5);
return 0;
)
do (
printf(-Enter your choice: .);
gets (str);
i = atoi (str);
printf (" \n") ;
) while(i<l II i>5);
return i;
)
void enter(void)
(
char temp [SO);
char name(80):
register lnt i;
'void load(void)
(
FILE ·fpi
loe = 0;
while ('! feo£ (fp» {
fread(&phone[loc], sizeof phone [loc], 1, £p};
loc++:
)
fclose'(fp) ;
)
void save(voidl
(
FILE *£p;
register int i;
• C
APTER 72
int main(void)
(
int i;
return 0;
)
5. a = b = c = 1;
max = a<b ? 100 0;
i *= 2:
821
y
12.2 EXERCISES
ERCISES
2. #include <stdio.h>
int main(void)
(
printf('%d 'd', ABS(-l), ABS(l));
return 0;
1 •. 2 EXERCISES
1. #include <stdio.h>
#define INT 0
#define FLOAT 1
_define PWR_TYPE INT
int main(void)
(
int e:
#if PWR_TYPE==FLOAT
double base. result;
#elif PWR_TYPE==INT
int base, result;
lendif
.if PWR_TYPE==FLOAT
printf("Enter floating point base: ");
scanf('%lf', &base);
822 TEACH YOURSElf
c
#elif PWR_TYPE==INT
printf{·Enter integer base: .):
scanf ("'d", &base);
iendif
printf("Enter integer exponent (greater than 0): .);
scanf ("'d", &e);
result = 1;
fore; e; e--)
result = result • base:
#if PWR_TYPE==FLOAT
printf("Result: %f-, result);
#elif PWR_TYPE==INT
printf(-Result: %d-, result);
tendif
return 0;
}
2. No. You cannot use an expression like IMIKE with #ifdef. Here
are two possible solutions.
*i fndef MIKE
#endif
/* or */
tend!f
ERCISES
XERCISES
2 . • include <stdio.h>
iinclude <stdlib.h>
int main(void)
(
int sort[lOO), if key;
int ·Pi
return 0;
)
3. iinclude cstdio.h>
return 0;
) ---
int sum(int a, int b)
{
return a ...b;
}
else return 0 i
)
ERCISES
int main(void)
(
int *p, i;
p = malloc(lO*sizeof(int)}:
H(!p) (
printf("Allocation Error");
exit(l);
}
free II') ;
l-eturn 0;
}
3. The statement
'p : malloc (10);
should be
I' : malloc(10);
2. #ifdef DEBUG
if(! (j%2» (
printf (-j = %d\n" , j );
J = 0;
)
#endif
3. _if DEBUG==l
if(!(j%2)) {
pri':1t:fC-j = %d\n" . j 1;
j = 0
}
#endif
int main(voidj
(
printf (str);
ANSWERS 627
CUMULA TlVE SKJUS CHECK
'"
return 0;
}
8. #include <stdio.h>
#include <stdlib.n>
int main(void)
(
double *p;
p =
malloc(sizeof(doublel) i
H(!p} (
printf ("Allocation Error");
exit(l) ;
}
*p == 99.01;
printf("%f", *p);
free (p) :
return 0;
}
I
CUMULA TlVE SKILLS CHECK
struct catalog {
char name [80] ; /' author name ' /
char title[80]; / ' title ' /
char pub[80]; / ' publisher ' /
unsigned date; / ' date of publication ' /
unsigned char ed; '*
edition rl
} ·cat [MAX]; /* notice that this declares a pointer array ,· ,
int main(void)
(
int choice;
do (
choice = menu();
switch (choJ.ce) (
case 1: enter(); / * enter books */
break;
case 2: author_search(): /* search by author
break;
case 3: title_search(); /* search by titl~ ,
break:
case 4: save ( ) ;
}
} while (choice! =5) ;
return 0:
}
do (
printf(-Choose your selection: ·'i
gets (str) ;
i = atai (str);
printf(·\n·) ;
}_waile{i<l II i>S);
return i;
}
/* Sea~cn by author. */
void author_search(void)
. {
630 TlACH YOURSElf
c
printf ("Name: .. ) i
gets (name) ;
found = 0:
forC i=O; i<top; i++)
if(!strcmp(name, cat(i]->name» {
display (i I ;
found = 1;
printf (. \nn);
}
/ * Search by title . • /
void title_search(void)
(
char tHle[80);
int i, found;
printf(~Title: ");
gets (title);
found = 0;
for(i=O; i<top; i++)
if(!strcmp(title, cat[iJ->title» (
display (i) ;
found = 1;
printfC"\n");
}
printfC"%s\n", catCi]->title);
printfC"by %s\n", cat[i)->name);
printf("published by %s\n", cat [i}->publ ;
printfC"Copyright: %u. %u edition\n", cat[i]->date.
cat(i]->ed);
}
ANSWERS 631
CUMULAT1Vf SKlLLS CHECK
fclose(fp) ;
)
fclose(fp) ;
)
2. linclude <stdio.h>
int rnain(void)
(
int ch;
printfC-Enter a character: .);
ch = getchar();
printf("'c coded is 'co , ch, CODE_IT(ch»;
return 0;
)
Index
•
" C
• C
maine) function, 3, 6, 24
K command-line arguments and, 215-220
kbhil( ) function, 236, 237-238 and prototypes, 205-Z06
Keyboard maUce{) function, 403-405, 441, 442-443
inputting numbers from. 15-16 MATH.H header file, 27, 203, 425
reading characters from, 69-74, 233-240 Memory, dynamic allocation of, 402-407, 440
reading strings from, 145-146 Menus, 472-473
Keywords, e, 35-36, 458-468 Message(s)
for basic data types, table of, 10 loop, 477-478, 487-489
and Windows, 473, 477
Microsoft Visual C++, 8, 9, 72
L Modulus operator, 17, 18
Mouse and Windows, 472
Label, 100, 462 MSG structure, 478, 488, 489
labs( ) function, 450 Multitasking and Windows, 474
Library functions, 3-4, 412
dynamic allocation, 440-444
mathematics, 424-434
miscellaneous, 444-455
and prototypes in header files, 203 Naming conventions (Windows), 490
string and character, 412·424 NOT logical operator, 62
time and date, 434-440 NULL Illflcro, 260
#line directive, 389, 390-391, 393 Null
__ LlNE__ macro, 392-393 pointers, 169·170
Loadeursor( ) API function, 484 string, 150
Loadlcon( ) API function, 483-484 terminator, 145
localtime() function, 316-317, 435, 438-439
log( ) function, 430
logIO() function, 430-431
LONG data type, 478
Octal
long type modifier, 107-11 0, 464
constants, specifying, 121
longjmp{ ) function, 450-452, 454
number system, 60, 121
Loops l's complement operator, 358, 359, 360-361
exiting, 89·92
Operator(s)
forcing next iteration of, 92·94
arithmetic, 17, 18
infinite, 81
arrow, 314-315, 330
message, 477, 478
assignment, 12, 367·369
nested,87
bit-shift, 363-364
LPARAM data type, 488
bitwise, 35ft...362
LPeSTR data type, 478
comma, 370--371
LPSTR data type, 478
decrement, 54·56
, LPVOID data type, 486
dot, 302, 314, 315, 330
LRESULT data type, 477
increment, 54-56
logical,61-66
modulus, 17, 18
M precedence of, 372
Macro(s) relational, 41-12, 61·64
built-in (e), 391-393 ternary, 365-367
function-like, 377-378, 379-380, 393-394 unary, 17
substitution, 229-232 OR bitwise operator, 358, 361·362
OR logical operator, 62
63B TEACH YOURSW
" C
"illin~ Ie (h" rlf ( . hi' pro, en plan for .. \\"ork with structures and unioll'i
sdccess bas bnn updated, e'paDded. and ., Explore advanced data tJpt's and opertors
rDhanct'd. There trul~ is no betler \\a~ to learn C. ./ Gain insight into C's preprocessor
" Learn how C can be used to create Windows
"riUm "jth Herb's uncompromising clarit~ and
programs
ant'Dtion 10 dt'lail. I ch \ ur: elf ( hegins" ith
the fUDdamentah. cm er... all the e"'tolials. and Best of all. "ou'lIlearn \\-ilh Schildt's pronn
concluds _hh a 100,," at \ome or(." ~ mo.,t " masterJ"method: the high)) ef1'ectin J"et \'enatiJe
ad~ ... nced reatures. \Iong the \\a~ 3rt' plent~ of a pproach that has helped millions become skilltd
prncticul t:\amp1rs. self-e~alualion c;.ldll checks. programmers. This approach lets JOu "ork at your
and exertisn.. an.'l~\ers to all e\.en'i'll'S are at the 0 "0 pace. in )'our own "3). E\'en if)ou han' found
bad or the book. so _'OU can ea... il~ ~our C confusing in the past. Schildt's clear. paced
prog.-.ss. presentation will make eHn adnnced topics easy
to understand .
Beca use C forms the basis for C++. aOer
Insidl' ~oar \\UJ
completing 1.. 14 1 OU f ( . lOU will ha\'e
., I.earn tbe !l.truclure of a C program the nect'ssar), foundation to ad~'ance to C++ .
'" l ndrrsland each of C\ program conlrol " ·hen it comes to teahing C. Herb schildt has it
statnnent
dOYtn to a science. And in this rnised and updated
." l: umiDt" ebta t~ pt'\. ,' ariable~. and e\.pressions best\ell er. he re~eals the formula that will make
." E_'-plore arra~ '0 and Mrin,::\
lO U a C programmer- the quickest. easiest. and
~ Lam about pointer, most elfecli\"{' wa~ possible!