c语言实现抽象数据类型(信息隐藏)

注:本篇博客的内容和列子都来源于书籍《c和指针》,是lc整理成篇的,推荐大家读读这本书。


所谓抽象数据类型,是指模块具有功能说明和接口说明,前者说明模块所执行的任务,后者定义模块的使用。但是,模块的用户并不需要知道模块实现的任何细节,而且除了那些定义好的接口之外,用户不能以任何方式访问模块,这个定义觉得是不是和面向对象语言的类的定义类似呢,c没提供类这种结构,c实现抽象数据类型的武器其实是static关键字。


c语言有三种链接属性,即external(外部),internal(内部)和none(无)。没有链接属性的标识符(none)总是被当作单独的实体,也就是说该标识符的多个声明被当作独立不同的实体。属于Internal链接属性的标志符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体,最后,属性external链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体。


关键字static和extern用于在声明中修改标识符的链接属性,如果某个声明在正常情况下具有external链接属性,在它前面加上static关键字可以使它的链接属性变为internal。


一般而言,函数参数,函数局部变量(没有extern属性修饰)的变量都具有none的链接属性;全局变量,函数声明,函数定义如果没有static修饰,则具有external链接属性,如果有static属性修饰,则具有Internal链接属性。


注意:1 static只对缺省链接属性为extern的声明才有改变链接属性的效果,如下列f。

           2 为一个变量指定extern属性,就可以访问在任何位置定义的这个实体,如下列k。

           3 当extern关键字用于源文件中一个标识符的第1次声明时,它指定该标识符具有extern属性,如下列b。

int a;
static int b;

int c(int d)
{
int e;
static int f;//f为none连接属性
extern int k;//k本来是none链接属性,现在指定了extern属性,就有extern链接属性
extern int b;//b第二次声明为extern,不修改b的链接属性,b仍为intern链接属性
}

static关键字的作用介绍清楚了,下面写一个demo,看看怎么实现抽象数据类型,怎么实现信息隐藏,头文件addrlist.h里面声明了接口lookup_address,lookup_phone,外面可以调用,但addrlist.c文件里面的find_entry函数,外面是不能调用的,因为该函数具有static属性,即不是external链接属性。

/*
** Declarations for the address list module.
*/

/*
** Data characteristics
**
**	Maximum lengths of the various data (includes space for the
**	terminating NUL byte), and maximum number of addresses.
*/
#define	NAME_LENGTH	30		/* longest name allowed */
#define	ADDR_LENGTH	100		/* longest address allowed */
#define	PHONE_LENGTH	11		/* longest phone # allowed */

#define	MAX_ADDRESSES	1000		/* # of addresses allowed */

/*
** Interface functions
**
**	Given a name, find the corresponding address.
*/
char const *
lookup_address( char const *name );

/*
**	Given a name, find the corresponding phone number.
*/
char const *
lookup_phone( char const *name );

/*
** Abstract data type to maintain an address list.
*/

#include "addrlist.h"
#include <stdio.h>

/*
**    The three parts to each address are kept in corresponding
**    elements of these three arrays.
*/
static    char    name[MAX_ADDRESSES][NAME_LENGTH];
static    char    address[MAX_ADDRESSES][ADDR_LENGTH];
static    char    phone[MAX_ADDRESSES][PHONE_LENGTH];

/*
**    This routine locates a name in the array and returns the
**    subscript of the location found.  If the name does not exist,
**    -1 is returned.
*/
static int
find_entry( char const *name_to_find )
{
    int    entry;

    for( entry = 0; entry < MAX_ADDRESSES; entry += 1 )
        if( strcmp( name_to_find, name[ entry ] ) == 0 )
            return entry;

    return -1;
}

/*
**    Given a name, look up and return the corresponding address. 
**    If the name was not found, return a NULL pointer instead.
*/
char const *
lookup_address( char const *name )
{
    int    entry;

    entry = find_entry( name );
    if( entry == -1 )
        return NULL;
    else
        return address[ entry ];
}

/*
**    Given a name, look up and return the corresponding phone
**    number. If the name was not found, return a NULL pointer
**    instead.
*/
char const *
lookup_phone( char const *name )
{
    int    entry;

    entry = find_entry( name );
    if( entry == -1 )
        return NULL;
    else
        return phone[ entry ];
}


1. 本演示程序中,集合元素限定为数字,大小由用户输入。集合中数字顺序不限,且一旦出现重复字符或非法字符,程序能自动滤去。输出的运算结果中将不含重复数字或非法字符,且按照从小到大的顺序输出。<br>2. 演示程序以用户和计算机的对话方式执行,即在计算机上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令;相应的数据输入和运算结果显示在其后。<br>3. 程序执行的命令包括:<br>(1)构造集合1;(2)构造集合2;(3)判断某数是否为集合元素;(4)添加元素;(5)删除元素;(6)求并集(存入集合1中);(7)求交集(存入集合3中);(8)输出集合1;(9)输出集合2;(0)退出。<br>“构造集合1”和“构造集合2”时,需以整型数字形式键入集合元素。<br><br>为实现上述程序功能,以线性链表表示集合。为此,需要两个抽象数据类型:线性表和集合。<br>1. 线性表的抽象数据类型定义为:<br> ADT LinkList{<br> 数据对象:D={ | IntSet,i=1,2,…,n,n 0}<br> 数据关系:R1={< , >| , D, < ,i=2,…,n}<br> 基本操作:<br> InitList(*L)<br> 操作结果:构造一个空的线性链表L。<br> IsElement(*L,e)<br> 初始条件:线性表L已存在。<br> 操作结果:若e是L的数据元素,返回1,否则返回0。<br> Append(*L,e)<br> 初始条件:线性表已存在。<br> 操作结果:按照由大到小的顺序往线性表里插入元素e,不允许重复元素。<br> Delete(*L,e)<br> 初始条件:线性表已存在。<br> 操作结果:在L中删除元素e。<br> }ADT LinkList<br>2. 集合的抽象数据类型定义为:<br> ADT LinkSet {<br> 数据对象:D={ | IntSet,i=1,2,…,n,n 0}<br> 数据关系:R1={}<br> 基本操作:<br> CreatSet(*L)<br> 初始条件:s为整型数组。<br> 操作结果:生成一个由s中数字构成的集合。<br> Union(*S1,*S2)<br> 初始条件:集合S1和S2存在。<br> 操作结果:生成一个由S1和S2的并集构成的集合,返回到S1。<br> Intersection (*S1,*S2)<br> 初始条件:集合S1和S2存在。<br> 操作结果:生成一个由S1和S2的交集构成的集合,返回到S1。<br> PrintSet (*S)<br> 初始条件:集合S已存在。<br> 操作结果:依次显示集合S中的全部元素。<br> }ADT LinkSet<br><br><br>带菜单<br>Turbo c 3.0编写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值