第二十九讲 正确的List(数组)

 

原本打算说点新内容的,但想想我们挖了一个坑,却没有来填,而有些朋友又没能看出其中端倪,这着实可恨,所以为了让大家都明白我们这个List为什么是错的,所以我想了下,还是决定把正确的实现方法放出来,也好让还没弄明白是怎么回事的朋友不必云里雾里。
为什么会有我们这个错误的实现方法呢?起源于开始我着手实现接口时候犹豫的那一瞬间,原本我是照着常规的方法写道:
——————————————–
typedef struct TelPhone{
char Name[20];

char TelNumber[20];

}iTem;


typedef struct node{
iTem item;

node* next;

}Node;


—————————————–
写到这里的时候,突然想到C++里面的class的派生和继承,于是就想不如弄个陷进在这里,看是否有人会跳,于是我又在下面加了这样的代码:
————————————–
typedef struct list{
Node* head;
list     *next;
int  size;

}List;


————————————-
当我敲下这段代码的时候,我就开始想,这种实现方师傅放在C里面有些麻烦了,他不同于C++的代码重用,所以想要实现接口确实不是那么一回事,当时我犹豫了下,要不要这样拿出来呢?如果大家C语言功底够厚,可能会容易看出来这是无法实现的,因为如果想要通过这种方式去实现List接口相当于实现了两个list,这是C里面及不容许,因为大家都知道资源的可贵。
既然这是一个陷阱,那么要怎么瞒天过海呢?这就是一个难题了。相信大家都被我贴的图给弄晕了,这好像看起来没问题,是啊,确实没问题,我们输入的两个联系人都能够正常显示,但是为什么我要告诉大家这是一个有问题的实现呢?问题到底出在哪里?实践才能检验真伪,相信到现在还没人反馈出来,多半是大家都只看却没真正的把代码敲在编译器里面运行看看。不管大家有没有验证,我觉得我还是有义务把正确的实现给放出来,否则不但不能授人以渔,反而还误人子弟。
其实这个实现主要考察的还是指针和数组的使用,很多人都说,C/C++的语法不多,但是确实最难学好的一门编程语言,通过这个综合实例,也可见一斑。
下面我们先看第一种实现,我们用数组的形式来实现,这是最简单的,但是功能不如用指针的方式。
———————————————
//my_list.h
#ifndef _MY_LIST_H_
#define _MY_LIST_H_

typedef struct TelPhone{
char Name[20];

char TelNumber[20];

}iTem;


typedef struct node{
iTem item;

node* next;

}Node;


#define MAXSIZE 100
typedef struct list{
iTem BookPhone[MAXSIZE];

int  size;

}List;



void InitializeList (List *plist);

bool ListIsEmpty (const List * plist);

bool ListisFull (const List * plist);

unsigned
int ListItemCount (const List * plist);

bool AddItem (iTem item, List * plist);

void ShowListItem(const List* plist);

void FreetheList (List * plist);


#endif
———————————————
接口没有变化,不同的是在我们声明新类型的时作了稍微的修改,所以实现起来变得很简单。如果大家没有看出差别,可以回头去看看我们那个有问题的声明方式。
——————————————-
#include <stdio.h>#include <stdlib.h>#include “my_list.h”
//全局函数,把元素添加进列表
static
void CopyToNode(Node * pNode,iTem item)
{
pNode->item = item;

}
//初始化
void InitializeList(List *plist)
{
plist->size = 0;

}
//确认列表是否为空
bool ListIsEmpty(const List* plist)
{
if(plist->size == 0)

return true;

return false;

}
//确认列表是否已满
bool ListisFull(const List* plist)
{
if(plist->size == MAXSIZE)

return true;

else

return false;

}
//返回元素个数
unsigned
int ListItemCount(const List * plist)
{

return plist->size;

}
//添加元素,由于我们实现的是单向链表,所以使用从尾部添加
bool AddItem (iTem item, List * plist)
{
if(plist->size == MAXSIZE)

return false;

else
{
plist->BookPhone[plist->size++] = item;

return true;

}
}
//显示列表中的元素
void ShowListItem(const List* plist)
{
if(plist->size == 0)
printf(“Not any data!!!”);

else
{
for(int i=0;

i<plist->size;

i++)
printf(“%-20s : %sn”,plist->BookPhone[i].Name,
plist->BookPhone[i].TelNumber);

}
}
//释放

void FreetheList (List * plist)
{
plist->size = 0;

}
—————————————————–
因为接口没有变化,所以我们的驱动函数不需要更改就可以直接运行,是不是觉得很方便呢?不过这个List的缺陷却因为他是数组的原因,所以使得他不能够收放自如,当然,要想让他能够收放自如我们可以使用指针的方式。接口还是这个接口,不过实现方式却大不一样,这个数组的方式比起来,难了不少,我们明天再说。

发表评论