169 Programming Problems 6.59 Modify the programs given in Examples 6.9,6.12and 6.16 so that each program does the following: a Read in a line of uppercase text, store it in an appro
Trang 1157
How many numbers? 6
We now introduce the comma operator (,) which is used primarily in conjunction with the f o r statement This operator permits two different expressions to appear in situations where only one expression would ordinarily be used For example, it is possible to write
f o r ( expression 7a, expression 7b; expression 2; expression 3 ) statement
where expression l a and expression 7b are the two expressions, separated by the comma operator,
where only one expression (expression I ) would normally appear These two expressions would typically initialize two separate indices that would be used simultaneously within the f o r loop
Similarly, a f o r statement might make use of the comma operator in the following manner
f o r ( expression 7; expression 2; expression 3a, expression 36) statement
Here expression 3a and expression 3b, separated by the comma operator, appear in place of the usual
single expression In this application the two separate expressions would typically be used to alter (e.g., increment or decrement) two different indices that are used simultaneously within the loop For example, one index might count forward while the other counts backward
EXAMPLE 6.32 Searching for Palindromes A palindrome is a word, phrase or sentence that reads the same way
either forward or backward For example, words such as noon, peep, and madam are palindromes If we disregard punctuation and blank spaces, then the sentence Rise to vote, sir! is also a palindrome
Let us write a C program that will enter a line of text containing a word, a phrase or a sentence, and determine whether or not the text is a palindrome To do so, we will compare the first character with the last, the second character with the next to last, and so on, until we have reached the middle of the text The comparisons will include punctuation and blank spaces
In order to outline a computational strategy, let us define the following variables
l e t t e r = a c ha r a c te r-type array containing as many as 80elements These elements will be the characters in
the line of text
t a g = an i n t e g e r variable indicating the number of characters assigned to l e t t e r , excluding the escape character \ Oat the end
count = an i n t e g e r variable used as an index when moving forward through l e t t e r
countback = an integer variable used as an index when moving backward through l e t t e r
f l a g = an i n t e g e r variable that will be used to indicate a true/false condition True will indicate that a
palindrome has been found
l o o p = an i n t e g e r variable whose value will always equal 1, thus appearing always to be true The intent here is to continue execution of a main loop, until a particular stopping condition causes a breakout
Trang 2I58 CONTROL STATEMENTS [CHAP 6
We can now outline our overall strategy as follows
1 Define the symbolic constants EOL (end-of-line), TRUE and FALSE
2 Declare all variables and initialize l o o p(i.e., assign TRUE to loop)
3 Enter the main loop
(a) Assign TRUE to f l a g , in anticipation of finding a palindrome
( 6 ) Read in the line of text on a character-by-character basis, and store in l e t t e r
( c ) Test to see if the uppercase equivalents of the first three characters are E, N and D, respectively If so,
break out of the main loop and exit the program
(6) Assign the final value of count, less I , to tag This value will indicate the number of characters in the line of text, not including the final escape character \0
(e) Compare each character in the first half of l e t t e r with the corresponding character in the second half If
a mismatch is found, assign FALSE to f l a g and break out of the (inner) comparison loop
(f) If flag is TRUE, display a message indicating that a palindrome has been found Otherwise, display a message indicating that a palindrome has not been found
4 Repeat step 3 (i.e., make another pass through the outer loop), thus processing another line of text
Here is the corresponding pseudocode
/ * assign number o f characters i n t e x t t o tag * /
f o r ( ( c o u n t = 0, countback = t a g ) ; count <= ( t a g - 1 ) / 2;(++count, countback)) {
/ * d i s p l a y a message i n d i c a t i n g whether o r not l e t t e r contains a palindrome * /
The program utilizes the comma operator within a f o r loop to compare each character in the first half of l e t t e r
with the corresponding character in the second half Thus, as count increases from 0 to ( t a g - 1) / 2, countback decreases from t a g to ( t a g / 2) + 1 Note that integer division (resulting in a truncated quotient) is involved in establishing these limiting values
Trang 3CHAP 61 CONTROL STATEMENTS 159
Also, observe that there will be two distinct comma operators within the f o r statement Each comma operator and its associated operands are enclosed in parentheses This is not necessary, but it does emphasize that each operand pair comprises one argument within the f o r statement
The complete C program is shown below
p r i n t f ( " P 1 e a s e e n t e r a word, phrase o r sentence b e l o w : \ n " ) ;
f o r (count = 0; ( l e t t e r [ c o u n t ] = g e t c h a r ( ) ) I = EOL; ++count)
Trang 4160 CONTROL STATEMENTS [CHAP 6
P l e a s e e n t e r a word, phrase o r sentence below:
FALSE
FALSE is NOT a palindrome
P l e a s e e n t e r a word, phrase o r sentence below:
PULLUP
PULLUP IS a palindrome
P l e a s e e n t e r a word, phrase o r sentence below:
ABLE W & I ERE I SAW ELBA
ABLE WAS I ERE I SAW ELBA IS a palindrome
P l e a s e e n t e r a word, phrase o r sentence below:
-END
Remember that the comma operator accepts two distinct expressions as operands These expressions will
be evaluated from left to right In situations that require the evaluation of the overall expression (i.e., the expression formed by the two operands and the comma operator), the type and value of the overall expression will be determined by the type and value of the right operand
Within the collection of C operators, the comma operator has the lowest precedence Thus, the comma operator falls within its own unique precedence group, beneath the precedence group containing the various assignment operators (see Appendix C) Its associativity is left to right
be transferred anywhere within the current function We will introduce functions in the next chapter, and
discuss them thoroughly in Chapter 7.) The target statement must be labeled, and the label must be followed
by a colon Thus, the target statement will appear as
Trang 5161
/ * e r r o r d e t e c t i o n r o u t i n e * /
e r r o r c h e c k : {
p r i n t f ("ERROR - NEGATIVE VALUE FOR X " ) ;
In this example control is transferred out of the w h i l e loop, to the compound statement whose label is e r r o r c h e c k , if a negative value is detected for the input variable x
The same thing could have been accomplished using the break statement, as illustrated in Example 6.28 The use of the b r e a k statement is actually the preferred approach The use of the goto statement is presented here only to illustrate the syntax
All of the popular general-purpose programming languages contain a g o to statement, though modern programming practice discourages its use The goto statement was used extensively, however, in early versions of some older languages, such as Fortran and BASIC The most common applications were:
1 Branching around statements or groups of statements under certain conditions
2 Jumping to the end of a loop under certain conditions, thus bypassing the remainder of the loop during the
of the g o t o statement, because the use of goto tends to encourage (or at least, not discourage) logic that skips all over the program whereas the structured features in C require that the entire program be written in an
orderly, sequential manner For this reason, use of the g o to statement should generally be avoided
Occasional situations do arise, however, in which the goto statement can be useful Consider, for example, a situation in which it is necessary to jump out of a doubly nested loop if a certain condition is detected This can be accomplished with two i f - break statements, one within each loop, though this is awkward A better solution in this particular situation might make use of the goto statement to transfer out of both loops at once The procedure is illustrated in the following example
EXAMPLE6.34 Converting Several Lines of Text to Uppercase Example 6.19 presents a program to convert several successive lines of text to uppercase, processing one line of text at a time, until the first character in a new line is
an asterisk (*) Let us now modifL this program to detect a break condition, as indicated by two successive dollar signs
($$) anywhere within a line of text If the break condition is encountered, the program will print the line of text containing the dollar signs, followed by an appropriate message Execution of the program will then terminate
The logic will be the same as that given in Example 6.19, except that an additional loop will now be added to test for two consecutive dollar signs Thus the program will proceed as follows
1 Assign an initial value of 1 to the outer loop index ( l i n e c o u n t )
2 Carry out the following steps repeatedly, for successive lines of text, as long as the first character in the line is
not an asterisk
(a) Read in a line of text and assign the individual characters to the elements of the char-type array l e t t e r
A line will be defined as a succession of characters that is terminated by an end-of-line (i.e, a newline)
designation
( b ) Assign the character count, including the end-of-line character, to t a g
Trang 6162 CONTROL STATEMENTS [CHAP 6
( c ) Display the line in uppercase, using the library function toupper to carry out the conversion Then display two newline characters (so that the next line of input will be separated from the current output by a blank line), and increment the line counter (linecount)
(d) Test all successive characters in the line for two successive dollar signs If two successive dollar signs are detected, then display a message indicating that a break condition has been found and jump to the terminating condition at the end of the program (see below)
3 Once an asterisk has been detected as the first character of a new line, write out "Good bye." and terminate the computation
Here is the complete C program
/ * convert s e v e r a l l i n e s o f t e x t t o uppercase
Continue conversion u n t i l t h e f i r s t character i n a l i n e i s an a s t e r i s k ( * )
Break o u t o f t h e program sooner i f two successive d o l l a r signs ( $ $ ) are detected * /
/ * t e s t f o r a break c o n d i t i o n * /
f o r ( c o u n t = l ; count < tag; ++count)
I $ '
i f ( l e t t e r [ c o u n t - 1 J == && l e t t e r [ c o u n t ] == I $ ' ) { printf('BREAK CONDITION DETECTED - TERMINATE EXECUTION\n\n");
a break condition is encountered, then control is transferred to the final p r i n t f statement ("Good bye') which is now labeled end Note that this transfer of control causes a breakout from the i f statement, the current f o r loop, and the outer
w h i l e loop
You should run this program, using both the regular terminating condition (an asterisk at the start of a new line) and the breakout condition Compare the results obtained with the output shown in Example 6.19
Trang 76.4 Summarize the rules associated with the use of the four relational operators, the
logical connectives and the unary negation operator What types of operands are used with each type of operator?
6.5
6.6
6.7 What is the purpose of the i f
-6.8 Describe the two different forms of the i f
-6.9 Compare the use of the i f -e l s e statement with the use of the 7 : operator In particular, in what way can the 7 operator be used in place of an i f -e l s e statement?
6.10 Summarize the syntactic rules associated with the i f
-6.11 How are nested i f
-i f e7 i f e2 s7
e l s e s2
Which logical expression is associated with the e l s e clause?
6.12 What happens when an expression is encountered whose value is nonzero within a group of nested i f
-statements?
6.13 What is the purpose of the
number of times that a while loop can be executed?
6.14 How is the execution of a
6.15 Summarize the syntactic rules associated with the
6.16 What is the purpose of the do
-6.17 What is the minimum number of times that a do
-explain the reasons for the differences
6.18 Summarize the syntactic rules associated with the do
-6.19 What is the purpose of the fo r statement? How does it differ from the while statement and the do
-statement?
6.20 How many times will a f o r loop be executed? Compare with the while loop and the do
-6.21 What is the purpose of the index in a
6.22 Can any of the three initial expressions in the for statement be omitted? If so,
omission?
6.23 Summarize the syntactic rules associated with the
6.24
6.25 Can loops be nested within i f -e l s e statements? Can i f
-6.26 What is the purpose of the
in this chapter?
6.27
6.28 Summarize the syntactic rules associated with the use of the
associated with one alternative?
6.29 What happens when the value of the expression in the
labels? What happens when the value of this expression does not match any of the case labels?
Trang 8164 CONTROL STATEMENTS [CHAP 6
6.30 Can a default alternative be defined within a s w i t c h statement? If so, how would the default alternative be labeled?
6.31 Compare the use of the s w i t c h statement with the use of nested if- e l s e statements Which is more convenient?
6.32 What is the purpose of the break statement? Within which control statements can the break statement be included?
6.33 Suppose a break statement is included within the innermost of several nested control statements What happens when the break statement is executed?
6.34 What is the purpose of the c o n t i n u e statement? Within which control statements can the c o n t i n u e statement be included? Compare with the break statement
6.35 What is the purpose of the comma operator? Within which control statement does the comma operator usually appear?
6.36 In situations that require the evaluation of an expression containing the comma operator, which operand will determine the type and the value of the entire expression (i.e.y the expression to the left of the comma operator or the expression to the right)?
6.37 What is the precedence of the comma operator compared with other C operators?
6.38 What is the purpose of the g o t o statement? How is the associated target statement identified?
6.39 Are there any restrictions that apply to where control can be transferred within a given C program?
6.40 Summarize the syntactic rules associated with the g o t o statement
6.41 Compare the syntax associated with statement labels with that of case labels (case prefixes)
6.42 Why is the use of the g o t o statement generally discouraged? Under what conditions might the g o t o statement be helpful? What types of usage should be avoided, and why? Discuss thoroughly
Problems 6.43 Explain what happens when the following statement is executed
i f ( a b s ( x ) .Z xmin) x = ( x > 0) 7 xmin : -xmin;
Is this a compound statement? Is a compound statement embedded within this statement?
6.44 IdentifL all compound statements that appear within the following program segment
6.45 Write a loop that will calculate the sum of every third integer, beginning with i=2 (icy calculate the sum 2 + 5 +
8 + 1 1 + - ) for all values of ithat are less than 100 Write the loop three different ways
( a ) Using a w h i l e statement
( 6 ) Using a do -w h i l e statement
(c) Using a f o r statement
Trang 9CHAP 61 CONTROL STATEMENTS 165
6.46 Repeat Prob 6.45 calculating the sum of every nth integer, beginning with the value assigned to n s t a r t (i.e., for
i= n s t a r t , n s t a r t + n , n s t a r t + 2*n, n s t a r t + 3 * n , etc.) Continue the looping process for all values of ithat do not exceed nstop
6.47 Write a loop that will examine each character in a character-type array called t e x t , and write out the ASCII equivalent (i.e, the numerical value) of each character Assume that the number of characters in the array is specified in advance by the integer variable n Write the loop three different ways
( a ) Using a while statement
( b ) Using a do -w h i l e statement
(c) Using a f o r statement
6.48 Repeat Prob 6.47 assuming that the number of characters in the array is not specified in advance Continue the looping action until an asterisk (*) is encountered Write the loop three different ways, as before
6.49 Generalize Prob 6.45 by generating a series of loops, each loop generating the sum of every j th integer, where j
ranges from 2 to 13 Begin each loop with a value of i= 2, and increase iby j until itakes on the largest
possible value that is less than 100 (In other words, the first loop will calculate the sum 2 + 4 + 6 + * -* + 98; the
second loop will calculate the sum 2 + 5 + 8 + - * * + 98; the third loop will calculate the sum 2 + 6 + 10 + - - +
98; and so on The last loop will calculate the sum 2 + 15 + 28 + - * * + 93.) Display the value of each complete
sum
Use a nested loop structure to solve this problem, with one loop embedded within another Calculate each sum with the inner loop, and let the outer loop control the value of j that is used by each pass through the inner loop Use a f o r statement to structure the outer loop, and use each of the three different loop statements ( w h i l e ,
do -w h i l e and f o r ) for the inner loop Develop a separate solution for each type of inner loop
6.50 Write a loop that will generate every third integer, beginning with i= 2 and continuing for all integers that are less
than 100 Calculate the sum of those integers that are evenly divisible by 5 Use two different methods to carry out the test
(a) Use the conditional operator (?:)
( b ) Use an i f -e l s e statement
6.51 Generalize Prob 6.50 by generating every nth integer, beginning with n s t a r t (i.e., i = n s t a r t, n s t a r t + n ,
n s t a r t + 2 * n , n s t a r t + 3*n, etc.) Continue the looping process for all values of ithat do not exceed
nstop Calculate the sum of those integers that are evenly divisible by k, where k represents some positive
integer
6.52 Write a loop that will examine each character in a character-type array called t e x t and determine how many of the characters are letters, how many are digits, how many are whitespace characters, and how many are other kinds
of characters (e.g., punctuation characters) Assume that t e x t contains 80 characters
6.53 Write a loop that will examine each character in a character-type array called t e x t and determine how many of the characters are vowels and how many are consonants (Hint: First determine whether or not a character is a letter; if so, determine the type of letter.) Assume that t e x t contains 80 characters
6.54 Write a switch statement that will examine the value of an integer variable called f l a g and print one of the following messages, depending on the value assigned to f l a g
(a) HOT, if f l a g has a value of 1
( b ) LUKE WARM, if f l a g has a value of 2
(c) COLD, if f l a g has a value of 3
(d) OUT OF RANGE if f l a g has any other value
6.55 Write a switch statement that will examine the value of a char-type variable called c o l o r and print one of the following messages, depending on the character assigned to c o l o r
(a) RED, if either r or R is assigned to c o l o r ,
(b) GREEN, if either g or G is assigned to c o l o r ,
Trang 10166 CONTROL STATEMENTS [CHAP 6
(c) BLUE, if either b or B is assigned to color,
(d) BLACK, if color is assigned any other character
6.56 Write an appropriate control structure that will examine the value of a floating-point variable called temp and print one of the following messages, depending on the value assigned to temp
(a) ICE, if the value of temp is less than 0
(b) WATER, if the value of temp lies between 0 and 100
(c) STEAM, if the value of temp exceeds 100
Can a switch statement be used in this instance?
6.57 Write a f o r loop that will read the characters in a character-type array called text and write the characters backwards into another character-type array called backtext Assume that text contains 80 characters Use the comma operator within the f o r loop
6.58 Describe the output that will be generated by each of the following C programs (Note the similarities in the programs that are shown across from each other.)
( a ) #include estdio h> ( b ) #include estdio h>
Trang 11167
(e) #include <stdio h> U> #include <stdio.h>
Trang 12168 CONTROL STATEMENTS [CHAP 6
Trang 13169
Programming Problems 6.59 Modify the programs given in Examples 6.9,6.12and 6.16 so that each program does the following:
( a ) Read in a line of uppercase text, store it in an appropriate array, and then write it out in lowercase
( 6 ) Read in a line of mixed text, store it in an appropriate array, and then write it out with all lowercase and
uppercase letters reversed, all digits replaced by O S , and all other characters (nonletters and nondigits)
Compare the calculated result with the results obtained for the last problem
6.62 Modify the program given in Example 6.10 so that the size of the list of numbers being averaged is not specified
in advance Continue looping (i.e., reading in a new value for x and adding it to sum) until a value of zero is
entered Thus, x = 0 will signal a stopping condition
6.63 Repeat Problem 6.62 for the program given in Example 6.17
6.64 Rewrite the depreciation program given in Example 6.26 to use the i f -else statement instead of the switch
statement Test the program using the data given in Example 6.26 Which version do you prefer? Why?
6.66 Modify the program given in Example 6.22, which solves for the roots of an algebraic equation, so that the while statement is replaced by a do -while statement Which structure is best suited for this particular problem?
6.67 Modify the program given in Example 6.22, which solves for the roots of an algebraic equation, so that the while
statement is replaced by a f o r statement Compare the use of the f o r , while and do -while statements Which version do you prefer, and why?
6.68 Add an error-trapping routine similar to that given in Example 6.21 to the depreciation program in Example 6.26
The routine should generate an error message, followed by a request to reenter the data, whenever a nonpositive input value is detected
6.69 Write a complete C program for each of the problems presented below Use whatever control structures are most appropriate for each problem Begin with a detailed outline Rewrite the outline in pseudocode if the translation into a working C program is not obvious Be sure to use good programming style (comments, indentation, etc.)
( a ) Calculate the weighted average of a list of n numbers, using the formula
xavg =fi x1 +f2 9 + - - +f&.J
where thef’s are fractional weighting factors, i.e.,
Test your program with the following data:
Trang 14170 CONTROL STATEMENTS [CHAP 6
(6) Determine the roots of the quadratic equation
(see Example 5.6) Allow for the possibility that one of the constants has a value of zero, and that the
quantity b2 -4ac is less than or equal to zero Test the program using the following sets of data:
( e ) The Fibonacci numbers are members of an interesting sequence in which each number is equal to the sum
of the previous two numbers In other words,
Fi = Fi-1 + Fi-2 where Fi refers to the ith Fibonacci number By definition, the first two Fibonacci numbers equal 1; i.e.,
Trang 15171 CONTROL STATEMENTS
Write a program that will determine the first n Fibonacci numbers Test the program with n = 7, n =
1 0 , n = 17andn=23
A prime number is a positive integer quantity that is evenly divisible (without a remainder) only by 1 or by itself For example, 7 is a prime number, but 6 is not
Calculate and tabulate the first n prime numbers (Hint: A number, n, will be a prime if the
remainders of n/2, n/3, n/4, ,n/& are all nonzero.) Test your program by calculating the first 100 prime numbers
Write an interactive program that will read in a positive integer value and determine the following:
( i ) If the integer is a prime number
(ii) If the integer is a Fibonacci number
Write the program in such a manner that it will execute repeatedly, until a zero value is detected for the input quantity Test the program with several integer values of your choice
Calculate the sum of the first n odd integers (i.e., 1 + 3 + 5 + - - - + 2n - 1) Test the program by calculating the sum of the first 100 odd integers (note that the last integer will be 199)
The sine of x can be calculated approximately by summing the first n terms of the infinite series
sinx=x-x3/3! +x5/5! -x7/7! + * *
where x is expressed in radians (Note: 7t radians = 180')
Write a C program that will read in a value for x and then calculate its sine Write the program two different ways:
( i ) Sum the first n terms, where n is a positive integer that is read into the computer along with the
numerical value for x
(ii) Continue adding successive terms in the series until the value of the next term becomes smaller (in magnitude) than 10-5
Test the program for x = 1, x = 2 and x = -3 In each case, display the number of terms used to obtain the final answer
Suppose that P dollars are borrowed from a bank, with the understanding that A dollars will be repaid each month until the entire loan has been repaid Part of the monthly payment will be interest, calculated as i
percent of the current unpaid balance The remainder of the monthly payment will be applied toward reducing the unpaid balance
Write a C program that will determine the following information:
(i) The amount of interest paid each month
( i i ) The amount of money applied toward the unpaid balance each month
(iii) The cumulative amount of interest that has been paid at the end of each month
( i v ) The amount of the loan that is still unpaid at the end of each month
( v ) The number of monthly payments required to repay the entire loan
(vi) The amount of the last payment (since it will probably be less than A)
Test your program using the following data: P = $40,000; A = $2,000; i = 1% per month
A class of students earned the following grades for the six examinations taken in a C programming course
Trang 16172 CONTROL STATEMENTS [CHAP 6
Write an interactive C program that will accept each student’s name and exam grades as input, determine an
average grade for each student, and then display the student’s name, the individual exam grades and the calculated average
Modify the program written for part (k) above to allow for unequal weighting of the individual exam grades In particular, assume that each of the first four exams contributes 15 percent to the final score, and each of the last two exams contributes 20 percent
Extend the program written for part (0above so that an overall class average is determined in addition to the individual student averages
Write a C program that will allow the computer to be used as an ordinary desk calculator Consider only the common arithmetic operations (addition, subtraction, multiplication and division) Include a memory that can store one number
Generate the following “pyramid” of digits, using nested loops
asterisk, preceded by an appropriate number of blank spaces Determine the position of the asterisk by
rounding the value of y to the nearest integer, scaled to the maximum number of characters per line.) Write an interactive C program that will convert a positive integer quantity to a roman numeral (e.g., 12
will be converted to XII, 14 will be converted to XIV, and so on) Design the program so that it will execute repeatedly, until a value of zero is read in from the keyboard
Trang 17173
( r ) Write an interactive C program that will convert a date, entered in the form mm -dd -yy (example: 4- 12-99)
into an integer that indicates the number of days beyond January 1, 1980 If the year does not extend beyond 1999 (i.e., if yy 5 99), we can make use of the following relationships:
( i ) The day of the current year can be determined approximately as
day = ( i n t ) (30.42 * (mm - 1 ) ) + dd
(ii) If mm == 2 (February), increase the value of day by 1
(iii) If mm > 2and mm < 8 (March, April, May, June or July), decrease the value of day by 1
(iv) If yy % 4 == 0 and mm > 2 (leap year), increase the value of day by 1
( v ) Increase the value of day by 1461 for each full 4-year cycle beyond 1-1-80
(vi) Increase day by 365 for each additional full year beyond the completion of the last full 4-year cycle, then add 1 (for the most recent leap year)
Test the program with today’s date, or any other date of your choice
(s) Extend part ( r ) above to accommodate calendar years beyond the year 1999 (Example 10.28 presents a solution to a more advanced version of this problem)
Trang 18Chapter
Functions
We have already seen that C supports the use of library functions, which are used to carry out a number of commonly used operations or calculations (see Sec 3.6) However, C also allows programmers to define their own fhctions for carrying out various individual tasks This chapter concentrates on the creation and utilization of such programmer-defined functions
The use of programmer-defined functions allows a large program to be broken down into a number of smaller, self-contained components, each of which has some unique, identifiable purpose Thus a C program
can be modularized through the intelligent use of such functions (C does not support other forms of modular
program development, such as the procedures in Pascal or the subroutines in Fortran.)
There are several advantages to this modular approach to program development For example, many programs require that a particular group of instructions be accessed repeatedly, from several different places within the program The repeated instructions can be placed within a single function, which can then be accessed whenever it is needed Moreover, a different set of data can be transferred to the function each time
it is accessed Thus, the use of a finction avoids the need for redundant (repeated) programming of the same instructions
Equally important is the logical clarity resulting fiom the decomposition of a program into several
concise functions, where each function represents some well-defined part of the overall problem Such programs are easier to write and easier to debug, and their logical structure is more apparent than programs which lack this type of structure This is especially true of lengthy, complicated programs Most C programs are therefore modularized in this manner, even though they may not involve repeated execution of the same tasks In fact the decomposition of a program into individual program modules is generally considered to be
an important part of good programming practice
The use of functions also enables a programmer to build a customized library of frequently used routines
or of routines containing system-dependent features Each routine can be programmed as a separate function and stored within a special library file If a program requires a particular routine, the corresponding library function can be accessed and attached to the program during the compilation process Hence a single function can be utilized by many different programs This avoids repetitive programming between programs It also
promotes portability since programs can be written that are independent of system-dependent features
In this chapter we will see how functions are defined and how they are accessed from various places within a C program We will then consider the manner in which information is passed to a function Our
discussion will include the use offinction prototypes, as recommended by the current ANSI standard And finally, we will discuss an interesting and important programming technique known as recursion, in which a
function can access itself repeatedly
7.1 A BRIEF OVERVIEW
Afinction is a self-contained program segment that carries out some specific, well-defined task Every C
program consists of one or more fbnctions (see Sec 1.5) One of these functions must be called main
Execution of the program will always begin by carrying out the instructions in main Additional functions will be subordinate to main, and perhaps to one another
If a program contains multiple fhctions, their definitions may appear in any order, though they must be independent of one another That is, one function definition cannot be embedded within another
A function will carry out its intended action whenever it is accessed (i.e., whenever the function is
"called") from some other portion of the program The same function can be accessed from several different
I74
Trang 19do not return anything (as, for example, the library function p r i n t f ) , whereas other functions (e.g., the library function scanf) return multiple values
EXAMPLE 7.1 Lowercase to Uppercase Character Conversion In Example 3.3 1 we saw a simple C program that read in a single lowercase character, converted it to uppercase using the library function toupper, and then displayed the uppercase equivalent We now consider a similar program, though we will define and utilize our own function for carrying out the lowercase to uppercase conversion
Our purpose in doing this is to illustrate the principal features involved in the use of functions Hence, you should concentrate on the overall logic, and not worry about the details of each individual statement just yet
Here is the complete program
/ * c o n v e r t a lowercase c h a r a c t e r t o uppercase using a programmer-defined f u n c t i o n * /
This program consists of two functions-the required main function, preceded by the programmer-defined function
lower-t 0-uppe r Note that lowe r-t o-uppe r carries out the actual character conversion This function converts only lowercase letters; all other characters are returned intact A lowercase letter is transferred into the function via the argument c l , and the uppercase equivalent, c2, is returned to the calling portion of the program (i.e., to main) via the
We will consider the rules associated with function definitions and function accesses in the remainder of this chapter
Trang 20176 FUNCTIONS [CHAP 7
A function defrnition has two principal components: the first line (including the argument declarations), and
the body of the function
The first line of a function definition contains the type specification of the value returned by the function, followed by the function name, and (optionally) a set of arguments, separated by commas and enclosed in parentheses Each argument is preceded by its associated type declaration An empty pair of parentheses must follow the function name if the function definition does not include any arguments
In general terms, the first line can be written as
data- type name( type 1 arg 7, type 2 arg 2, , type n arg n )
where data -type represents the data type of the item that is returned by the function, name represents the function name, and type I,type 2, , type n represent the data types of the arguments arg I , arg 2,
, arg n The data types are assumed to be of type int if they are not shown explicitly However, the omission of the data types is considered poor programming practice, even if the data items are integers
The arguments are called formal arguments, because they represent the names of data items that are transferred into the function from the calling portion of the program They are also known as parameters or formal parameters (The corresponding arguments in the function reference are called actual arguments,
since they define the data items that are actually transferred Some textbooks refer to actual arguments simply
as arguments, or as actual parameters.) The identifiers used as formal arguments are "local" in the sense that
they are not recognized outside of the function Hence, the names of the formal arguments need not be the same as the names of the actual arguments in the calling portion of the program Each formal argument must
be of the same data type, however, as the data item it receives from the calling portion of the program
The remainder of the function definition is a compound statement that defines the action to be taken by
the function This compound statement is sometimes referred to as the boafy of the function Like any other
compound statement, this statement can contain expression statements, other compound statements, control statements, and so on It should include one or more return statements, in order to return a value to the calling portion of the program
A function can access other functions In fact, it can even access itself (this process is known as recursion
and is discussed in Sec 7.6)
EXAMPLE 7.2 Consider the function lower-to-upper, which was originally presented in Example 7.1
The body of the function begins on the second line, with the declaration of the local char-type variable c2 (Note the distinction between the formal argument c l , and the local variable c2.) Following the declaration of c 2 is a statement that tests whether c l represents a lowercase letter and then carries out the conversion The original character is returned intact if it is not a lowercase letter Finally, the r e t u r n statement (see below) causes the converted character to be returned to the calling portion of the program
Trang 21CHAP 71 FUNCTIONS 177
Information is returned from the function to the calling portion of the program via the r e t u r n statement The r e t u r n statement also causes the program logic to return to the point from which the function was accessed
In general terms, the r e t u r nstatement is written as
r e t u r n expression,
The value of the expression is returned to the calling portion of the program, as in Example 7.2 above The expression is optional If the expression is omitted, the r e t u r nstatement simply causes control to revert back to the calling portion of the program, without any transfer of information
Only one expression can be included in the r e t u r n statement Thus, a function can return only one value
to the calling portion of the program via r e t u r n
A function definition can include multiple r e t u r n statements, each containing a different expression Functions that include multiple branches often require multiple returns
EXAMPLE 7.3 Here is a variation of the function lower-to-upper, which appeared in Examples 7.1 and 7.2
This particular function contains two different return statements The first returns an expression that represents the
uppercase equivalent of the lowercase character ;the second returns the original lowercase character, unchanged
The r e t u r n statement can be absent altogether fiom a function definition, though this is generally regarded as poor programming practice If a function reaches the end without encountering a r e t u r n statement, control simply reverts back to the calling portion of the program without returning any information The presence of an empty r e t u r n statement (without the accompanying expression) is recommended in such situations, to clarify the logic and to accommodate future modifications to the function
EXAMPLE 7.4 The following function accepts two integer quantities and determines the larger value, which is then
displayed The function does not return any information to the calling program
Trang 22expressed as an ordinary integer, m v be too large for some computers.)
long int factorial(int n ) / * calculate the factorial of n * /
Notice the long int type specification that is included in the first line of the function definition The local variable
prod is declared to be a long integer within the function It is assigned an initial value of 1, though its value is
recalculated within a for loop The final value of prod, which is returned by the function, represents the desired value of
n factorial
If the data type specified in the first line is inconsistent with the expression appearing in the r e t u r n
statement, the compiler will attempt to convert the quantity represented by the expression to the data type specified in the first line This could result in a compilation error, or it may involve a partial loss of data (e.g., due to truncation) In any event, inconsistencies of this type should be avoided
EXAMPLE 7.6 The following function definition is identical to that in Example 7.5 except that the first line does not include a type specification for the value that is returned by the function
The function expects to return an ordinary integer quantity, since there is no explicit type declaration in the first line
of the function definition However the quantity being returned (prod) is declared as a long integer within the function
This inconsistency can result in an error (Some compilers will generate a diagnostic error and then stop without
completing the compilation.) The problem can be avoided, however, by adding a long int type declaration to the first line of the function definition, as in Example 7.5
The keyword v o i d can be used as a type specifier when defining a function that does not return anything,
or when the function definition does not include any arguments The presence of this keyword is not mandatory, but it is good programming practice to make use of this feature
EXAMPLE 7.7 Consider once again the function presented in Example 7.4, which accepts two integer quantities and displays the larger of the two Recall that this function does not return anything to the calling portion of the program
Therefore the function can be written as
Trang 23A function can be accessed (i.e., called) by specifLing its name, followed by a list of arguments enclosed in
parentheses and separated by commas If the function call does not require any arguments, an empty pair of parentheses must follow the name of the function The function call may be a part of a simple expression (such as anassignment statement), or it may be one of the operands within a more complex expression
The arguments appearing in the function call are referred to as actual arguments, in contrast to the formal
arguments that appear in the first line of the function definition (They are also known simply as arguments,
or as actual parameters.) In a normal function call, there will be one actual argument for each formal
argument The actual arguments may be expressed as constants, single variables, or more complex
expressions However, each actual argument must be of the same data type as its corresponding formal
argument Remember that it is the value of each actual argument that is transferred into the function and
assigned to the corresponding formal argument
If the function returns a value, the function access is often written as an assignment statement; e.g.,
y = polynomial(x);
This function access causes the value returned by the function to be assigned to the variable y
On the other hand, if the function does not return anything, the function access appears by itself; e.g.,
Trang 24When the function is accessed, the value of lower to be transferred to the function This value is represented by c l
within the function The value of the uppercase equivalent, c2, is then determined and returned to the calling portion of the program, where it is assigned to the char-type variable upper
The last two statements in main can be combined to read
p r i n t f ( " \ n T h e uppercase e q u i v a l e n t i s % c \ n \ n " , lower-to-upper(1ower));
The call to lower-to-upper is now an actual argument for the library function p r i n t f Also, note that the variable
upper is no longer required
Finally, notice the manner in which the first line of main is written, i.e., v o i d main ( v o i d ) This is permitted under the ANSI standard, though some compilers do not accept the v o i d return type Hence, many authors (and many programmers) write the first line of main as m a i n ( v o i d ) , or simply main( ) We will follow the latter designation throughout the remainder of this book
There may be several different calls to the same function from various places within a program The
actual arguments may differ from one function call to another Within each function call, however, the actual arguments must correspond to the formal arguments in the function definition; i.e., the number of actual arguments must be the same as the number of formal arguments, and each actual argument must be of the same data type as its corresponding formal argument
EXAMPLE 7.9 Largest of Three Integer Quantities The following program determines the largest of three integer quantities This program makes use of a function that determines the larger of two integer quantities The function is similar to that defined in Example 7.4, except that the present function returns the larger value to the calling program rather than displaying it
The overall strategy is to determine the larger of the first two quantities, and then compare this value with the third quantity The largest quantity is then displayed by the main part of the program
Trang 25Note the two statements in m a i n that access maximum,i.e.,
In the programs that we have examined earlier in this chapter, the programmer-defined function has always
preceded main Thus, when these programs are compiled, the programmer-defined function will have been defined before the first function access However, many programmers prefer a "top-down" approach, in which main appears ahead of the programmer-defined function definition In such situations the fbnction access (within main) will precede the function definition This can be confusing to the compiler, unless the compiler is first alerted to the fact that the function being accessed will be defined later in the program A
finctionprototype is used for this purpose
Function prototypes are usually written at the beginning of a program, ahead of any programmer-defined functions (including main) The general form of a function prototype is
data-type name( type I arg I , type 2 arg 2, , type n arg n ) ;
where data- type represents the data type of the item that is returned by the function, name represents the
function name, and type 7, type 2, ,type n represent the data types of the arguments a r g I , arg 2,
,a r g n Notice that a function prototype resembles the first line of a function definition (though a
function prototype ends with a semicolon)
The names of the arguments within the function prototype need not be declared elsewhere in the program, since these are "dummy" argument names that are recognized only within the prototype In fact, the argument names can be omitted (though it is not a good idea to do so);however, the argument data types are essential
Trang 26182 FUNCTIONS [CHAP 7
In practice, the argument names are usually included and are often the same as the names of the actual arguments appearing in one of the hnction calls The data types of the actual arguments must conform to the data types of the arguments within the prototype
Function prototypes are not mandatory in C They are desirable, however, because they further facilitate error checking between the calls to a function and the corresponding function definition
EXAMPLE 7.10 Calculating Factorials Here is a complete program to calculate the factorial of a positive integer
quantity The program utilizes the function factorial, defined in Example 7.5 Note that the function definition
precedes main,as in the earlier programming examples within this chapter
/ * calculate the factorial of an integer quantity * /
#include <stdio.h>
long int factorial(int n)
/ * calculate the factorial of n * /
/ * calculate and display the factorial * /
printf("\nn! = %Id", factorial(n));
1
The programmer-defined function (factorial) makes use of an integer argument (n) and two local variables-m ordinary integer (i) and a long integer (prod) Since the function returns a long integer, the type declaration long int
appears in the first line of the function definition
Here is another version of the program, written top-down (ie, with main appearing ahead of factorial) Notice
the presence of the function prototype at the beginning of the program The function prototype indicates that a function
called factorial, which accepts an integer quantity and returns a long integer quantity, will be defined later in the
Trang 27long int factorial(int n)
/ * calculate the factorial of n * /
Craps is a popular dice game in which you throw a pair of dice one or more times until you either win or lose The game can be simulated on a computer by generating random numbers rather than actually throwing the dice
There are two ways to win in craps You can throw the dice once and obtain a score of either 7 or 11; or you can
obtain a 4, 5, 6, 8, 9 or 10 on the first throw and then repeat the same score on a subsequent throw before obtaining a 7
Conversely, there are two ways to lose You can throw the dice once and obtain a 2 , 3 or 12; or you can obtain a 4, 5,6, 8,
9 or 10 on the first throw and then obtain a 7 on a subsequent throw before repeating your original score
We will develop the game interactively, so that one throw of the dice will be simulated each time you press the Enter key A message will then appear indicating the outcome of each throw At the end of each game, you will be asked whether or not you want to continue to play
Our program will require a random number generator that produces uniformly distributed integers between 1 and 6
(By uniformly distributed we mean that any integer between 1 and 6 is just as likely to appear as any other integer.) Most
versions of C include a random number generator in their library routines These random number generators typically return a floating-point number that is uniformly distributed between 0 and 1, or an integer quantity that is uniformly distributed between 0 and some very large integer value
We will employ a random number generation routine called rand, which returns a uniformly distributed integer
between 0 and 215 -1 (i.e., between 0 and 32,767) We then convert each random integer quantity to a floating-point number, x, which varies from 0 to 0.99999-* * To do so, we write
x = rand() / 32768.0
Note that the denominator is written as a floating-point constant This forces the quotient, and hence x, to be a floating- point quantity