首页 > 编程知识 正文

c语言中抽象数据类型怎么定义,抽象数据类型的实现

时间:2023-05-05 11:59:43 阅读:231832 作者:3574

C语言实现抽象数据类型(ADT) 什么是抽象数据类型(ADT)C语言通过怎样的方式来实现ADT举例参考资料


什么是抽象数据类型(ADT)

C/C++有固有数据类型,比如int,float,double。int a; 就声明且定义出一个int型变量(或者叫数据对象);但光有这些固有的数据类型不能满足编程的可读、可复用、可维护性的要求。比如想要处理一个现实中“学生老迟到的睫毛”的对象,如果能有一个名叫“Student”的“学生”类型(好比“int”类型),通过像Student Xiaoming; 这样的语句,就可以定义出一个名为Xiaoming的学生类型对象(就好比“int a;”定义出一个名为a的int整型变量那样),那就好办了。同样的,如果能实现一个名叫“Stack”的栈数据类型,名叫“List”的链表数据类型,名叫“Car”的汽车数据类型,名叫“Plane”的飞机数据类型……,就很方便了。用C++的话说来就是Class Student{……}; Student Xiaoming; Class Stack{……}; Stack my_stack; Class Plane{……}; Plane Boing747; ,如此我们自定义出想要的数据类型,然后使用它。

用面向对象的语言和语法,更容易理解抽象数据类型,就像上面写的那样。“抽象、封装、继承、多态”是面向对象的4个特点,抽象就是把同一数据类型的共有特征概括出来。一个数据对象有四个属性:V(值),A(地址),N(名称),T(类型)。在程序编译完成后,可执行程序里面产生了信息缺失:程序中的数据对象只有地址和值,没有数据类型、数据名称、数据意义等信息了。所以抽象完成在编写程序的时候。抽象得出的数据类型的特点包含两个方面:属性和方法。拿“Student”学生类型来说,姓名,性别,年级,班级,成绩等就是学生类型的“属性”,可以由各种变量表示;努力学习,升学,考试,翘课,挂科,被加分,被表扬,被扣分,被处分等就是学生类型的“方法”,可以由各种函数表示。方法可以对属性进行操作,比如“被加分”会修改“成绩”这个属性。封装就是通过一定的语法形式,把抽象出来的属性和方法“捆绑在一起”,在形式上写成一个整体,使人从形式上就能看出两者的紧密关系,这个过程叫封装。通过封装,还可以将部分属性和方法隐藏起来,对外只留一定的接口(函数),实现“信息隐藏”。封装可以理解为抽象的具体表现形式。

C语言实现抽象数据类型不如面向对象语言来的方便,不过抽象和封装还是能实现的。


C语言通过怎样的方式来实现ADT

C语言用不完整类型作为唯一的封装工具。不完整类型的描述是:描述了对象但缺少定义对象大小所需的信息。

例如声明 struct t; //声明不完整类型t。

这告诉编译器t是一个结构标记,但并没有描述结构的成员,所以,编译器没有足够的信息去确定该结构的大小,sizeof不能用在不完整类型上,也不能用它来声明变量:

struct t s;(这是错误的)。

但是可以定义一个指针类型指向不完整类型:

typedef struct t *T;

这个类型定义表明,类型T 的变量是指向标记为t的结构的指针。现在可以声明类型T的变量,将其作为函数的参数进行传递,并可以执行其他合法的指针运算(指针的大小并不依赖于它指向的对象,这就解释了为什么C语言允许这种行为)。不完整类型的信息将在程序的其他地方补充完整。


举例

举学生数据类型的例子说明利用不完整类型实现抽象数据类型:实现抽象数据类型,形式上还是用头文件,源文件的方式,头文件是供其他人看的,供其他模块其他客户调用的“库”、“模块对外接口”,在头文件里定义学生抽象数据类型,并给出代表学生类型“方法”(升学,考试,翘课,挂科……)的函数的原型:

studentADT.h

#ifndef STUDENTADT_H#define STUDENTADT_Hstruct Student; //声明不完整类型Studenttypedef struct Student * PStudent;//定义学生抽象数据类型,客户用PStudent而不是Student来定义ADTPStudent create(char * name, char * school, int id, int age );void destroy(PStudent s);void JiaFen(PStudent s, int score); //被加分void KouFen(PStudent s, int score); //被扣分void ShengXue(PStudent s, char * school); //升学,可能升到其他学校去了void ShowInfo(PStudent s); //显示ADT变量的具体信息//……可能还有其他函数实现各种学生类型的“方法”#endif

声明的struct这个结构体里具体有哪些变量,也就是学生类型具体细节(比如学生成绩既有可能是用数组存储的,也有可能是用链表存储的),都不在这里体现,在这里隐藏起来。在源文件中再具体实现。客户不能访问struct结构的成员。PStudent才是为客户定义的,供客户使用的学生抽象数据类型(而不是Student类型),包含此头文件的客户可以使用PStudent类型的变量,调用这个头文件中的函数。
抽象数据类型需要create和destroy这样的函数。int a;//内置类型的声明,直接它自己就分配出一个int型的空间。,而抽象数据类型是自定义出来的,需要我们自己手动分配和释放空间。
客户可以这样使用学生ADT:

PStudent Xiaoming;Xiaoming = cteate("Xiaoming", "Peking University", 20200001, 18);//定义出一个Xiaoming的学生ADT变量,并做初始化:他的名字叫“Xiaoming”,学校是北京大学,学号20200001,年龄18岁。JiaFen(Xiaoming, 2);//老迟到的睫毛被加分了,加了2分。KouFen(Xiaoming, 1);//老迟到的睫毛被扣分了,扣了1分。ShengXue(Xiaoming, "TsingHua University");//老迟到的睫毛升学去了清华。destroy(Xiaoming);//不再使用Xiaoming变量后,释放动态分配的内存,以免内存泄漏

studentADT.c可能像这样实现:

#include <stdio.h>#include <stdlib.h>#include "studentADT.h"struct Student { char name[20]; char school[30]; int id; int age; int score;};PStudent create(char * name, char * school, int id, int age ) { PStudent s = malloc(sizeof(struct Student)); strcpy(s->name, name); strcpy(s->school, school); s->id = id; s->age = age; s->score = 0; return s;}void destroy(PStudent s) { free(s); }void JiaFen(PStudent s, int score) { s->score += score; }void KouFen(PStudent s, int score) { s->score -= score; }void ShengXue(PStudent s, char * school) { if (s->score >= 100) strcpy(s->school, school);// 分数够了就可以升学}void ShowInfo(PStudent s){ printf("%s, %s, %d, %d, %dn", s->name, s->school, s->id, s->age, s->score);}
参考资料

《C语言程序设计:现代方法》K.N.wndgb; 《新标准C++程序设计教程》jmdhlg;《基于Linux的C++》MOOC课程,乔林

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。