C_Primer_Plus_Chapter17_exercise2
题目
Suppose list.h(Listing 17.3)uses the following definition of a list:
typedef struct list
{
Node * head; /* points to head of list */
Node * end; /* points to end of list */
}list;
Rewrite the list.c(Listing 17.5) functions to fit this definition and test the resulting code with the film3.c(Listing17.4) program.
解答
list.h
#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
list.c
#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 && plist->end == NULL)
return true;
else
return false;
}
/* returns true if list is full */
bool ListIsFull(const List * plist)
{
Node * pt;
bool full;
(void) plist; /* not needed: probe by malloc() */
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;
}
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;
plist->end = pnew;
}
else
{
plist->end->next = pnew;
plist->end = 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;
plist->head = plist->head->next;
free(psave); /* free current node */
}
plist->end = NULL;
}
/* local function definition */
/* copies an item into a node */
static void CopyToNode(Item item, Node * pnode)
{
pnode->item = item; /* structure copy */
}
film3.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')
{
int status, ch;
puts("Enter your rating <0-10> in integer:");
while ((status = scanf("%d", &temp.rating)) != 1 ||
temp.rating < 0 || temp.rating > 10)
{
if (status == EOF)
break;
puts("Wrong input! Please enter a rating in integer:");
while ((ch = getchar()) != '\n' && ch != EOF)
continue; /* dispose of bad input */
}
if (status == EOF)
break; /* input ended, stop gathering */
while ((ch = getchar()) != '\n' && ch != EOF)
continue; /* dispose of rest of line */
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;
}
浙公网安备 33010602011771号