目录
文章目录
前言
一、数据类型描述
二、源代码(扩展名.cpp)
1.引入库
2.读入数据
代码段的理解
前言
作为新手,模仿+理解+运用是学习的三个阶段
本文以理解代码段为学习目标
一、数据类型描述
三元组Triplet的定义:
ADT Triplet{
数据对象:D={e1, e2, e3|e1, e2, e3属于ElemType(定义了关系的某个集合)}
数据关系:R={
基本操作:
initTriplet(&T, v0, v1, v2)
初始条件:
操作结果:构造三元组T,元素e1, e2和e3分别被赋予参数v1, v2, v3的值。
destroyTriplet(Triplet T)
初始条件:三元组T已经存在。
操作结果:销毁三元组T。
printTriplet(T)
初始条件:三元组T已经存在。
操作结果:显示三元组T。
getElem(T, i, &e)
初始条件:三元组T已经存在, 1 <= i <= 3。
操作结果:用e返回三元组T的第i(1~3)个元素的值。
putElem(&T, I, e)
初始条件:三元组T已经存在, 1 <= i <= 3。
操作结果:用e的值取代三元组T的第i(1~3)个元素的值。
getMax(T, &e)
初始条件:三元组T已经存在。
操作结果:用e返回三元组T的最大值。
getMin(T, &e)
初始条件:三元组T已经存在。
操作结果:用e返回三元组T的最小值。
isAscending(T)
初始条件:三元组T已经存在。
操作结果:如果T的三个元素按升序排序,则返回OK,否则返回ERROR。
isDescending(T)
初始条件:三元组T已经存在。
操作结果:如果T的三个元素按降序排序,则返回OK,否则返回ERROR。
Add(T1, &T2)
初始条件:存在三元组T1, T2。
操作结果:用T2带回操作结果。
mulCoef(&T1, coef)
初始条件:三元组T1已经存在。
操作结果:用T1带回乘系数之后都结果。
}ADT Triplet
二、源代码(扩展名.cpp)
1.引入库
代码如下(示例):
# include//标准的输入输出函数库 # include //使用动态分配内存必须引入的函数库 # define OK 1 //宏定义,下同 # define ERROR 0 # define OVERFLOW -2 typedef int Status; //给int起了个别名(Status),下同 typedef float ElemType; typedef ElemType *Triplet; //声明Triplet为指向任意类型(此处为ElemType)的指针 //三元组的初始化// void initTriplet(Triplet &T, ElemType v0, ElemType v1, ElemType v2) { //动态分配内存 T = (ElemType *)malloc(3*sizeof(ElemType)); if (!T) { printf("分配内存失败!"); exit(OVERFLOW); } T[0] = v0; T[1] = v1; T[2] = v2; } //销毁三元组// void destroyTriplet(Triplet &T) { free(T); printf("分配内存已释放!"); exit(0); } //销毁三元组// void destroyTriplet_2(Triplet &T) { delete []T; printf("分配内存已释放!"); exit(0); } //显示三元组 void printTriplet(Triplet T) { printf("调用初始化函数后,T的三个值为:%.1f,%.1f,%.1fn", T[0], T[1], T[2]); } // 用e获取T的第i(1~N)个元素的值// Status getElem(Triplet T, int i, ElemType &e) { if (i < 1 || i > 3) return ERROR; else e = T[i-1]; return OK; } // 置T的第i元的值为e Status putElem(Triplet &T, int i, ElemType e) { if (i < 1 || i > 3) return ERROR; else T[i-1] = e; return OK; } //用e返回值指向T的最大元素的值 ElemType getMax(Triplet T, ElemType &e) { if (T[0] > T[1]) e = T[0]; else e = T[1]; if (T[2] > e) e = T[2]; printf("三元组T的最大元素的值为:%4.2fn",e); return e; } //用e返回值指向T的最小元素的值 ElemType getMin(Triplet T, ElemType &e) { if (T[0] < T[1]) e = T[0]; else e = T[1]; if (T[2] < e) e = T[2]; printf("三元组T的最小元素的值为:%4.2fn",e); return e; } //如果T的三个元素按升序排序,则返回1,否则返回0// void isAscending(Triplet T) { if (((T[0] <= T[1]) && (T[1] <= T[2] )) != ERROR) printf("T的三个元素按升序排序n"); else printf("T的三个元素不是按升序排序"); } //如果T的三个元素按降序排序,则返回1,否则返回0// void isDescending(Triplet T) { if (((T[0] >= T[1]) && (T[1] >= T[2])) != ERROR) printf("T的三个元素按降序排序n"); else printf("T的三个元素不是按降序排序"); } //两个三元组相加 void add(Triplet T, Triplet &T2) { int i; for (i = 0; i < 3; i++) T2[i] += T[i]; } //三元组的各分量同乘比例系数 void mulCoef(Triplet &T, float coef) { int i; for (i = 0; i < 3; i++) T[i] *= coef; } int main() { Triplet T, T2; ElemType v0, v1, v2, e, coef; int funNum, i; printf("----三元组操作主菜单----n"); printf("----1.三元组初始化----n"); printf("----2.显示三元组----n"); printf("----3.用e获取T的第i(1~N)个元素的值----n"); printf("----4.置T的第i个元素的值为e----n"); printf("----5.是否升序排列----n"); printf("----6.是否降序排列----n"); printf("----7.取最大值----n"); printf("----8.取最小值----n"); printf("----9.输入另一个三元组相加----n"); printf("----10.三元组的各分量同乘比例系数----n"); printf("----11.退出系统----n"); while (1) { printf("请输入你想完成的功能编号:n"); scanf("%d", &funNum); switch (funNum) { case 1: printf("请输入三元组的每个元素:n"); scanf("%f %f %f", &v0, &v1, &v2); initTriplet(T, v0, v1, v2); break; case 2: printTriplet(T); break; case 3: printf("请输入要获取第几个元素的值:n"); scanf("%d", &i); getElem(T, i, e); printf("第%d个元素的值为:%4.2fn", i, e); break; case 4: printf("请输入要更改的位置和要输入的值:n"); scanf("%d %f", &i, &e); putElem(T, i, e); printf("新的三元组为:n"); printTriplet(T); break; case 5: isAscending(T); break; case 6: isDescending(T); break; case 7: getMax(T, e); break; case 8: getMin(T, e); break; case 9: printf("请输入另一个三元组的每个元素n"); scanf("%f %f %f", &v0, &v1, &v2); initTriplet(T2, v0, v1, v2); add(T, T2); printf("相加之后的三元组的值为:n"); printTriplet(T2); break; case 10: printf("请输入所乘的系数n"); scanf("%f", &coef); mulCoef(T, coef); printf("每项乘系数之后的三元组为:n"); printTriplet(T); break; case 11: destroyTriplet(T); destroyTriplet(T2); break; default: printf("没有你想完成的功能n");break; } } return 0; }
2.读入数据
代码如下:
代码段的理解
上文的源代码中,基本每段代码之后都有程序注释,作为新手,程序注释更是我们检验理解能力的"一杆秤“。
除程序注释,以下方面是对整片代码的理解:
1.指针问题
c中指针内容没掌握好的同学,(例如我),刚开始会对上述代码会有疑惑,全文中只有开头typedef ElemType *Triplet;中带有出现指针定义的间接访问运算符”*“,好像与下面代码显得格格不入
而理解代码的话,你会惊奇的发现,下面代码基本全部使用了指针,每一个变量T都是指针型变量,“指针无处不在”。
上面指出typedef ElemType *Triplet;是在声明Triplet为指向任意类型(此处为ElemType)的指针,所以,下面每一个Triplet数据类型的变量,全都是指向ElemType类型的指针变量,
在子函数中,会发现许多T[0]的用法,其实这就是指针的便捷之处,如果我们用结构体的话,必须 使用类似T.e[0]的形式,才能做一系列操作,但如果上面定义指针类型的话,直接使用T[0]即可。
T[0]的用法有些类似数组,对于数组而言,数组名[]可对数组中的元素操作,而对于指针变量同样适用,指针变量名T[]即可对指针指向的内容操作。(注意,不是指针本身的内容(或者说指针指向的方向))。
2.引用问题
上述代码我们使用了c++中的“引用”,(这也就是为什么源代码的扩展名要为.cpp),引用通俗来讲,就是给变量a又取了一个名字为变量b,所以引用并没有给b分配内存空间,而是让b与a共用同一块内存空间,此处与指针不同
在上述代码的参数传递中,我们多次使用了引用"&T",对于什么时候需要使用来说,如果你要改变某个实参的值,就对某个实参使用引用,反之,则不用。
3.针对上文使用的动态内存分配问题
本实验要求动态内存分配,其实对于三元组来说,并没有把动态内存分配的功能发挥的淋漓精致,但也简单的让我们看到了其强大功能的一二。
动态内存分配需要使用指针,指针的强大上文已经略有细说,我们慢慢体会。
动态分配内存要养成及时把需要释放的内存给释放掉的好习惯,对于大量的程序代码段,有助于提升系统的效率,减少所占内存。
写在最后
上文多次写了我对指针的理解,比如说两个特性,方向与大小,
但只是配和理解,真正应该以配合理解去使理解专业化,而不应该停留在配合理解或者被其框架所束缚。
浮游乎万物之祖,物物而不物于物。



