昨天我们说了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{ typedef struct node{ typedef struct 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 typedef struct TelPhone{ typedef struct node{ typedef struct list{ void InitializeList (List * plist); bool AddItem (iTem item, List * plist); void ShowListItem(const List* plist); void FreetheList (List * plist); #endif ---------------------------------------------- 这是一个大家新接触的玩意,可能对下面这个不解,没关系,我会在这里说的。 ------------------------------- #ifndef _MY_LIST_H_ #endif -------------------------------- 这个的目的是为了防止出现重复包含,好比在其他地方多次包含头文件,他也只会只会去访问一次。_MY_LIST_H_这是一个不重复的名字,也就是没有被定义过的名字,可以随便取,当然现在有种更方便的方式: ----------------------------- #pragma once ----------------------------- 只需这句话就好,作用和上面的一样。 现在,头文件接口以及定义好了,该是实现的接口的时候了。实现接口说道底就是用我们所学的知识把接口的功能所实现出来,到现在,我想大家都有这个底子了,我们直接写出头文件的实现程序就好,添加一个C文件,然后实现每个接口,不过今天实在有些晚了,接口的实现就留待明晚吧。 对了,今天尝试运行了下昨晚上我们的例子。发现里面最后释放内存的时候有点问题,不知道大家有没有发现,如果发现了,那恭喜你中将了,如果没发现,明晚上我们接着说。 ===================== 回复D(不区分大小写)直接查看目录。 |
|
来自: 昵称29398856 > 《第三天》