抽象数据类型(ADT)的问题

ProgrammingRing 2010-10-30 10:52:12
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


list.c

#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; /* 结构复制 */
}



films3.c

#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);
}


films3.c里我用//标出了不明白的地方,请各位说说,不是很明白啊
...全文
201 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
hsk0408 2012-04-08
  • 打赏
  • 举报
回复
这是普拉塔的 C Primer Plus 第17章的一个程序清单,楼主你的版本是哪一版?我的书上有很多错误,比如在
films3.c中你的是 ListIsFull(&movies),ListIsEmpty(&movies),我的书上是 ListIsFull(movies),ListIsEmpty(movies),这是不是错误,麻烦懂得哥们给说一下,谢谢
zff869030831 2010-10-30
  • 打赏
  • 举报
回复
感觉你这代码写的挺有意思的!首先你的问题,你的函数原型是List *pList;面List本来就是指向一个结点的指针,所以List *pList,就是指向结点指针的指针,然后这样做的原因也很简单,因为指向链表的指针有可能会发生变化,所以就要这样子传递,当然还有一些其它的方法,另外你还专门写了一个ListIsFull,我还是第一次见到这样子写的,呵呵,感觉没有必要,另外有些地方可以改进,AddItem可以不用那样写的,
ProgrammingRing 2010-10-30
  • 打赏
  • 举报
回复
哦,刚刚Google了下,要是想指向一个指针变量,就得是指向指针的指针,如果不用&,*plist得到的只是movies的地址,加上&,*plist从传送过来的地址取到movies的值。我这样理解对吗?
ProgrammingRing 2010-10-30
  • 打赏
  • 举报
回复
去Google下指针的指针。。。
yg2362 2010-10-30
  • 打赏
  • 举报
回复
typedef Node * List List是指针类型
void InitializeList(List * plist);这个函数的参数是指针的指针
所以movies传递给InitializeList必须加上&符号

ProgrammingRing 2010-10-30
  • 打赏
  • 举报
回复
- - !!还是不是很明白啊。。
無_1024 2010-10-30
  • 打赏
  • 举报
回复
因为你输入的东西是一个节点 就存在节点里面 然后将节点的值赋给指针变量
ProgrammingRing 2010-10-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zff869030831 的回复:]

感觉你这代码写的挺有意思的!首先你的问题,你的函数原型是List *pList;面List本来就是指向一个结点的指针,所以List *pList,就是指向结点指针的指针,然后这样做的原因也很简单,因为指向链表的指针有可能会发生变化,所以就要这样子传递,当然还有一些其它的方法,另外你还专门写了一个ListIsFull,我还是第一次见到这样子写的,呵呵,感觉没有必要,另外有些地方可以改进,AddIt……
[/Quote]
这是书上的一个例题。。

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧