C Primer Plus(第六版)第十七章 编程练习答案
Posted 水番正文
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C Primer Plus(第六版)第十七章 编程练习答案相关的知识,希望对你有一定的参考价值。
结束了,这本树,现在就差道复习题的答案确认了,最后一题沉浸式解题,仿佛在做逆向题一样,好了,这就是我的这本书看完了每一页做完了每一题的最后一章。--11.26
CH17 Code answer 1:
FilmA
/* films2.c -- using a linked list of structures */
#include <stdio.h>
#include <stdlib.h> /* has the malloc prototype */
#include <string.h> /* has the strcpy prototype */
#define TSIZE 45 /* size of array to hold title */
struct film
char title[TSIZE];
int rating;
struct film * next; /* points to next struct in list */
struct film * prev;
;
char * s_gets(char * st, int n);
int main(void)
struct film * head = NULL;
struct film * prev, * current;
char input[TSIZE];
/* Gather and store information*/
puts("Enter first movie title:");
while (s_gets(input, TSIZE) != NULL && input[0] != '\\0')
current = (struct film *) malloc(sizeof(struct film));
if (head == NULL) /* first structure */
head = current; //链表头部
current->prev = NULL; //头部没有上一个链表
else /* subsequent structures */
prev->next = current; //前一个链表指向当前链表
current->prev = prev; //当前链表指向上个链表
current->next = NULL; //当前链表的下一个链表待定
strcpy(current->title, input); //存储项
puts("Enter your rating <0-10>:");
scanf("%d", ¤t->rating);
while(getchar() != '\\n')
continue;
puts("Enter next movie title (empty line to stop):");
prev = current; //当前链表变成上个链表
/* Show list of movies */
if (head == NULL)
printf("No data entered. ");
else
printf ("Here is the movie list:\\n");
printf("Reverse order\\n");
while (current != NULL) //逆序打印
printf("Movie: %s Rating: %d\\n",
current->title, current->rating);
current = current->prev;
printf("\\n");
printf("Positive order\\n");
current = head; //正序打印
while (current != NULL)
printf("Movie: %s Rating: %d\\n",
current->title, current->rating);
current = current->next;
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
free(current);
current = current->next;
printf("\\nBye!");
return 0;
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
FilmB
/* films2.c -- using a linked list of structures */
#include <stdio.h>
#include <stdlib.h> /* has the malloc prototype */
#include <string.h> /* has the strcpy prototype */
#define TSIZE 45 /* size of array to hold title */
struct film
char title[TSIZE];
int rating;
struct film * next; /* points to next struct in list */
;
char * s_gets(char * st, int n);
void Re_Pt(struct film * pf);
int main(void)
struct film * head = NULL;
struct film * prev, * current;
char input[TSIZE];
/* Gather and store information */
puts("Enter first movie title:");
while (s_gets(input, TSIZE) != NULL && input[0] != '\\0')
current = (struct film *) malloc(sizeof(struct film));
if (head == NULL) /* first structure */
head = current;
else /* subsequent structures */
prev->next = current;
current->next = NULL;
strcpy(current->title, input);
puts("Enter your rating <0-10>:");
scanf("%d", ¤t->rating);
while(getchar() != '\\n')
continue;
puts("Enter next movie title (empty line to stop):");
prev = current;
/* Show list of movies */
if (head == NULL)
printf("No data entered. ");
else
printf ("Here is the movie list:\\n");
current = head;
while (current != NULL)
printf("Movie: %s Rating: %d\\n",
current->title, current->rating);
current = current->next;
puts("\\n");
current = head;
Re_Pt(current);
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
free(current);
current = current->next;
printf("\\nBye!");
return 0;
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
void Re_Pt(struct film * pf)
if (pf->next != NULL) //如果下一项链表不为空 就向下递归
Re_Pt(pf->next);
printf("Movie: %s Rating: %d\\n",
pf->title, pf->rating);
CH17 Code answer 2:
Flims.c
/* films3.c -- using an ADT-style linked list */
/* compile with list.c */
#include <stdio.h>
#include <stdlib.h> /* prototype for exit() */
#include <string.h>
#include "list.h" /* defines List, Item */
void showmovies(Item item);
char * s_gets(char * st, int n);
int main(void)
List movies;
Item temp;
/* initialize */
InitializeList(&movies);
if (ListIsFull(&movies))
fprintf(stderr,"No memory available! Bye!\\n");
exit(1);
/* gather and store */
puts("Enter first movie title:");
while (s_gets(temp.title, TSIZE) != NULL && temp.title[0] != '\\0')
puts("Enter your rating <0-10>:");
scanf("%d", &temp.rating);
while(getchar() != '\\n')
continue;
if (AddItem(temp, &movies)==false)
fprintf(stderr,"Problem allocating memory\\n");
break;
if (ListIsFull(&movies))
puts("The list is now full.");
break;
puts("Enter next movie title (empty line to stop):");
/* display */
if (ListIsEmpty(&movies))
printf("No data entered. ");
else
printf ("Here is the movie list:\\n");
Traverse(&movies, showmovies);
printf("You entered %d movies.\\n", ListItemCount(&movies));
/* clean up */
EmptyTheList(&movies);
printf("Bye!\\n");
return 0;
void showmovies(Item item)
printf("Movie: %s Rating: %d\\n", item.title,
item.rating);
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
list.c
/* list.c -- functions supporting list operations */
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/* local function prototype */
static void CopyToNode(Item item, Node * pnode);
/* interface functions */
/* set the list to empty */
void InitializeList(List * plist)
plist->head = NULL;
plist->end = NULL;
/* returns true if list is empty */
bool ListIsEmpty(const List * plist)
if (plist->head == NULL)
return true;
else
return false;
/* returns true if list is full */
bool ListIsFull(const List * plist)
Node * pt;
bool full;
pt = (Node *) malloc(sizeof(Node));
if (pt == NULL)
full = true;
else
full = false;
free(pt);
return full;
/* returns number of nodes */
unsigned int ListItemCount(const List * plist)
unsigned int count = 0;
Node * pnode = plist->head; /* set to start of list */
while (pnode != NULL)
++count;
pnode = pnode->next; /* set to next node */
return count;
/* creates node to hold item and adds it to the end of */
/* the list pointed to by plist (slow implementation) */
bool AddItem(Item item, List * plist)
Node * pnew;
Node * scan = plist->head;
pnew = (Node *) malloc(sizeof(Node));
if (pnew == NULL)
return false; /* quit function on failure */
CopyToNode(item, pnew);
pnew->next = NULL;
if (scan == NULL) /* empty list, so place */
plist->head = pnew; /* pnew at head of list */
else
while (scan->next != NULL)
scan = scan->next; /* find end of list */
scan->next = pnew; /* add pnew to end */
return true;
/* visit each node and execute function pointed to by pfun */
void Traverse (const List * plist, void (* pfun)(Item item) )
Node * pnode = plist->head; /* set to start of list */
while (pnode != NULL)
(*pfun)(pnode->item); /* apply function to item */
pnode = pnode->next; /* advance to next item */
/* free memory allocated by malloc() */
/* set list pointer to NULL */
void EmptyTheList(List * plist)
Node * psave;
while (plist->head != NULL)
psave = plist->head->next; /* save address of next node */
free(plist->head); /* free current node */
plist->head = psave; /* advance to next node */
/* local function definition */
/* copies an item into a node */
static void CopyToNode(Item item, Node * pnode)
pnode->item = item; /* structure copy */
list.h
/* list.h -- header file for a simple list type */
#ifndef LIST_H_
#define LIST_H_
#include <stdbool.h> /* C99 feature */
/* program-specific declarations */
#define TSIZE 45 /* size of array to hold title */
struct film
char title[TSIZE];
int rating;
;
/* general type definitions */
typedef struct film Item;
typedef struct node
Item item;
struct node * next;
Node;
typedef struct list
Node * head;
Node * end;
List;
/* function prototypes */
/* operation: initialize a list */
/* preconditions: plist points to a list */
/* postconditions: the list is initialized to empty */
void InitializeList(List * plist);
/* operation: determine if list is empty */
/* plist points to an initialized list */
/* postconditions: function returns True if list is empty */
/* and returns False otherwise */
bool ListIsEmpty(const List *plist);
/* operation: determine if list is full */
/* plist points to an initialized list */
/* postconditions: function returns True if list is full */
/* and returns False otherwise */
bool ListIsFull(const List *plist);
/* operation: determine number of items in list */
/* plist points to an initialized list */
/* postconditions: function returns number of items in list */
unsigned int ListItemCount(const List *plist);
/* operation: add item to end of list */
/* preconditions: item is an item to be added to list */
/* plist points to an initialized list */
/* postconditions: if possible, function adds item to end */
/* of list and returns True; otherwise the */
/* function returns False */
bool AddItem(Item item, List * plist);
/* operation: apply a function to each item in list */
/* plist points to an initialized list */
/* pfun points to a function that takes an */
/* Item argument and has no return value */
/* postcondition: the function pointed to by pfun is */
/* executed once for each item in the list */
void Traverse (const List *plist, void (* pfun)(Item item) );
/* operation: free allocated memory, if any */
/* plist points to an initialized list */
/* postconditions: any memory allocated for the list is freed */
/* and the list is set to empty */
void EmptyTheList(List * plist);
#endif
CH17 Code answer 3:
Films.c
/* films3.c -- using an ADT-style linked list */
/* compile with list.c */
#include <stdio.h>
#include <stdlib.h> /* prototype for exit() */
#include <string.h>
#include "list.h" /* defines List, Item */
void showmovies(Item item);
char * s_gets(char * st, int n);
int main(void)
List movies;
Item temp;
/* initialize */
InitializeList(&movies);
if (ListIsFull(&movies))
fprintf(stderr,"No memory available! Bye!\\n");
exit(1);
/* gather and store */
puts("Enter first movie title:");
while (s_gets(temp.title, TSIZE) != NULL && temp.title[0] != '\\0')
puts("Enter your rating <0-10>:");
scanf("%d", &temp.rating);
while(getchar() != '\\n')
continue;
if (AddItem(temp, &movies)==false)
fprintf(stderr,"Problem allocating memory\\n");
break;
if (ListIsFull(&movies))
puts("The list is now full.");
break;
puts("Enter next movie title (empty line to stop):");
/* display */
if (ListIsEmpty(&movies))
printf("No data entered. ");
else
printf ("Here is the movie list:\\n");
Traverse(&movies, showmovies);
printf("You entered %d movies.\\n", ListItemCount(&movies));
/* clean up */
EmptyTheList(&movies);
printf("Bye!\\n");
return 0;
void showmovies(Item item)
printf("Movie: %s Rating: %d\\n", item.title,
item.rating);
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
list.c
/* list.c -- functions supporting list operations */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
/* local function prototype */
static void CopyToNode(Item item, Node * pnode);
static void CopyToItem(Item item, Item * entries, int n);
/* interface functions */
/* set the list to empty */
void InitializeList(List * plist)
plist->entries[MAXSIZE] = 0 ;
plist->items = 0;
/* returns true if list is empty */
bool ListIsEmpty(const List * plist)
if (plist->items == 0) //直接借用items当下标 所以为0~99
return true;
else
return false;
/* returns true if list is full */
bool ListIsFull(const List * plist)
Node * pt;
bool full;
pt = (Node *) malloc(sizeof(Node));
if (pt == NULL)
full = true;
else
full = false;
free(pt);
return full;
/* returns number of nodes */
unsigned int ListItemCount(const List * plist)
// unsigned int count = 0;
// Node * pnode = *plist; /* set to start of list */
//
// while (pnode != NULL)
//
// ++count;
// pnode = pnode->next; /* set to next node */
//
return plist->items; //一句到位
/* creates node to hold item and adds it to the end of */
/* the list pointed to by plist (slow implementation) */
bool AddItem(Item item, List * plist)
// Node * pnew;
// Node * scan = *plist;
// pnew = (Node *) malloc(sizeof(Node));
// if (pnew == NULL)
// return false; /* quit function on failure */
// CopyToNode(item, pnew);
// pnew->next = NULL;
// if (scan == NULL) /* empty list, so place */
// *plist = pnew; /* pnew at head of list */
// else
//
// while (scan->next != NULL)
// scan = scan->next; /* find end of list */
// scan->next = pnew; /* add pnew to end */
//
if (plist->items >= MAXSIZE)
return false;
CopyToItem(item, plist->entries, plist->items);
plist->items++;
return true;
/* visit each node and execute function pointed to by pfun */
void Traverse (const List * plist, void (* pfun)(Item item) )
// Node * pnode = *plist; /* set to start of list */
//
// while (pnode != NULL)
//
// (*pfun)(pnode->item); /* apply function to item */
// pnode = pnode->next; /* advance to next item */
//
int i;
for (i = 0; i < plist->items; i++)
(*pfun)(plist->entries[i]);
/* free memory allocated by malloc() */
/* set list pointer to NULL */
void EmptyTheList(List * plist)
// Node * psave;
//
// while (*plist != NULL)
//
// psave = (*plist)->next; /* save address of next node */
// free(*plist); /* free current node */
// *plist = psave; /* advance to next node */
//
plist->entries[MAXSIZE] = 0 ;
plist->items = 0;
/* local function definition */
/* copies an item into a node */
static void CopyToNode(Item item, Node * pnode)
pnode->item = item; /* structure copy */
static void CopyToItem(Item item, Item * entries, int n)
strcpy(entries[n].title, item.title);
entries[n].rating = item.rating;
list.h
/* list.h -- header file for a simple list type */
#ifndef LIST_H_
#define LIST_H_
#include <stdbool.h> /* C99 feature */
/* program-specific declarations */
#define TSIZE 45 /* size of array to hold title */
#define MAXSIZE 100
struct film
char title[TSIZE];
int rating;
;
/* general type definitions */
typedef struct film Item;
typedef struct node
Item item;
struct node * next;
Node;
typedef struct list
Item entries[MAXSIZE];
int items;
List;
/* function prototypes */
/* operation: initialize a list */
/* preconditions: plist points to a list */
/* postconditions: the list is initialized to empty */
void InitializeList(List * plist);
/* operation: determine if list is empty */
/* plist points to an initialized list */
/* postconditions: function returns True if list is empty */
/* and returns False otherwise */
bool ListIsEmpty(const List *plist);
/* operation: determine if list is full */
/* plist points to an initialized list */
/* postconditions: function returns True if list is full */
/* and returns False otherwise */
bool ListIsFull(const List *plist);
/* operation: determine number of items in list */
/* plist points to an initialized list */
/* postconditions: function returns number of items in list */
unsigned int ListItemCount(const List *plist);
/* operation: add item to end of list */
/* preconditions: item is an item to be added to list */
/* plist points to an initialized list */
/* postconditions: if possible, function adds item to end */
/* of list and returns True; otherwise the */
/* function returns False */
bool AddItem(Item item, List * plist);
/* operation: apply a function to each item in list */
/* plist points to an initialized list */
/* pfun points to a function that takes an */
/* Item argument and has no return value */
/* postcondition: the function pointed to by pfun is */
/* executed once for each item in the list */
void Traverse (const List *plist, void (* pfun)(Item item) );
/* operation: free allocated memory, if any */
/* plist points to an initialized list */
/* postconditions: any memory allocated for the list is freed */
/* and the list is set to empty */
void EmptyTheList(List * plist);
#endif
CH17 Code answer 4:
mall.c
// mall.c -- use the Queue interface
// compile with queue.c
#include <stdio.h>
#include <stdlib.h> // for rand() and srand()
#include <time.h> // for time()
#include "queue.h" // change Item typedef
#define MIN_PER_HR 60.0
bool newcustomer(double x); // is there a new customer?
Item customertime(long when); // set customer parameters
int main(void)
Queue line1;
Queue line2;
Item temp1; // new customer data
Item temp2;
int hours; // hours of simulation
int perhour; // average # of arrivals per hour
long cycle, cyclelimit; // loop counter, limit
long turnaways = 0; // turned away by full queue
long customers = 0; // joined the queue
long served = 0; // served during the simulation
long sum_line = 0; // cumulative line length
int wait_time1 = 0; // time until Sigmund is free
int wait_time2 = 0;
double min_per_cust; // average time between arrivals
long line_wait = 0; // cumulative time in line
InitializeQueue(&line1);
InitializeQueue(&line2);
srand((unsigned int) time(0)); // random initializing of rand()
puts("Case Study: Sigmund Lander's Advice Booth");
puts("Enter the number of simulation hours:");
scanf("%d", &hours);
cyclelimit = MIN_PER_HR * hours;
puts("Enter the average number of customers per hour:");
scanf("%d", &perhour);
min_per_cust = MIN_PER_HR / perhour;
for (cycle = 0; cycle < cyclelimit; cycle++)
if (newcustomer(min_per_cust)) //新顾客来了
if (QueueIsFull(&line1) && QueueIsFull(&line2)) //如果都满了 走的顾客就+1
turnaways++;
else //肯定都没满 或者一个满了
customers++;
if (QueueIsFull(&line1)) //line1满了加line2
temp2 = customertime(cycle); //创建客户数据
EnQueue(temp2, &line2);
else
temp1 = customertime(cycle); //创建客户数据
EnQueue(temp1, &line1);
if (wait_time1 <= 0 && !QueueIsEmpty(&line1))
DeQueue (&temp1, &line1);
wait_time1 = temp1.processtime; //设置接下来的咨询时间
line_wait += cycle - temp1.arrive; //计算总的 到来时间-咨询时间之前
served++; //咨询人数加一
if (wait_time2 <= 0 && !QueueIsEmpty(&line2))
DeQueue (&temp2, &line2);
wait_time2 = temp2.processtime;
line_wait += cycle - temp2.arrive;
served++;
if (wait_time1 > 0)
wait_time1--;
if (wait_time2 > 0)
wait_time2--;
sum_line += QueueItemCount(&line1);
sum_line += QueueItemCount(&line2);
if (customers > 0)
printf("customers accepted: %ld\\n", customers);
printf(" customers served: %ld\\n", served);
printf(" turnaways: %ld\\n", turnaways);
printf("average queue size: %.2f\\n",
(double) sum_line / cyclelimit);
printf(" average wait time: %.2f minutes\\n",
(double) line_wait / served);
else
puts("No customers!");
EmptyTheQueue(&line1);
EmptyTheQueue(&line2);
puts("Bye!");
return 0;
// x = average time, in minutes, between customers
// return value is true if customer shows up this minute
bool newcustomer(double x)
if (rand() * x / RAND_MAX < 1)
return true;
else
return false;
// when is the time at which the customer arrives
// function returns an Item structure with the arrival time
// set to when and the processing time set to a random value
// in the range 1 - 3
Item customertime(long when)
Item cust;
cust.processtime = rand() % 3 + 1;
cust.arrive = when;
return cust;
queue.c
/* queue.c -- the Queue type implementation*/
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
/* local functions */
static void CopyToNode(Item item, Node * pn);
static void CopyToItem(Node * pn, Item * pi);
void InitializeQueue(Queue * pq)
pq->front = pq->rear = NULL;
pq->items = 0;
bool QueueIsFull(const Queue * pq)
return pq->items == MAXQUEUE;
bool QueueIsEmpty(const Queue * pq)
return pq->items == 0;
int QueueItemCount(const Queue * pq)
return pq->items;
bool EnQueue(Item item, Queue * pq)
Node * pnew;
if (QueueIsFull(pq))
return false;
pnew = (Node *) malloc( sizeof(Node));
if (pnew == NULL)
fprintf(stderr,"Unable to allocate memory!\\n");
exit(1);
CopyToNode(item, pnew);
pnew->next = NULL;
if (QueueIsEmpty(pq))
pq->front = pnew; /* item goes to front */
else
pq->rear->next = pnew; /* link at end of queue */
pq->rear = pnew; /* record location of end */
pq->items++; /* one more item in queue */
return true;
bool DeQueue(Item * pitem, Queue * pq)
Node * pt;
if (QueueIsEmpty(pq))
return false;
CopyToItem(pq->front, pitem);
pt = pq->front;
pq->front = pq->front->next;
free(pt);
pq->items--;
if (pq->items == 0)
pq->rear = NULL;
return true;
/* empty the queue */
void EmptyTheQueue(Queue * pq)
Item dummy;
while (!QueueIsEmpty(pq))
DeQueue(&dummy, pq);
/* Local functions */
static void CopyToNode(Item item, Node * pn)
pn->item = item;
static void CopyToItem(Node * pn, Item * pi)
*pi = pn->item;
queue.h
/* queue.h -- interface for a queue */
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdbool.h>
// INSERT ITEM TYPE HERE
// FOR EXAMPLE,
//typedef int Item; // for use_q.c
// OR typedef struct item int gumption; int charisma; Item;
// OR (for mall.c)
/**/
typedef struct item
long arrive; // the time when a customer joins the queue
int processtime; // the number of consultation minutes desired
Item;
/**/
#define MAXQUEUE 10
typedef struct node
Item item;
struct node * next;
Node;
typedef struct queue
Node * front; /* pointer to front of queue */
Node * rear; /* pointer to rear of queue */
int items; /* number of items in queue */
Queue;
/* operation: initialize the queue */
/* precondition: pq points to a queue */
/* postcondition: queue is initialized to being empty */
void InitializeQueue(Queue * pq);
/* operation: check if queue is full */
/* precondition: pq points to previously initialized queue */
/* postcondition: returns True if queue is full, else False */
bool QueueIsFull(const Queue * pq);
/* operation: check if queue is empty */
/* precondition: pq points to previously initialized queue */
/* postcondition: returns True if queue is empty, else False */
bool QueueIsEmpty(const Queue *pq);
/* operation: determine number of items in queue */
/* precondition: pq points to previously initialized queue */
/* postcondition: returns number of items in queue */
int QueueItemCount(const Queue * pq);
/* operation: add item to rear of queue */
/* precondition: pq points to previously initialized queue */
/* item is to be placed at rear of queue */
/* postcondition: if queue is not empty, item is placed at */
/* rear of queue and function returns */
/* True; otherwise, queue is unchanged and */
/* function returns False */
bool EnQueue(Item item, Queue * pq);
/* operation: remove item from front of queue */
/* precondition: pq points to previously initialized queue */
/* postcondition: if queue is not empty, item at head of */
/* queue is copied to *pitem and deleted from */
/* queue, and function returns True; if the */
/* operation empties the queue, the queue is */
/* reset to empty. If the queue is empty to */
/* begin with, queue is unchanged and the */
/* function returns False */
bool DeQueue(Item *pitem, Queue * pq);
/* operation: empty the queue */
/* precondition: pq points to previously initialized queue */
/* postconditions: the queue is empty */
void EmptyTheQueue(Queue * pq);
#endif
CH17 Code answer 5:
stack.c
#include <stdio.h>
#include "stack.h"
static void ToBeTrueIndex(int * index);
void InitializeStack(Stack * ps)
ps->top = 0;
ps->items[MAXSTACK] = 0 ;
bool FullStack(const Stack * ps)
return ps->top == MAXSTACK - 1;
bool EmptyStack(const Stack * ps)
return ps->top == 0;
bool Push(Item item, Stack * ps)
if (FullStack(ps)) //如果栈已满返回错误
return false;
ps->items[ps->top] = item; //放入栈顶
ps->top++; //压栈
return true;
bool Pop(Item * pitem, Stack * ps)
if (FullStack(ps))
return false;
ToBeTrueIndex(&ps->top);
*pitem = ps->items[ps->top]; //抬栈
// ps->top--; //调整栈顶
if (ps->top == 0) //如果栈全面被抬完就初始化栈
InitializeStack(ps);
return true;
static void ToBeTrueIndex(int * index)
--(*index); //指向栈顶数据
stack.h
#ifndef STACK_H_ //注意是if n def!!! 看了半天
#define STACK_H_
#include <stdbool.h>
#define MAXSTACK 10
typedef char Item;
typedef struct stack
int top;
Item items[MAXSTACK];
Stack;
/*操作: 初始化栈 */
/*前提条件: ps指向一个栈 */
/*后置条件: 该栈初始化为空 */
void InitializeStack(Stack * ps);
/*操作: 检查栈是否已满 */
/*前提条件: ps指向之前已被初始化的栈 */
/*后置条件: 如果栈已经满,该函数返回true */
bool FullStack(const Stack * ps);
/*操作: 检查栈是否为空 */
/*前提条件: ps指向之前已被初始化的栈 */
/*后置条件: 如果栈为空,该函数放回ture;否者,返回false */
bool EmptyStack(const Stack * ps);
/*操作: 把项压入栈顶 */
/*前提条件: ps指向之前已被初始化的栈 */
/* items是待压入栈顶的项 */
/*后置条件: 如果栈不满,把item放在栈顶,该函数返回true; */
/* 否则,栈不变,该函数返回false */
bool Push(Item item, Stack * ps);
/*操作: 从栈顶删除项 */
/*前提条件: ps指向之前已被初始化的栈 */
/*后置条件: 如果栈不为空,把item拷贝到*pitem */
/* 删除栈顶的item,该函数返回true */
/* 如果该操作后栈中没有项,则重置该项为空 */
/* 如果删除操作之前栈为空,栈不变,该函数返回false */
bool Pop(Item * pitem, Stack * ps);
#endif
use_s.c
#include <stdio.h>
#include <string.h>
#include "stack.h"
int main(void)
Item temp[MAXSTACK];
Stack box;
int i;
Item t; //应该为字符 不应该是指针
printf("Enter a string, I will give you string of reverse!\\n");
while (scanf("%s", temp))
InitializeStack(&box); //初始化栈
for ( i = 0; i < strlen(temp); i++ ) //将字符压栈
Push(temp[i], &box);
for ( i = 0; i < strlen(temp); i++) //将字符弹栈
Pop(&t, &box);
printf("%c", t);
puts("\\n");
printf("Enter a string, I will give you string of reverse!(enter ^C to quit)\\n");
printf("Bye!");
return 0;
CH17 Code answer 6:
Binary_Search.c
#include <stdio.h>
#define MAX 1024
int Binary_Search(int *, int, int);
int Pow(int, int);
int main(void)
int data[MAX];
int i;
for ( i = 0; i < MAX; i++)
data[i] = i;
// printf("%d ", data[i]);
printf("%d", Binary_Search(data, MAX, 777));
return 0;
int Binary_Search(int * target, int n, int key)
int i;
int index;
int min = 0, max = n;
int len = 0;
int answer = 0;
while ( Pow(2, len) < n ) //判断是多少2^n - 1以内
len++;
index = n / 2; //到中间的位置
for ( i = 0; i < len; i++ )
if ( key < target[index] )
max = index;
index = (min + index) / 2;
else if( key > target[index] )
min = index;
index = (index + max) / 2;
else
answer = 1;
return answer;
int Pow(int num, int n)
int i;
int pow = 1;
if ( n == 0 )
return 1;
for ( i = 0; i < n; i++ )
pow = pow * num;
return pow;
CH17 Code answer 7:
tree.c
/* tree.c -- tree support functions */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
/* local data type */
typedef struct pair
Trnode * parent;
Trnode * child;
Pair;
/* protototypes for local functions */
static Trnode * MakeNode(const Item * pi);
static bool ToLeft(const Item * i1, const Item * i2);
static bool ToRight(const Item * i1, const Item * i2);
static void AddNode (Trnode * new_node, Trnode * root);
static void InOrder(const Trnode * root, void (* pfun)(Item item));
static Pair SeekItem(const Item * pi, const Tree * ptree);
static void DeleteNode(Trnode **ptr);
static void DeleteAllNodes(Trnode * ptr);
/* function definitions */
void InitializeTree(Tree * ptree)
ptree->root = NULL;
ptree->size = 0;
bool TreeIsEmpty(const Tree * ptree)
if (ptree->root == NULL)
return true;
else
return false;
bool TreeIsFull(const Tree * ptree)
if (ptree->size == MAXITEMS)
return true;
else
return false;
int TreeItemCount(const Tree * ptree)
return ptree->size;
bool AddItem(const Item * pi, Tree * ptree)
Trnode * new_node;
Trnode * like;
if (TreeIsFull(ptree))
fprintf(stderr,"Tree is full\\n");
return false; /* early return */
if ( ( like = SeekItem(pi, ptree).child ) != NULL) //找到相同的
// printf("Attempted to add duplicate item\\n");
// return false; /* early return */
like->item.frequency++;
return true; /* successful return */
new_node = MakeNode(pi); /* points to new node */
if (new_node == NULL)
fprintf(stderr, "Couldn't create node\\n");
return false; /* early return */
/* succeeded in creating a new node */
ptree->size++;
if (ptree->root == NULL) /* case 1: tree is empty */
ptree->root = new_node; /* new node is tree root */
else /* case 2: not empty */
AddNode(new_node,ptree->root); /* add node to tree */
return true; /* successful return */
int InTree(const Item * pi, const Tree * ptree)
Trnode * temp;
if ( (temp = SeekItem(pi, ptree).child) == NULL )
return 0;
else
return temp->item.frequency;
bool DeleteItem(const Item * pi, Tree * ptree)
Pair look;
look = SeekItem(pi, ptree);
if (look.child == NULL)
return false;
if (look.parent == NULL) /* delete root item */
DeleteNode(&ptree->root);
else if (look.parent->left == look.child)
DeleteNode(&look.parent->left);
else
DeleteNode(&look.parent->right);
ptree->size--;
return true;
void Traverse (const Tree * ptree, void (* pfun)(Item item))
if (ptree != NULL)
InOrder(ptree->root, pfun);
void DeleteAll(Tree * ptree)
if (ptree != NULL)
DeleteAllNodes(ptree->root);
ptree->root = NULL;
ptree->size = 0;
/* local functions */
static void InOrder(const Trnode * root, void (* pfun)(Item item))
if (root != NULL)
InOrder(root->left, pfun);
(*pfun)(root->item);
InOrder(root->right, pfun);
static void DeleteAllNodes(Trnode * root)
Trnode * pright;
if (root != NULL)
pright = root->right;
DeleteAllNodes(root->left);
free(root);
DeleteAllNodes(pright);
static void AddNode (Trnode * new_node, Trnode * root)
if (ToLeft(&new_node->item, &root->item))
if (root->left == NULL) /* empty subtree */
root->left = new_node; /* so add node here */
else
AddNode(new_node, root->left);/* else process subtree*/
else if (ToRight(&new_node->item, &root->item))
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
else /* should be no duplicates */
// if ( !strcmp(new_node->item.word, root->item.word) ) 按理来说执行不到这
// root->item.n++; //相同的单词 次数加一
static bool ToLeft(const Item * i1, const Item * i2)
int comp1;
if ((comp1 = strcmp(i1->word, i2->word)) < 0) //这改了
return true;
else
return false;
static bool ToRight(const Item * i1, const Item * i2)
int comp1;
if ((comp1 = strcmp(i1->word, i2->word)) > 0) //这也改了
return true;
else
return false;
static Trnode * MakeNode(const Item * pi)
Trnode * new_node;
new_node = (Trnode *) malloc(sizeof(Trnode));
if (new_node != NULL)
new_node->item = *pi;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
static Pair SeekItem(const Item * pi, const Tree * ptree)
Pair look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look; /* early return */
while (look.child != NULL)
if (ToLeft(pi, &(look.child->item)))
look.parent = look.child;
look.child = look.child->left;
else if (ToRight(pi, &(look.child->item)))
look.parent = look.child;
look.child = look.child->right;
else /* must be same if not to left or right */
break; /* look.child is address of node with item */
return look; /* successful return */
static void DeleteNode(Trnode **ptr)
/* ptr is address of parent member pointing to target node */
Trnode * temp;
if ( (*ptr)->left == NULL)
temp = *ptr;
*ptr = (*ptr)->right;
free(temp);
else if ( (*ptr)->right == NULL)
temp = *ptr;
*ptr = (*ptr)->left;
free(temp);
else /* deleted node has two children */
/* find where to reattach right subtree */
for (temp = (*ptr)->left; temp->right != NULL;
temp = temp->right)
continue;
temp->right = (*ptr)->right;
temp = *ptr;
*ptr =(*ptr)->left;
free(temp);
tree.h
/* tree.h -- binary search tree */
/* no duplicate items are allowed in this tree */
#ifndef _TREE_H_
#define _TREE_H_
#include <stdbool.h>
/* redefine Item as appropriate */
#define SLEN 20
typedef struct item
char word[SLEN];
int frequency;
Item;
#define MAXITEMS 10
typedef struct trnode
Item item;
struct trnode * left; /* pointer to right branch */
struct trnode * right; /* pointer to left branch */
Trnode;
typedef struct tree
Trnode * root; /* pointer to root of tree */
int size; /* number of items in tree */
Tree;
/* function prototypes */
/* operation: initialize a tree to empty */
/* preconditions: ptree points to a tree */
/* postconditions: the tree is initialized to empty */
void InitializeTree(Tree * ptree);
/* operation: determine if tree is empty */
/* preconditions: ptree points to a tree */
/* postconditions: function returns true if tree is */
/* empty and returns false otherwise */
bool TreeIsEmpty(const Tree * ptree);
/* operation: determine if tree is full */
/* preconditions: ptree points to a tree */
/* postconditions: function returns true if tree is */
/* full and returns false otherwise */
bool TreeIsFull(const Tree * ptree);
/* operation: determine number of items in tree */
/* preconditions: ptree points to a tree */
/* postconditions: function returns number of items in */
/* tree */
int TreeItemCount(const Tree * ptree);
/* operation: add an item to a tree */
/* preconditions: pi is address of item to be added */
/* ptree points to an initialized tree */
/* postconditions: if possible, function adds item to */
/* tree and returns true; otherwise, */
/* the function returns false */
bool AddItem(const Item * pi, Tree * ptree);
/* operation: find an item in a tree */
/* preconditions: pi points to an item */
/* ptree points to an initialized tree */
/* postconditions: function returns true if item is in */
/* tree and returns false otherwise */
int InTree(const Item * pi, const Tree * ptree);
/* operation: delete an item from a tree */
/* preconditions: pi is address of item to be deleted */
/* ptree points to an initialized tree */
/* postconditions: if possible, function deletes item */
/* from tree and returns true; */
/* otherwise the function returns false*/
bool DeleteItem(const Item * pi, Tree * ptree);
/* operation: apply a function to each item in */
/* the tree */
/* preconditions: ptree points to a tree */
/* pfun points to a function that takes*/
/* an Item argument and has no return */
/* value */
/* postcondition: the function pointed to by pfun is */
/* executed once for each item in tree */
void Traverse (const Tree * ptree, void (* pfun)(Item item));
/* operation: delete everything from a tree */
/* preconditions: ptree points to an initialized tree */
/* postconditions: tree is empty */
void DeleteAll(Tree * ptree);
#endif
petclub.c
/* petclub.c -- use a binary search tree */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "tree.h"
char menu(void);
void addpet(Tree * pt, Item * temp);
void droppet(Tree * pt);
void showpets(const Tree * pt);
void findpet(const Tree * pt);
void printitem(Item item);
void uppercase(char * str);
char * s_gets(char * st, int n);
int main(void)
Tree pets;
char choice;
Item temp;
FILE * fp;
if ( (fp = fopen("words.txt", "r")) == NULL ) //判断是否能打开
printf("Can't open words.txt!\\n");
exit(EXIT_FAILURE);
InitializeTree(&pets); //初始化树
while (fscanf(fp, "%s", temp.word) != EOF) //读入二叉树
// printf("%s\\n", temp.word); //好像好起来了
addpet(&pets, &temp);
while ((choice = menu()) != 'q')
switch (choice)
case 'l' : showpets(&pets);
break;
case 'f' : findpet(&pets);
break;
default : puts("Switching error");
puts("\\n");
DeleteAll(&pets);
puts("\\nBye.");
return 0;
char menu(void)
int ch;
puts("Nerfville Pet Club Membership Program");
puts("Enter the letter corresponding to your choice:");
puts("l) show list of pets f) find pets");
puts("q) quit");
while ((ch = getchar()) != EOF)
while (getchar() != '\\n') /* discard rest of line */
continue;
ch = tolower(ch);
if (strchr("lfq",ch) == NULL)
puts("Please enter an l, f or q:");
else
break;
if (ch == EOF) /* make EOF cause program to quit */
ch = 'q';
return ch;
void addpet(Tree * pt, Item * temp)
if (TreeIsFull(pt))
puts("No room in the club!");
else
uppercase(temp->word);
temp->frequency = 1;
AddItem(temp, pt);
void showpets(const Tree * pt)
if (TreeIsEmpty(pt))
puts("No entries!");
else
Traverse(pt, printitem);
void printitem(Item item)
printf("Word: %-19s frequency: %-19d\\n", item.word,
item.frequency);
void findpet(const Tree * pt)
Item temp;
int frequency;
if (TreeIsEmpty(pt))
puts("No entries!");
return; /* quit function if tree is empty */
puts("Please enter word you wish to find:");
s_gets(temp.word, SLEN);
uppercase(temp.word);
temp.frequency = 0;
printf("%s", temp.word);
if ( frequency = InTree(&temp, pt))
printf("is a member %d of frequency.\\n", frequency);
else
printf("is not a member.\\n");
void uppercase(char * str)
while (*str)
*str = toupper(*str);
str++;
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
CH17 Code answer 8:
pets.c
/* petclub.c -- use a binary search tree */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "tree.h"
char menu(void);
void addpet(Tree * pt);
void droppet(Tree * pt);
void showpets(const Tree * pt);
void findpet(const Tree * pt);
void printitem(Item item);
void uppercase(char * str);
char * s_gets(char * st, int n);
int main(void)
Tree pets;
char choice;
InitializeTree(&pets);
while ((choice = menu()) != 'q')
switch (choice)
case 'a' : addpet(&pets);
break;
case 'l' : showpets(&pets);
break;
case 'f' : findpet(&pets);
break;
case 'n' : printf("%d pets in club\\n",
TreeItemCount(&pets));
break;
case 'd' : droppet(&pets);
break;
default : puts("Switching error");
puts("\\n");
DeleteAll(&pets);
puts("Bye.");
return 0;
char menu(void)
int ch;
puts("Nerfville Pet Club Membership Program");
puts("Enter the letter corresponding to your choice:");
puts("a) add a pet l) show list of pets");
puts("n) number of pets f) find pets");
puts("d) delete a pet q) quit");
while ((ch = getchar()) != EOF)
while (getchar() != '\\n') /* discard rest of line */
continue;
ch = tolower(ch);
if (strchr("alrfndq",ch) == NULL)
puts("Please enter an a, l, f, n, d, or q:");
else
break;
if (ch == EOF) /* make EOF cause program to quit */
ch = 'q';
return ch;
void addpet(Tree * pt)
Item temp;
if (TreeIsFull(pt))
puts("No room in the club!");
else
puts("Please enter name of pet:");
s_gets(temp.petname,SLEN);
puts("Please enter pet kind:");
s_gets(temp.petkind[0],SLEN);
uppercase(temp.petname);
uppercase(temp.petkind[0]);
AddItem(&temp, pt);
void showpets(const Tree * pt)
if (TreeIsEmpty(pt))
puts("No entries!");
else
Traverse(pt, printitem);
void printitem(Item item)
int i;
printf("Pet: %-19s Kind:", item.petname);
for ( i = 0; i <= item.index; i++ )
printf(" %s", item.petkind[i]);
printf("\\n");
void findpet(const Tree * pt)
Item temp;
if (TreeIsEmpty(pt))
puts("No entries!");
return; /* quit function if tree is empty */
puts("Please enter name of pet you wish to find:");
s_gets(temp.petname, SLEN);
uppercase(temp.petname);
printf("%s ", temp.petname);
if (InTree(&temp, pt))
printf("is a member.\\n");
SpecialPet(&temp, pt);
else
printf("is not a member.\\n");
void droppet(Tree * pt)
Item temp;
if (TreeIsEmpty(pt))
puts("No entries!");
return; /* quit function if tree is empty */
puts("Please enter name of pet you wish to delete:");
s_gets(temp.petname, SLEN);
uppercase(temp.petname);
printf("%s ", temp.petname);
if (DeleteItem(&temp, pt))
printf("is dropped from the club.\\n");
else
printf("is not a member.\\n");
void uppercase(char * str)
while (*str)
*str = toupper(*str);
str++;
char * s_gets(char * st, int n)
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
find = strchr(st, '\\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\\0'; // place a null character there
else
while (getchar() != '\\n')
continue; // dispose of rest of line
return ret_val;
tree.c
/* tree.c -- tree support functions */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
/* local data type */
typedef struct pair
Trnode * parent;
Trnode * child;
Pair;
/* protototypes for local functions */
static Trnode * MakeNode(const Item * pi);
static bool ToLeft(const Item * i1, const Item * i2);
static bool ToRight(const Item * i1, const Item * i2);
static void AddNode (Trnode * new_node, Trnode * root);
static void InOrder(const Trnode * root, void (* pfun)(Item item));
static Pair SeekItem(const Item * pi, const Tree * ptree);
static void DeleteNode(Trnode **ptr);
static void DeleteAllNodes(Trnode * ptr);
static bool TestSame(const Item * i1, const Item * i2);
static void ToBeTrueIndex(Item * item);
/* function definitions */
void InitializeTree(Tree * ptree)
ptree->root = NULL;
ptree->size = 0;
bool TreeIsEmpty(const Tree * ptree)
if (ptree->root == NULL)
return true;
else
return false;
bool TreeIsFull(const Tree * ptree)
if (ptree->size == MAXITEMS)
return true;
else
return false;
int TreeItemCount(const Tree * ptree)
return ptree->size;
bool AddItem(const Item * pi, Tree * ptree)
Trnode * new_node;
Trnode * temp;
if (TreeIsFull(ptree))
fprintf(stderr,"Tree is full\\n");
return false; /* early return */
if ((temp = SeekItem(pi, ptree).child) != NULL)//传回来的可能是名字相同 也可能是名字种类都相同
if ( TestSame(pi, &temp->item) && (temp->item.index >= MAXLISTS) )//如果种类也相同 就返回错误
fprintf(stderr, "Attempted to add duplicate item\\n");
return false; /* early return */
else //只是名字相同
ToBeTrueIndex(&temp->item);
strcpy(temp->item.petkind[temp->item.index], pi->petkind[0]);
// printf("%s:%s\\n", temp->item.petname, temp->item.petkind[0]);
// printf("%s:%s\\n", temp->item.petname, temp->item.petkind[1]);
return true;
new_node = MakeNode(pi); /* points to new node */
if (new_node == NULL)
fprintf(stderr, "Couldn't create node\\n");
return false; /* early return */
/* succeeded in creating a new node */
ptree->size++;
if (ptree->root == NULL) /* case 1: tree is empty */
ptree->root = new_node; /* new node is tree root */
else /* case 2: not empty */
AddNode(new_node,ptree->root); /* add node to tree */
return true; /* successful return */
bool InTree(const Item * pi, const Tree * ptree)
return (SeekItem(pi, ptree).child == NULL) ? false : true;
bool DeleteItem(const Item * pi, Tree * ptree)
Pair look;
look = SeekItem(pi, ptree);
if (look.child == NULL)
return false;
if (look.parent == NULL) /* delete root item */
DeleteNode(&ptree->root);
else if (look.parent->left == look.child)
DeleteNode(&look.parent->left);
else
DeleteNode(&look.parent->right);
ptree->size--;
return true;
void Traverse (const Tree * ptree, void (* pfun)(Item item))
if (ptree != NULL)
InOrder(ptree->root, pfun);
void DeleteAll(Tree * ptree)
if (ptree != NULL)
DeleteAllNodes(ptree->root);
ptree->root = NULL;
ptree->size = 0;
//有点纠结这算是接口还是内部函数 但感觉肯定不算内部函数
void SpecialPet(const Item * pi, const Tree * ptree)
Trnode * temp;
int i;
temp = SeekItem(pi, ptree).child;
printf("Pet: %-19s Kind:", temp->item.petname);
for ( i = 0; i <= temp->item.index; i++ )
printf(" %s", temp->item.petkind[i]);
printf("\\n");
/* local functions */
static void InOrder(const Trnode * root, void (* pfun)(Item item))
if (root != NULL)
InOrder(root->left, pfun);
(*pfun)(root->item);
InOrder(root->right, pfun);
static void DeleteAllNodes(Trnode * root)
Trnode * pright;
if (root != NULL)
pright = root->right;
DeleteAllNodes(root->left);
free(root);
DeleteAllNodes(pright);
static void AddNode (Trnode * new_node, Trnode * root)
if (ToLeft(&new_node->item, &root->item))
if (root->left == NULL) /* empty subtree */
root->left = new_node; /* so add node here */
else
AddNode(new_node, root->left);/* else process subtree*/
else if (ToRight(&new_node->item, &root->item))
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
else /* should be no duplicates */
fprintf(stderr,"location error in AddNode()\\n");
exit(1);
static bool ToLeft(const Item * i1, const Item * i2)
int comp1;
if ((comp1 = strcmp(i1->petname, i2->petname)) < 0)
return true;
// else if (comp1 == 0 && //不用比较种类
// strcmp(i1->petkind, i2->petkind) < 0 )
// return true;
else
return false;
static bool ToRight(const Item * i1, const Item * i2)
int comp1;
if ((comp1 = strcmp(i1->petname, i2->petname)) > 0)
return true;
// else if (comp1 == 0 && //不用比较种类
// strcmp(i1->petkind, i2->petkind) > 0 )
// return true;
else
return false;
static Trnode * MakeNode(const Item * pi)
Trnode * new_node;
new_node = (Trnode *) malloc(sizeof(Trnode));
if (new_node != NULL)
new_node->item = *pi;
new_node->left = NULL;
new_node->right = NULL;
new_node->item.index = 0; //初始化节点的下标为0
return new_node;
static Pair SeekItem(const Item * pi, const Tree * ptree)
Pair look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look; /* early return */
while (look.child != NULL)
if (ToLeft(pi, &(look.child->item)))
look.parent = look.child;
look.child = look.child->left;
else if (ToRight(pi, &(look.child->item)))
look.parent = look.child;
look.child = look.child->right;
else /* must be same if not to left or right */
break; /* look.child is address of node with item */
return look; /* successful return */
static void DeleteNode(Trnode **ptr)
/* ptr is address of parent member pointing to target node */
Trnode * temp;
if ( (*ptr)->left == NULL)
temp = *ptr;
*ptr = (*ptr)->right;
free(temp);
else if ( (*ptr)->right == NULL)
temp = *ptr;
*ptr = (*ptr)->left;
free(temp);
else /* deleted node has two children */
/* find where to reattach right subtree */
for (temp = (*ptr)->left; temp->right != NULL;
temp 以上是关于C Primer Plus(第六版)第十七章 编程练习答案的主要内容,如果未能解决你的问题,请参考以下文章