c语言程序设计现代方法(第二版)习题答案

更新时间:2024-04-10 19:08:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Chapter 2

Answers to Selected Exercises

2. [was #2] (a) The program contains one directive (#include) and four statements (three calls of printf and one return). (b)

Parkinson's Law:

Work expands so as to fill the time available for its completion. 3. [was #4]

#include

int main(void) {

int height = 8, length = 12, width = 10, volume;

volume = height * length * width;

printf(\ printf(\

printf(\

return 0; }

4. [was #6] Here's one possible program: #include

int main(void) {

int i, j, k; float x, y, z;

printf(\ printf(\ printf(\

printf(\ printf(\

printf(\

return 0; }

When compiled using GCC and then executed, this program produced the following output: Value of i: 5618848 Value of j: 0

Value of k: 6844404 Value of x: 3.98979e-34 Value of y: 9.59105e-39 Value of z: 9.59105e-39

The values printed depend on many factors, so the chance that you'll get exactly these numbers is small.

5. [was #10] (a) is not legal because 100_bottles begins with a digit. 8. [was #12] There are 14 tokens: a, =, (, 3, *, q, -, p, *, p, ), /, 3, and ;.

Answers to Selected Programming Projects 4. [was #8; modified]

#include

int main(void) {

float original_amount, amount_with_tax;

printf(\ scanf(\

amount_with_tax = original_amount * 1.05f;

printf(\

return 0; }

The amount_with_tax variable is unnecessary. If we remove it, the program is slightly shorter: #include

int main(void) {

float original_amount;

printf(\ scanf(\

printf(\

return 0; }

Chapter 3

Answers to Selected Exercises 2. [was #2]

(a) printf(\(b) printf(\(c) printf(\(d) printf(\

5. [was #8] The values of x, i, and y will be 12.3, 45, and .6, respectively. Answers to Selected Programming Projects 1. [was #4; modified]

#include

int main(void) {

int month, day, year;

printf(\ scanf(\

printf(\

return 0; }

3. [was #6; modified]

#include

int main(void) {

int prefix, group, publisher, item, check_digit;

printf(\

scanf(\&check_digit);

printf(\

printf(\ printf(\ printf(\

printf(\

/* The five printf calls can be combined as follows:

printf(\code: %d\\nItem number: %d\\nCheck digit: %d\\n\

prefix, group, publisher, item, check_digit); */

return 0; }

Chapter 4

Answers to Selected Exercises

2. [was #2] Not in C89. Suppose that i is 9 and j is 7. The value of (-i)/j could be either –1 or –2, depending on the implementation. On the other hand, the value of -(i/j) is always –1, regardless of the implementation. In C99, on the other hand, the value of (-i)/j must be equal to the value of -(i/j). 9. [was #6] (a) 63 8 (b) 3 2 1 (c) 2 -1 3 (d) 0 0 0

13. [was #8] The expression ++i is equivalent to (i += 1). The value of both expressions is i after the increment has been performed. Answers to Selected Programming Projects 2. [was #4]

#include

int main(void) {

int n;

printf(\ scanf(\

printf(\

return 0; }

Chapter 5

Answers to Selected Exercises 2. [was #2] (a) 1 (b) 1 (c) 1 (d) 1

4. [was #4] (i > j) - (i < j)

6. [was #12] Yes, the statement is legal. When n is equal to 5, it does nothing, since 5 is not equal to –9. 10. [was #16] The output is onetwo

since there are no break statements after the cases. Answers to Selected Programming Projects 2. [was #6]

#include

int main(void) {

int hours, minutes;

printf(\ scanf(\

printf(\ if (hours == 0)

printf(\ else if (hours < 12)

printf(\ else if (hours == 12)

printf(\ else

printf(\

return 0; }

4. [was #8; modified]

#include

int main(void) {

int speed;

printf(\ scanf(\

if (speed < 1)

printf(\ else if (speed <= 3) printf(\ else if (speed <= 27) printf(\ else if (speed <= 47) printf(\ else if (speed <= 63) printf(\ else

printf(\

return 0; }

6. [was #10]

#include

int main(void) {

int check_digit, d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5, first_sum, second_sum, total;

printf(\ scanf(\

printf(\

scanf(\ printf(\ scanf(\ printf(\ scanf(\

first_sum = d + i2 + i4 + j1 + j3 + j5; second_sum = i1 + i3 + i5 + j2 + j4; total = 3 * first_sum + second_sum;

if (check_digit == 9 - ((total - 1) % 10)) printf(\ else

printf(\

return 0; }

10. [was #14]

#include

int main(void) {

int grade;

printf(\ scanf(\

if (grade < 0 || grade > 100) { printf(\ return 0; }

switch (grade / 10) { case 10:

case 9: printf(\ break;

case 8: printf(\ break;

case 7: printf(\ break;

case 6: printf(\ break; case 5: case 4: case 3: case 2: case 1:

case 0: printf(\ break; }

return 0; }

Chapter 6

Answers to Selected Exercises

4. [was #10] (c) is not equivalent to (a) and (b), because i is incremented before the loop body is executed.

10. [was #12] Consider the following while loop: while (…) { …

continue; … }

The equivalent code using goto would have the following appearance:

while (…) { …

goto loop_end; …

loop_end: ; /* null statement */ }

12. [was #14]

for (d = 2; d * d <= n; d++) if (n % d == 0) break;

The if statement that follows the loop will need to be modified as well: if (d * d <= n)

printf(\else

printf(\

14. [was #16] The problem is the semicolon at the end of the first line. If we remove it, the statement is now correct: if (n % 2 == 0)

printf(\

Answers to Selected Programming Projects 2. [was #2]

#include

int main(void) {

int m, n, remainder;

printf(\ scanf(\

while (n != 0) { remainder = m % n; m = n;

n = remainder; }

printf(\

return 0; }

4. [was #4]

#include

int main(void) {

float commission, value;

printf(\ scanf(\

while (value != 0.0f) { if (value < 2500.00f)

commission = 30.00f + .017f * value; else if (value < 6250.00f)

commission = 56.00f + .0066f * value; else if (value < 20000.00f)

commission = 76.00f + .0034f * value; else if (value < 50000.00f)

commission = 100.00f + .0022f * value; else if (value < 500000.00f)

commission = 155.00f + .0011f * value; else

commission = 255.00f + .0009f * value;

if (commission < 39.00f) commission = 39.00f;

printf(\

printf(\ scanf(\ }

return 0; }

6. [was #6] #include

int main(void) {

int i, n;

printf(\ scanf(\

for (i = 2; i * i <= n; i += 2) printf(\

return 0; }

8. [was #8]

#include

int main(void) {

int i, n, start_day;

printf(\ scanf(\

printf(\ scanf(\

/* print any leading \ for (i = 1; i < start_day; i++) printf(\

/* now print the calendar */ for (i = 1; i <= n; i++) { printf(\

if ((start_day + i - 1) % 7 == 0) printf(\ }

return 0; }

Chapter 7

Answers to Selected Exercises

3. [was #4] (b) is not legal.

4. [was #6] (d) is illegal, since printf requires a string, not a character, as its first argument.

10. [was #14] unsigned int, because the (int) cast applies only to j, not j * k.

12. [was #16] The value of i is converted to float and added to f, then the result is converted to double and stored in d.

14. [was #18] No. Converting f to int will fail if the value stored in f exceeds the largest value of type int. Answers to Selected Programming Projects

1. [was #2] short int values are usually stored in 16 bits, causing failure at 182. int and long int values are usually stored in 32 bits, with failure occurring at 46341. 2. [was #8]

#include

int main(void) {

int i, n; char ch;

printf(\ printf(\ scanf(\ ch = getchar();

/* dispose of new-line character following number of entries */ /* could simply be getchar(); */

for (i = 1; i <= n; i++) {

printf(\ if (i % 24 == 0) {

printf(\

ch = getchar(); /* or simply getchar(); */ } }

return 0;

}

5. [was #10]

#include #include

int main(void) {

int sum = 0; char ch;

printf(\

while ((ch = getchar()) != '\\n') switch (toupper(ch)) { case 'D': case 'G': sum += 2; break;

case 'B': case 'C': case 'M': case 'P': sum += 3; break;

case 'F': case 'H': case 'V': case 'W': case 'Y': sum += 4; break; case 'K':

sum += 5; break; case 'J': case 'X': sum += 8; break; case 'Q': case 'Z': sum += 10; break; default:

sum++; break; }

printf(\

return 0; }

6. [was #12]

#include

int main(void) {

printf(\ printf(\

printf(\ printf(\ printf(\

printf(\

return 0; }

Since the type of a sizeof expression may vary from one implementation to another, it's necessary in C89 to cast sizeof expressions to a known type before printing them. The sizes of the basic types are small numbers, so it's safe to cast them to int. (In general, however, it's best to cast sizeof expressions to unsigned long and print them using %lu.) In C99, we can avoid the cast by using the %zu conversion specification.

Chapter 8

Answers to Selected Exercises

1. [was #4] The problem with sizeof(a) / sizeof(t) is that it can't easily be checked for correctness by someone reading the program. (The reader would have to locate the declaration of a and make sure that its elements have type t.)

2. [was #8] To use a digit d (in character form) as a subscript into the array a, we would write a[d-'0']. This assumes that digits have

consecutive codes in the underlying character set, which is true of ASCII and other popular character sets. 7. [was #10]

const int segments[10][7] = {{1, 1, 1, 1, 1, 1}, {0, 1, 1},

{1, 1, 0, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 0, 1}, {0, 1, 1, 0, 0, 1, 1}, {1, 0, 1, 1, 0, 1, 1}, {1, 0, 1, 1, 1, 1, 1}, {1, 1, 1},

{1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1}}; Answers to Selected Programming Projects

2. [was #2]

#include

int main(void) {

int digit_count[10] = {0}; int digit; long n;

printf(\ scanf(\

while (n > 0) { digit = n % 10;

digit_count[digit]++; n /= 10; }

printf (\

for (digit = 0; digit <= 9; digit++) printf(\ printf(\

for (digit = 0; digit <= 9; digit++) printf(\ printf(\

return 0; }

5. [was #6]

#include

#define NUM_RATES ((int) (sizeof(value) / sizeof(value[0]))) #define INITIAL_BALANCE 100.00

int main(void) {

int i, low_rate, month, num_years, year; double value[5];

printf(\ scanf(\

printf(\

scanf(\

printf(\

for (i = 0; i < NUM_RATES; i++) { printf(\ value[i] = INITIAL_BALANCE; }

printf(\

for (year = 1; year <= num_years; year++) { printf(\

for (i = 0; i < NUM_RATES; i++) {

for (month = 1; month <= 12; month++)

value[i] += ((double) (low_rate + i) / 12) / 100.0 * value[i]; printf(\ }

printf(\ }

return 0; }

8. [was #12]

#include

#define NUM_QUIZZES 5 #define NUM_STUDENTS 5

int main(void) {

int grades[NUM_STUDENTS][NUM_QUIZZES]; int high, low, quiz, student, total;

for (student = 0; student < NUM_STUDENTS; student++) { printf(\ for (quiz = 0; quiz < NUM_QUIZZES; quiz++) scanf(\ }

printf(\

for (student = 0; student < NUM_STUDENTS; student++) { printf(\ total = 0;

for (quiz = 0; quiz < NUM_QUIZZES; quiz++) total += grades[student][quiz];

printf(\ }

printf(\

for (quiz = 0; quiz < NUM_QUIZZES; quiz++) { printf(\ total = 0; high = 0; low = 100;

for (student = 0; student < NUM_STUDENTS; student++) { total += grades[student][quiz]; if (grades[student][quiz] > high) high = grades[student][quiz]; if (grades[student][quiz] < low) low = grades[student][quiz]; }

printf(\ }

return 0; }

Chapter 9

Answers to Selected Exercises 2. [was #2]

int check(int x, int y, int n) {

return (x >= 0 && x <= n - 1 && y >= 0 && y <= n - 1); }

4. [was #4]

int day_of_year(int month, int day, int year) {

int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int day_count = 0, i;

for (i = 1; i < month; i++) day_count += num_days[i-1];

/* adjust for leap years, assuming they are divisible by 4 */ if (year % 4 == 0 && month > 2) day_count++;

return day_count + day; }

Using the expression year % 4 == 0 to test for leap years is not completely correct. Centuries are special cases: if a year is a multiple of 100, then it must also be a multiple of 400 in order to be a leap year. The correct test is

year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) 6. [was #6; modified] int digit(int n, int k) {

int i;

for (i = 1; i < k; i++) n /= 10;

return n % 10; }

8. [was #8] (a) and (b) are valid prototypes. (c) is illegal, since it doesn't specify the type of the parameter. (d) incorrectly specifies that f returns an int value in C89; in C99, omitting the return type is illegal. 10. [was #10] (a)

int largest(int a[], int n) {

int i, max = a[0];

for (i = 1; i < n; i++) if (a[i] > max) max = a[i];

return max; }

(b)

int average(int a[], int n) {

int i, avg = 0;

for (i = 0; i < n; i++) avg += a[i];

return avg / n; } (c)

int num_positive(int a[], int n) {

int i, count = 0;

for (i = 0; i < n; i++) if (a[i] > 0) count++;

return count; }

15. [was #12; modified]

double median(double x, double y, double z) {

double result;

if (x <= y)

if (y <= z) result = y;

else if (x <= z) result = z; else result = x; else {

if (z <= y) result = y;

else if (x <= z) result = x; else result = z; }

return result; }

17. [was #14]

int fact(int n) {

int i, result = 1;

for (i = 2; i <= n; i++) result *= i;

return result; }

19. [was #16] The following program tests the pb function: #include

void pb(int n);

int main(void) {

int n;

printf(\ scanf(\

printf(\ pb(n);

printf(\

return 0; }

void pb(int n) {

if (n != 0) { pb(n / 2);

putchar('0' + n % 2); } }

pb prints the binary representation of the argument n, assuming that n is greater than 0. (We also assume that digits have consecutive codes in the underlying character set.) For example: Enter a number: 53 Output of pb: 110101

A trace of pb's execution would look like this:

pb(53) finds that 53 is not equal to 0, so it calls

pb(26), which finds that 26 is not equal to 0, so it calls pb(13), which finds that 13 is not equal to 0, so it calls pb(6), which finds that 6 is not equal to 0, so it calls pb(3), which finds that 3 is not equal to 0, so it calls pb(1), which finds that 1 is not equal to 0, so it calls pb(0), which finds that 0 is equal to 0, so it returns, causing

pb(1) to print 1 and return, causing pb(3) to print 1 and return, causing pb(6) to print 0 and return, causing pb(13) to print 1 and return, causing pb(26) to print 0 and return, causing pb(53) to print 1 and return.

Chapter 10

Answers to Selected Exercises

1. [was #2] (a) a, b, and c are visible. (b) a, and d are visible. (c) a, d, and e are visible. (d) a and f are visible.

Answers to Selected Programming Projects 3. [was #4]

#include /* C99 only */ #include #include

#define NUM_CARDS 5 #define RANK 0 #define SUIT 1

/* external variables */ int hand[NUM_CARDS][2]; /* 0 1 ____ ____ 0 |____|____|

1 |____|____| 2 |____|____| 3 |____|____| 4 |____|____| rank suit */

bool straight, flush, four, three; int pairs; /* can be 0, 1, or 2 */

/* prototypes */

void read_cards(void); void analyze_hand(void); void print_result(void);

/********************************************************** * main: Calls read_cards, analyze_hand, and print_result * * repeatedly. * **********************************************************/ int main(void) {

for (;;) {

read_cards(); analyze_hand(); print_result(); } }

/********************************************************** * read_cards: Reads the cards into the external variable * * hand; checks for bad cards and duplicate * * cards. * **********************************************************/ void read_cards(void) {

char ch, rank_ch, suit_ch; int i, rank, suit;

bool bad_card, duplicate_card; int cards_read = 0;

while (cards_read < NUM_CARDS) { bad_card = false;

printf(\

rank_ch = getchar(); switch (rank_ch) {

case '0': exit(EXIT_SUCCESS); case '2': rank = 0; break; case '3': rank = 1; break; case '4': rank = 2; break; case '5': rank = 3; break; case '6': rank = 4; break; case '7': rank = 5; break; case '8': rank = 6; break; case '9': rank = 7; break; case 't': case 'T': rank = 8; break; case 'j': case 'J': rank = 9; break; case 'q': case 'Q': rank = 10; break; case 'k': case 'K': rank = 11; break; case 'a': case 'A': rank = 12; break; default: bad_card = true; }

suit_ch = getchar(); switch (suit_ch) {

case 'c': case 'C': suit = 0; break; case 'd': case 'D': suit = 1; break; case 'h': case 'H': suit = 2; break; case 's': case 'S': suit = 3; break; default: bad_card = true; }

while ((ch = getchar()) != '\\n') if (ch != ' ') bad_card = true;

if (bad_card) {

printf(\ continue; }

duplicate_card = false;

for (i = 0; i < cards_read; i++)

if (hand[i][RANK] == rank && hand[i][SUIT] == suit) { printf(\ duplicate_card = true; break; }

if (!duplicate_card) {

hand[cards_read][RANK] = rank; hand[cards_read][SUIT] = suit; cards_read++; } } }

/********************************************************** * analyze_hand: Determines whether the hand contains a * * straight, a flush, four-of-a-kind, * * and/or three-of-a-kind; determines the * * number of pairs; stores the results into * * the external variables straight, flush, * * four, three, and pairs. * **********************************************************/ void analyze_hand(void) {

int rank, suit, card, pass, run;

straight = true; flush = true; four = false; three = false; pairs = 0;

/* sort cards by rank */

for (pass = 1; pass < NUM_CARDS; pass++)

for (card = 0; card < NUM_CARDS - pass; card++) { rank = hand[card][RANK]; suit = hand[card][SUIT];

if (hand[card+1][RANK] < rank) {

hand[card][RANK] = hand[card+1][RANK]; hand[card][SUIT] = hand[card+1][SUIT]; hand[card+1][RANK] = rank; hand[card+1][SUIT] = suit; } }

/* check for flush */ suit = hand[0][SUIT];

for (card = 1; card < NUM_CARDS; card++) if (hand[card][SUIT] != suit)

flush = false;

/* check for straight */

for (card = 0; card < NUM_CARDS - 1; card++)

if (hand[card][RANK] + 1 != hand[card+1][RANK]) straight = false;

/* check for 4-of-a-kind, 3-of-a-kind, and pairs by looking for \ card = 0;

while (card < NUM_CARDS) { rank = hand[card][RANK]; run = 0; do {

run++; card++;

} while (card < NUM_CARDS && hand[card][RANK] == rank); switch (run) {

case 2: pairs++; break; case 3: three = true; break; case 4: four = true; break; } } }

/********************************************************** * print_result: Prints the classification of the hand, * * based on the values of the external * * variables straight, flush, four, three, * * and pairs. * **********************************************************/ void print_result(void) {

if (straight && flush) printf(\ else if (four) printf(\ else if (three &&

pairs == 1) printf(\ else if (flush) printf(\ else if (straight) printf(\

else if (three) printf(\ else if (pairs == 2) printf(\ else if (pairs == 1) printf(\

else printf(\

printf(\}

5. [was #6]

#include /* C99 only */ #include #include

#define NUM_RANKS 13 #define NUM_SUITS 4 #define NUM_CARDS 5

/* external variables */ int num_in_rank[NUM_RANKS]; int num_in_suit[NUM_SUITS];

bool straight, flush, four, three; int pairs; /* can be 0, 1, or 2 */

/* prototypes */

void read_cards(void); void analyze_hand(void); void print_result(void);

/********************************************************** * main: Calls read_cards, analyze_hand, and print_result * * repeatedly. * **********************************************************/ int main(void) {

for (;;) {

read_cards(); analyze_hand(); print_result(); } }

/********************************************************** * read_cards: Reads the cards into the external * * variables num_in_rank and num_in_suit; * * checks for bad cards and duplicate cards. * **********************************************************/ void read_cards(void) {

bool card_exists[NUM_RANKS][NUM_SUITS]; char ch, rank_ch, suit_ch; int rank, suit; bool bad_card;

int cards_read = 0;

for (rank = 0; rank < NUM_RANKS; rank++) { num_in_rank[rank] = 0;

for (suit = 0; suit < NUM_SUITS; suit++) card_exists[rank][suit] = false; }

for (suit = 0; suit < NUM_SUITS; suit++) num_in_suit[suit] = 0;

while (cards_read < NUM_CARDS) { bad_card = false;

printf(\

rank_ch = getchar(); switch (rank_ch) {

case '0': exit(EXIT_SUCCESS); case '2': rank = 0; break; case '3': rank = 1; break; case '4': rank = 2; break; case '5': rank = 3; break; case '6': rank = 4; break; case '7': rank = 5; break; case '8': rank = 6; break; case '9': rank = 7; break; case 't': case 'T': rank = 8; break; case 'j': case 'J': rank = 9; break; case 'q': case 'Q': rank = 10; break; case 'k': case 'K': rank = 11; break; case 'a': case 'A': rank = 12; break; default: bad_card = true; }

suit_ch = getchar(); switch (suit_ch) {

case 'c': case 'C': suit = 0; break; case 'd': case 'D': suit = 1; break; case 'h': case 'H': suit = 2; break;

case 's': case 'S': suit = 3; break; default: bad_card = true; }

while ((ch = getchar()) != '\\n') if (ch != ' ') bad_card = true;

if (bad_card)

printf(\ else if (card_exists[rank][suit])

printf(\ else {

num_in_rank[rank]++; num_in_suit[suit]++;

card_exists[rank][suit] = true; cards_read++; } } }

/********************************************************** * analyze_hand: Determines whether the hand contains a * * straight, a flush, four-of-a-kind, * * and/or three-of-a-kind; determines the * * number of pairs; stores the results into * * the external variables straight, flush, * * four, three, and pairs. * **********************************************************/ void analyze_hand(void) {

int num_consec = 0; int rank, suit;

straight = false; flush = false; four = false; three = false; pairs = 0;

/* check for flush */

for (suit = 0; suit < NUM_SUITS; suit++) if (num_in_suit[suit] == NUM_CARDS) flush = true;

/* check for straight */ rank = 0;

while (num_in_rank[rank] == 0) rank++;

for (; rank < NUM_RANKS && num_in_rank[rank] > 0; rank++) num_consec++;

if (num_consec == NUM_CARDS) { straight = true; return; }

/* check for ace-low straight */ if (num_consec == NUM_CARDS - 1 &&

num_in_rank[0] > 0 && num_in_rank[NUM_RANKS-1] > 0) { straight = true; return; }

/* check for 4-of-a-kind, 3-of-a-kind, and pairs */ for (rank = 0; rank < NUM_RANKS; rank++) { if (num_in_rank[rank] == 4) four = true; if (num_in_rank[rank] == 3) three = true; if (num_in_rank[rank] == 2) pairs++; } }

/********************************************************** * print_result: Prints the classification of the hand, * * based on the values of the external * * variables straight, flush, four, three, * * and pairs. * **********************************************************/ void print_result(void) {

if (straight && flush) printf(\ else if (four) printf(\ else if (three &&

pairs == 1) printf(\ else if (flush) printf(\ else if (straight) printf(\

else if (three) printf(\ else if (pairs == 2) printf(\ else if (pairs == 1) printf(\

else printf(\

printf(\}

Chapter 11

Answers to Selected Exercises

2. [was #2] (e), (f), and (i) are legal. (a) is illegal because p is a pointer to an integer and i is an integer. (b) is illegal because *p is an integer and &i is a pointer to an integer. (c) is illegal because &p is a pointer to a pointer to an integer and q is a pointer to an integer. (d) is illegal for reasons similar to (c). (g) is illegal because p is a pointer to an integer and *q is an integer. (h) is illegal because *p is an integer and q is a pointer to an integer. 4. [was #4; modified] void swap(int *p, int *q) {

int temp;

temp = *p; *p = *q; *q = temp; }

6. [was #6]

void find_two_largest(int a[], int n, int *largest, int *second_largest) {

int i;

if (a[0] > a[1]) { *largest = a[0];

*second_largest = a[1]; } else {

*largest = a[1];

*second_largest = a[0]; }

for (i = 2; i < n; i++) if (a[i] > *largest) {

*second_largest = *largest;

*largest = a[i];

} else if (a[i] > *second_largest) *second_largest = a[i]; }

Chapter 12

Answers to Selected Exercises

2. [was #2] The statement is illegal because pointers cannot be added. Here's a legal statement that has the desired effect: middle = low + (high - low) / 2;

The value of (high - low) / 2 is an integer, not a pointer, so it can legally be added to low. 4. [was #6]

int *top_ptr;

void make_empty(void) {

top_ptr = &contents[0]; }

bool is_empty(void) {

return top_ptr == &contents[0]; }

bool is_full(void) {

return top_ptr == &contents[STACK_SIZE]; }

6. [was #10; modified]

int sum_array(const int a[], int n) {

int *p, sum;

sum = 0;

for (p = a; p < a + n; p++)

sum += *p; return sum; }

13. [was #12; modified]

#define N 10

double ident[N][N], *p; int num_zeros = N;

for (p = &ident[0][0]; p <= &ident[N-1][N-1]; p++) if (num_zeros == N) { *p = 1.0;

num_zeros = 0; } else { *p = 0.0; num_zeros++; }

15. [was #14]

int *p;

for (p = temperatures[i]; p < temperatures[i] + 24; p++) printf(\

Answers to Selected Programming Projects 1. [was #4] (a)

#include

#define MSG_LEN 80 /* maximum length of message */

int main(void) {

char msg[MSG_LEN]; int i;

printf(\ for (i = 0; i < MSG_LEN; i++) { msg[i] = getchar();

if (msg[i] == '\\n') break; }

printf(\ for (i--; i >= 0; i--) putchar(msg[i]); putchar('\\n');

return 0; } (b)

#include

#define MSG_LEN 80 /* maximum length of message */

int main(void) {

char msg[MSG_LEN], *p;

printf(\

for (p = &msg[0]; p < &msg[MSG_LEN]; p++) { *p = getchar(); if (*p == '\\n') break; }

printf(\

for (p--; p >= &msg[0]; p--) putchar(*p); putchar('\\n');

return 0; }

3. [was #8]

#include

#define MSG_LEN 80 /* maximum length of message */

int main(void) {

char msg[MSG_LEN], *p;

printf(\

for (p = msg; p < msg + MSG_LEN; p++) { *p = getchar(); if (*p == '\\n') break; }

printf(\ for (p--; p >= msg; p--) putchar(*p); putchar('\\n');

return 0; }

Chapter 13

Answers to Selected Exercises 2. [was #2]

(a) Illegal; p is not a character. (b) Legal; output is a. (c) Legal; output is abc.

(d) Illegal; *p is not a pointer. 4. [was #4] (a)

int read_line(char str[], int n) {

int ch, i = 0;

while ((ch = getchar()) != '\\n') if (i == 0 && isspace(ch)) ; /* ignore */ else if (i < n) str[i++] = ch; str[i] = '\\0'; return i; }

(b)

int read_line(char str[], int n) {

int ch, i = 0;

while (!isspace(ch = getchar())) if (i < n)

str[i++] = ch; str[i] = '\\0'; return i; } (c)

int read_line(char str[], int n) {

int ch, i = 0;

do {

ch = getchar(); if (i < n)

str[i++] = ch; } while (ch != '\\n'); str[i] = '\\0'; return i; } (d)

int read_line(char str[], int n) {

int ch, i;

for (i = 0; i < n; i++) { ch = getchar(); if (ch == '\\n') break;

str[i] = ch; }

str[i] = '\\0'; return i; }

6. [was #6]

void censor(char s[]) {

int i;

for (i = 0; s[i] != '\\0'; i++)

if (s[i] == 'f' && s[i+1] == 'o' && s[i+2] =='o') s[i] = s[i+1] = s[i+2] = 'x'; }

Note that the short-circuit evaluation of && prevents the if statement from testing characters that follow the null character. 8. [was #10] tired-or-wired?

10. [was #12] The value of q is undefined, so the call of strcpy attempts to copy the string pointed to by p into some unknown area of memory. Exercise 2 in Chapter 17 discusses how to write this function correctly. 15. [was #8]

(a) 3 (b) 0 (c) The length of the longest prefix of the string s that consists entirely of characters from the string t. Or, equivalently, the position of the first character in s that is not also in t. 16. [was #16]

int count_spaces(const char *s) {

int count = 0;

while (*s)

if (*s++ == ' ') count++; return count; }

Answers to Selected Programming Projects 1. [was #14] #include #include

#define WORD_LEN 20

void read_line(char str[], int n);

int main(void) {

char smallest_word[WORD_LEN+1], largest_word[WORD_LEN+1], current_word[WORD_LEN+1];

printf(\

read_line(current_word, WORD_LEN);

strcpy(smallest_word, strcpy(largest_word, current_word));

while (strlen(current_word) != 4) { printf(\

read_line(current_word, WORD_LEN);

if (strcmp(current_word, smallest_word) < 0) strcpy(smallest_word, current_word);

if (strcmp(current_word, largest_word) > 0) strcpy(largest_word, current_word); }

printf(\ printf(\

return 0; }

void read_line(char str[], int n) {

int ch, i = 0;

while ((ch = getchar()) != '\\n') if (i < n)

str[i++] = ch; str[i] = '\\0'; }

4. [was #18]

#include

int main(int argc, char *argv[])

{

int i;

for (i = argc - 1; i > 0; i--) printf(\ printf(\

return 0; }

6. [was #20]

#include #include #include

#define NUM_PLANETS 9

int string_equal(const char *s, const char *t);

int main(int argc, char *argv[]) {

char *planets[] = {\ \ \ int i, j;

for (i = 1; i < argc; i++) {

for (j = 0; j < NUM_PLANETS; j++)

if (string_equal(argv[i], planets[j])) {

printf(\ break; }

if (j == NUM_PLANETS)

printf(\ }

return 0; }

int string_equal(const char *s, const char *t) {

int i;

for (i = 0; toupper(s[i]) == toupper(t[i]); i++) if (s[i] == '\\0') return 1;

return 0; }

Chapter 14

Answers to Selected Exercises

2. [was #2] #define NELEMS(a) ((int) (sizeof(a) / sizeof(a[0]))) 4. [was #4]

(a) One problem stems from the lack of parentheses around the replacement list. For example, the statement a = 1/AVG(b, c); will be replaced by a = 1/(b+c)/2;

Even if we add the missing parentheses, though, the macro still has problems, because it needs parentheses around x and y in the replacement list. The preprocessor will turn the statement a = AVG(bd); into

a = ((bd)/2); which is equivalent to a = ((b<(c+c)>d)/2);

Here's the final (corrected) version of the macro: #define AVG(x,y) (((x)+(y))/2)

(b) The problem is the lack of parentheses around the replacement list. For example,

a = 1/AREA(b, c); becomes a = 1/(b)*(c);

Here's the corrected macro: #define AREA(x,y) ((x)*(y)) 5. [was #6]

(a) The call of putchar expands into the following statement: putchar(('a'<=(s[++i])&&(s[++i])<='z'?(s[++i])-'a'+'A':(s[++i]))); The character a is less than or equal to s[1] (which is b), yielding a true condition. The character s[2] (which is c) is less than or equal to z, which is also true. The value printed is s[3]-'a'+'A', which is D (assuming that the character set is ASCII).

(b) The character a is not less than or equal to s[1] (which is 1) so the test condition is false. The value printed is s[2], which is 2. 7. [was #8] (a)

long long_max(long x, long y) {

return x > y ? x : y; }

The preprocessor would actually put all the tokens on one line, but this version is more readable.

(b) The problem with types such as unsigned long is that they require two words, which prevents GENERIC_MAX from creating the desired function name. For example, GENERIC_MAX(unsigned long) would expand into unsigned long unsigned long_max(unsigned long x, unsigned long y) {

return x > y ? x : y; }

(c) To make GENERIC_MAX work with any basic type, use a type definition to rename the type: typedef unsigned long ULONG;

We can now write GENERIC_MAX(ULONG).

12. [was #10] (c) and (e) will fail, since M is defined.

14. [was #12; modified] Here's what the program will look like after preprocessing:

Blank line Blank line Blank line Blank line Blank line Blank line Blank line

int main(void) {

int a[= 10], i, j, k, m;

Blank line i = j;

Blank line Blank line Blank line

i = 10 * j+1;

i = (x,y) x-y(j, k);

i = ((((j)*(j)))*(((j)*(j)))); i = (((j)*(j))*(j)); i = jk;

puts(\

Blank line i = SQR(j); Blank line i = (j);

return 0; }

Some preprocessors delete white-space characters at the beginning of a line, so your results may vary. Three lines will cause errors when the program is compiled. Two contain syntax errors: int a[= 10], i, j, k, m; i = (x,y) x-y(j, k);

The third refers to an undefined variable: i = jk;

Chapter 15

Answers to Selected Exercises

2. [was #2] (b). Function definitions should not be put in a header file. If a function definition appears in a header file that is included by two (or more) source files, the program can't be linked, since the linker will see two copies of the function. 6. [was #8]

(a) main.c, f1.c, and f2.c.

(b) f1.c (assuming that f1.h is not affected by the change). (c) main.c, f1.c, and f2.c, since all three include f1.h. (d) f1.c and f2.c, since both include f2.h.

Chapter 16

Answers to Selected Exercises 2. [was #2; modified] (a)

struct {

double real, imaginary; } c1, c2, c3; (b)

struct {

double real, imaginary;

} c1 = {0.0, 1.0}, c2 = {1.0, 0.0}, c3; (c) Only one statement is necessary: c1 = c2; (d)

c3.real = c1.real + c2.real;

c3.imaginary = c1.imaginary + c2.imaginary; 4. [was #4; modified] (a)

typedef struct {

double real, imaginary; } Complex;

(b) Complex c1, c2, c3; (c)

Complex make_complex(double real, double imaginary) {

Complex c;

c.real = real;

c.imaginary = imaginary; return c; } (d)

Complex add_complex(Complex c1, Complex c2) {

Complex c3;

c3.real = c1.real + c2.real;

c3.imaginary = c1.imaginary + c2.imaginary; return c3; }

11. [was #10; modified] The a member will occupy 8 bytes, the union e will take 8 bytes (the largest member, c, is 8 bytes long), and the array f will require 4 bytes, so the total space allocated for s will be 20 bytes.

14. [was #12; modified] (a)

double area(struct shape s) {

if (s.shape_kind == RECTANGLE)

return s.u.rectangle.height * s.u.rectangle.width; else

return 3.14159 * s.u.circle.radius * s.u.circle.radius; } (b)

struct shape move(struct shape s, int x, int y) {

struct shape new_shape = s;

new_shape.center.x += x; new_shape.center.y += y; return new_shape; } (c)

struct shape scale(struct shape s, double c) {

struct shape new_shape = s;

if (new_shape.shape_kind == RECTANGLE) { new_shape.u.rectangle.height *= c; new_shape.u.rectangle.width *= c; } else

new_shape.u.circle.radius *= c;

return new_shape; }

15. [was #14]

(a) enum week_days {MON, TUE, WED, THU, FRI, SAT, SUN};

(b) typedef enum {MON, TUE, WED, THU, FRI, SAT, SUN} Week_days; 17. [was #16] All the statements are legal, since C allows integers and enumeration values to be mixed without restriction. Only (a), (d), and

(e) are safe. (b) is not meaningful if i has a value other than 0 or 1. (c) will not yield a meaningful result if b has the value 1. Answers to Selected Programming Projects 1. [was #6; modified]

#include

#define COUNTRY_COUNT \\

((int) (sizeof(country_codes) / sizeof(country_codes[0])))

struct dialing_code { char *country; int code; };

const struct dialing_code country_codes[] =

{{\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\ {\

int main(void) {

int code, i;

printf(\ scanf(\

for (i = 0; i < COUNTRY_COUNT; i++) if (code == country_codes[i].code) {

printf(\

code, country_codes[i].country); return 0; }

printf(\ return 0; }

3. [was #8]

#include #include \

#define NAME_LEN 25 #define MAX_PARTS 100

struct part { int number;

char name[NAME_LEN+1]; int on_hand; };

int find_part(int number, const struct part inv[], int np); void insert(struct part inv[], int *np);

void search(const struct part inv[], int np); void update(struct part inv[], int np);

void print(const struct part inv[], int np);

/********************************************************** * main: Prompts the user to enter an operation code, * * then calls a function to perform the requested * * action. Repeats until the user enters the * * command 'q'. Prints an error message if the user * * enters an illegal code. * **********************************************************/ int main(void) {

char code;

struct part inventory[MAX_PARTS]; int num_parts = 0;

for (;;) {

printf(\ scanf(\

while (getchar() != '\\n') /* skips to end of line */ ;

switch (code) {

case 'i': insert(inventory, &num_parts); break;

case 's': search(inventory, num_parts); break;

case 'u': update(inventory, num_parts); break;

case 'p': print(inventory, num_parts); break; case 'q': return 0;

default: printf(\ }

printf(\ } }

/********************************************************** * find_part: Looks up a part number in the inv array. * * Returns the array index if the part number * * is found; otherwise, returns -1. * **********************************************************/ int find_part(int number, const struct part inv[], int np) {

int i;

for (i = 0; i < np; i++)

if (inv[i].number == number) return i; return -1; }

/********************************************************** * insert: Prompts the user for information about a new * * part and then inserts the part into the inv * * array. Prints an error message and returns * * prematurely if the part already exists or the * * array is full. * **********************************************************/ void insert(struct part inv[], int *np) {

int part_number;

if (*np == MAX_PARTS) {

printf(\ return; }

printf(\ scanf(\

if (find_part(part_number, inv, *np) >= 0) { printf(\ return; }

inv[*np].number = part_number; printf(\

read_line(inv[*np].name, NAME_LEN); printf(\ scanf(\ (*np)++; }

/********************************************************** * search: Prompts the user to enter a part number, then * * looks up the part in the inv array. If the * * part exists, prints the name and quantity on * * hand; if not, prints an error message. * **********************************************************/ void search(const struct part inv[], int np) {

int i, number;

printf(\ scanf(\

i = find_part(number, inv, np); if (i >= 0) {

printf(\

printf(\ } else

printf(\}

/********************************************************** * update: Prompts the user to enter a part number. * * Prints an error message if the part can't be * * found in the inv array; otherwise, prompts the *

* user to enter change in quantity on hand and * * updates the array. * **********************************************************/ void update(struct part inv[], int np) {

int i, number, change;

printf(\ scanf(\

i = find_part(number, inv, np); if (i >= 0) {

printf(\ scanf(\ inv[i].on_hand += change; } else

printf(\}

/********************************************************** * print: Prints a listing of all parts in the inv array, * * showing the part number, part name, and * * quantity on hand. Parts are printed in the * * order in which they were entered into the * * array. * **********************************************************/ void print(const struct part inv[], int np) {

int i;

printf(\ \ for (i = 0; i < np; i++)

printf(\ inv[i].name, inv[i].on_hand); }

Chapter 17

Answers to Selected Exercises 2. [was #2; modified] char *duplicate(const char *s) {

char *temp = malloc(strlen(s) + 1);

if (temp == NULL) return NULL;

strcpy(temp, s); return temp; }

5. [was #6] (b) and (c) are legal. (a) is illegal because it tries to reference a member of d without mentioning d. (d) is illegal because it uses -> instead of . to reference the c member of d.

7. [was #8] The first call of free will release the space for the first node in the list, making p a dangling pointer. Executing p = p->next to advance to the next node will have an undefined effect. Here's a correct way to write the loop, using a temporary pointer that points to the node being deleted: struct node *temp;

p = first;

while (p != NULL) { temp = p; p = p->next; free(temp); }

8. [was #10; modified]

#include /* C99 only */ #include #include #include \

struct node { int value;

struct node *next; };

struct node *top = NULL;

void make_empty(void) {

struct node *temp;

本文来源:https://www.bwwdw.com/article/s2ur.html

Top