抽象数据类型(ADT)的问题
list.h
#ifndef LIST_H_#define LIST_H_enum Bool {False, True}; /* 把Bool定义为类型, False,True是他的值 *//* 特定于程序的声明 */#define TSIZE 45 /* 存放片名的数组大小 */struct film { char title[TSIZE]; int rating;};/* 一般类型定义 */typedef struct film Item;typedef struct node{ Item item; struct node * next;} Node;typedef Node * List; /* 函数原型 *//* 操作: 初始化一个列表 *//* 操作前:plist指向一个列表 *//* 操作后:该列表被初始化为空列表 */void InitializeList(List * plist);/* 操作: 确定列表是否为空列表 *//* 操作前:plist指向一个已初始化的列表 *//* 操作后:如果该列表为空则返回True;否则返回False */Bool ListIsEmpty(const List * plist);/* 操作: 确定列表是否已满 *//* 操作前:plist指向一个已初始化的列表 *//* 操作后:如果该列表已满则返回True;否则返回fales */Bool ListIsFull(const List * plist);/* 操作: 确定列表中项目的个数 *//* 操作前:plist指向一个已初始化的列表 *//* 操作后:返回该列表中项目的个数 */unsigned int ListItemCount(const List * plist);/* 操作: 在列表尾部添加一个项目 *//* 操作前:item是要被增加到列表的项目 *//* plist指向一个已初始化的列表 *//* 操作后:如果可能的话,在列表末尾添加一个新项目 *//* 函数返回True;否则函数返回False */Bool AddItem(Item item, List * plist);/* 操作: 把一个函数作用于列表中的每个项目 *//* 操作前:plist指向一个已初始化的列表 *//* pfun指向一个函数,该函数接受 *//* 一个Item参数并且无返回值 *//* 操作后:pfun指向的函数被作用到 *//* 列表的每个项目一次 */void Traverse(const List * plist, void(* pfun)(Item item));/* 操作: 释放已分配的内存(如果有) *//* 操作前:plist指向一个已初始化的列表 *//* 操作后:为该列表分配的内存已被释放 *//* 并且该列表被置为空列表 */void EmptyTheList(List * plist);#endif#include <stdio.h>#include <stdlib.h>#include "list.h"/* 局部函数原型 */static void CopyToNode(Item item, Node * pnode);/* 接口函数 *//* 把列表设置为空列表 */void InitializeList(List * plist){ *plist = NULL;}/* 如果列表为空则返回真 */Bool ListIsEmpty(const List * plist){ if(*plist == NULL) return True; else return False;}/* 如果列表已满则返回真 */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;}/* 返回节点数 */unsigned int ListItemCount(const List * plist){ unsigned int count = 0; Node * pnode = *plist; /* 设置到列表的开始处 */ while(pnode != NULL) { ++count; pnode = pnode->next; /* 把l设置为下一个节点 */ } return count;}/* 创建存放项目的节点,并把它添加到 *//* 有plist指向的列表(较慢的实现方法)尾部 */Bool AddItem(Item item, List * plist){ Node * pnew; Node * scan = *plist; pnew = (Node *)malloc(sizeof(Node)); if(pnew == NULL) return False; /* 失败时退出函数 */ CopyToNode(item, pnew); pnew->next = NULL; if(scan == NULL) /* 空列表,因此把pnew */ *plist = pnew; /* 放在列表头部 */ else { while(scan->next != NULL) scan = scan->next; /* 找到列表结尾 */ scan->next = pnew; /* 把pnew添加到结尾处 */ } return True;}/* 访问每个节点并对它们分别执行由pfun指向的函数 */void Traverse(const List * plist, void(* pfun)(Item item)){ Node * pnode = *plist; /* 设置到列表的开始处 */ while(pnode != NULL) { (* pfun)(pnode->item); /* 把函数作用于列表中的项目 */ pnode = pnode->next; /* 前进到下一项 */ }}/* 释放malloc()分配的内存 *//* 把列表指针设置为NULL */void EmptyTheList(List * plist){ Node * psave; while(*plist != NULL) { psave = (*plist)->next; /* 保存下一个节点的地址 */ free(*plist); /* 释放当前节点 */ *plist = psave; /* 前进到下一个节点 */ }}/* 局部函数定义 *//* 把一个项目复制到一个节点中 */static void CopyToNode(Item item, Node * pnode){ pnode->item = item; /* 结构复制 */}
#include <stdio.h>#include <stdlib.h> /* 为exit()提供原型 */#include "list.h" /* 定义List,Item */void showmovies(Item item);int main(void){ List movies; // 疑惑,这里不是等同struct node * movies吗 Item temp; // 这个movies不是已经是一个指针了吗? /* 初始化 */ InitializeList(&movies); // 那这里为什么要用&movies? if(ListIsFull(&movies)) { fprintf(stderr, "No memory available! Bey!\n"); exit(EXIT_FAILURE); } /* 收集并存储 */ puts("Enter first movie title: "); while(gets(temp.title) != 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): "); } /* 显示 */ if(ListIsEmpty(&movies)) printf("No data entered.\n"); else { printf("Here is the movie list: \n"); Traverse(&movies, showmovies); } printf("You entered %d movies.\n", ListItemCount(&movies)); /* 清除 */ EmptyTheList(&movies); printf("Bey!\n"); return 0;}void showmovies(Item item){ printf("Movie: %s Rating: %d\n", item.title, item.rating);}