#define LIST_H_INCLUDED
//#include <stdbool.h>
#define bool int
#define false 0
#define true 1
//特定于程序的声明
#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,否则返回false
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_H_INCLUDED
List.c
static void CopyToNode(Item item,Node * pnode);
void InitializeList(List * plist)
{
*plist = NULL;
}
//函数原型
//操作:确定列表是否为空列表
//操作前:plist指向一个列表
//操作后:如果该列表为空返回true,否则返回false
bool ListIsEmpty (const List * plist)
{
if( *plist == NULL)
return true;
else
return false;
}
//函数原型
//操作:确定列表是否已满
//操作前:plist指向一个已初始化的列表
//操作后:如果该列表为满返回true,否则返回false
bool ListIsFull (const List * plist)
{
Node * pf;
pf = (List) malloc(sizeof(Node));
// if(pf)
// return true;
// else//不能这样写,因为pf != NULL ,也不能说明了pf为真。
// return false;
if(pf == NULL)
return true;
else
return false;
}
//函数原型
//操作:确定列表中项目的个数
//操作前:plist指向一个已初始化的列表
//操作后:返回该列表中项目的个数
unsigned int ListItemCount(const List * plist)
{
Node * pnode;
pnode = *plist;
unsigned int count=0;
while( pnode != NULL)
{
count++;
pnode = pnode->next;
}
return count;
}
//函数原型
//操作:在列表尾部添加一个项目
//操作前:item是要被增加到列表的项目
// plist指向一个已初始化的列表
//操作后:如果可能的话,在列表尾部添加一个新项目,
// 函数返回true,否则返回false
bool AddItem (Item item,List * plist)
{
Node * pnode;
Node * scan;//用来扫描
scan = *plist;
pnode = (List)malloc( sizeof(Node));
if(pnode == NULL)
{
//free(pnode);
return false;
}
CopyToNode(item,pnode);
pnode->next = NULL;
if(scan == NULL)
{
*plist = pnode;//好像问题就在这了
//scan = pnode;
}
else
{
while(scan->next != NULL)////这才是问题所在,如果写成了scan != NULL ,那么导致输出的时候只能输出一个。第一天调的我都快放弃了,第二天才终于调试成了。
scan = scan->next;//找到了plist的 末尾了。
scan = pnode;
}
return true;
}
//函数原型
//操作:把函数作用于列表中的每一个节点的操作
//操作前:plist指向一个已初始化的列表
// pfun指向一个函数,该函数接受
// 一个Item参数并且无返回值
//操作后:pfun指向的函数被作用到列表中的每一个项目一次
void Traverse (const List *plist,void (* pfun) (Item item))
{
Node * pnode;
pnode = *plist;
while( pnode != NULL )
{
(*pfun)(pnode->item);
pnode = pnode->next;
}
}
//函数原型
//操作:释放已分配的内存
//操作前:plist指向一个已初始化的列表
//操作后:为该列表分配的内存以释放,并且该列表被置为空列表
void EmptyTheList(List * plist)
{
List pnode,prev;
pnode = * plist;
while( pnode != NULL)
{
prev = pnode->next;
free(pnode);
pnode = prev;//这个地方是我错的地方。当时写成了pnode = prev->next ,程序直接崩溃了
}
}
void CopyToNode(Item item,Node * pnode)
{
pnode->item = item;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "list.h"//这在CB中时包含“list.h”,在VC中包含"list.c"
void showmovies(Item item);
int main(void)
{
List movise;
Item temp;
InitializeList(&movise);
if(ListIsFull(&movise))
{
fprintf(stderr,"列表已满safa!");
exit(1);
}
printf("输入电影的名字:\n");
while(gets(temp.title) != NULL && temp.title[0] != '\0')
{
puts("输入电影的级别:");
scanf("%d",&temp.rating);
while(getchar() != '\n')
continue;
if( !AddItem(temp,&movise) )
{
printf("内存已满!\n");
break;
}
if(ListIsFull(&movise))
{
printf("列表已满!");
break;
}
printf("输入电影的名字:\n");
}
printf("节点的个数为:%d\n",ListItemCount(&movise));
//显示
if(ListIsEmpty(&movise))
{
printf("没有电影!\n");
}
else
{
printf("这是电影的列表:\n");
Traverse(&movise,showmovies);
}
EmptyTheList(&movise);
return 0;
}
void showmovies(Item item)
{
printf("title : %s rating : %d\n",item.title,item.rating);
}