第二十七讲 综合运用C(3)

      昨天我们说了List,所以我们今天的任务就是实现这个List,不过我们今天要实现的是单向的链表,至于双向的就留待大家去思考。
第一步,我们要做的是构造接口,构造接口的第一步我们应该先我们所需要的类型构造出来:
————————
struct  TelPhone{
           char Name[20];


           char  TeiNumber[20];


};


———————-
今天我们并没有在这个结构里面添加一个指向该类型的指针,为什么呢?这样的话岂不是不能实现链表了吗?当然能,今天我们要构造的是一个通用型的,所以我们就不要在再目标类型里面再添加指向该类型的指针,那么我们该怎么办呢?嗯,想起来,有个关键词还没给大家说,不过现在说不迟,我以前也说过,因为我们这里不是专业的,所以不会那么专业的一字一句的说,我们只说一些经常用的,不过今天我们要说的这个关键字也是常用的,尤其是我们现在准备开发程序的时候更要应该用好这个关键字,我想熟悉C/C++的朋友应该想到我们今天要说的就是:
—————-
typedef
—————
这个关键字的意思大概就是像我们给别人取外号一样,比如说,你叫张三,有人非得叫你李四一样,反正不管李四是不是你的名字,但是大家都知道叫李四就是叫你。
—————————-
typedef  TelPhone  iTem;
—————————
上面这句话的意思就是让iTem表示TelPhone,现在想必大家应该都懂了吧,不过为了养成大家良好的编程习惯,我们应该这样写会更好一些。
—————————–
tepedef struck TelPhone iTem;
——————————
因为我们的TelPhone是我们自定义的类型,所以我们了解,但是别人不一定会了解,如果我们再加上struck这个关键字,别人就会知道这是一个自定义的类型,也不会造成费解。
当然我们还可以有另一种写法:
———————————-
typedef struct TelPhone{
             char    Name[20];


             char    TelNumber[20];


}iTem;


———————————
这样的话,当我们声明一个新类型的时候就给他取了一个外号,iTem既是TelPhone,为什么我们要给TelPhone取个外号呢?因为这个外号正是实现接口的关键,接下来,我们怎么从这个外号取得接口。
———————————
typedef stuck node{
             iTem item;
             node* next;
}Node;
———————————-
到了这一步应该熟悉了吧,所以我们把我们想要的类型传递到这个结构里面来,然后再在这里实现连接,接下来的东西和我们昨天的差不多,但是有一点不同,那就是今天我们做的是抽象数据。
windows系统的源代码我们看得见吗?API的源代码我们看得见吗?看不见,他被所在微软总部的保险箱里面,或者被放在比尔盖茨的书房中,没人知道,通常情况下,我们都只是根据他实现的功能和微软给我们提供的接口来推断,推敲出所谓的伪代码,看好,这里说的伪代码,伪代码就是不是真的。所以,我们要做的也是这样,我们只需要提供一个接口,别人只需要使用这个接口便好,至于内部实现就不需要去管他,我们可以给使用的人提供一份文档,知道这些接口是实现什么功能的就好,当然我们今天不打算写一个动态链接库(Dll),动态链接库留待我们学习C++的时候再来讨论。那么,接口应该放在哪里呢?当然是头文件里。怎么创建一个头文件呢?如果大家用的是VS6.0的话,先创建一个控制台工程,然后选择文件,添加head文件,然后我们把他命名为my_list,如果大家用的是VS8以上的版本,在创建好工程之后,在解决方案里面的头文件处右键添加头文件即可,最终结果像下面的这样。
————————————–
//my_list.h
typedef struct TelPhone{
char Name[20];

char TelNumber[20];

}iTem;


typedef struct node{
iTem item;

node* next;

}Node;


typedef struct list{
node* head;

int  size;

}List;


————————————-
经过三个结构的嵌套,我们终于得到了我们想要的List,这样我们就可以使用List,比如现在我们想要让他来申请一个通讯录,可以这样做:
————————–
List   BookPhone;
————————–
当然,声明一个对象就得初始化,所以我们还得初始化,所以我们还得添加一个接口,用来初始化List对象。
—————————————-

void InitializeList (List * plist);

—————————————–
有了这个接口之后,我们便可以通过这样的方式来初始化List对象了。
—————————————–
InitializeList(&

BookPhone);
—————————————–
光有初始化还不够,比如说我们还要添加联系人,所以我们得加上这个接口:
—————————————————
bool AddiTtem (iTem item, List * plist);


—————————————————
当然,添加一个元素的同时我们还得保证列表是否已满,是否为空等等,所以我们还得添加下面的接口:
———————————————–
bool ListIsEmpty (const List * plist);
bool ListisFull (const List * plist);
———————————————–
既然我们考虑到List会有满的情况,那么我们就应该考虑里面的个数,所以我们还得添加一个计算当前列表元素的个数的接口:
———————————————————–
unsigned
int ListItemCount (const List * plist);


————————————————————
当然,我们还需要显示联系人信息,所以还得提供一个接口:
————————————————

void ShowListItem(const List* plist);


————————————————-
现在我们基本可以得到一个简单的List接口了,下面是完整的头文件:
——————————————
//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;


typedef struct list{
node* head;

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
———————————————-
这是一个大家新接触的玩意,可能对下面这个不解,没关系,我会在这里说的。
——————————-
#ifndef _MY_LIST_H_
#define _MY_LIST_H_

#endif
——————————–
这个的目的是为了防止出现重复包含,好比在其他地方多次包含头文件,他也只会只会去访问一次。_MY_LIST_H_这是一个不重复的名字,也就是没有被定义过的名字,可以随便取,当然现在有种更方便的方式:
—————————–
#pragma once
—————————–
只需这句话就好,作用和上面的一样。
现在,头文件接口以及定义好了,该是实现的接口的时候了。实现接口说道底就是用我们所学的知识把接口的功能所实现出来,到现在,我想大家都有这个底子了,我们直接写出头文件的实现程序就好,添加一个C文件,然后实现每个接口,不过今天实在有些晚了,接口的实现就留待明晚吧。
对了,今天尝试运行了下昨晚上我们的例子。发现里面最后释放内存的时候有点问题,不知道大家有没有发现,如果发现了,那恭喜你中将了,如果没发现,明晚上我们接着说。

发表评论