c定义一种类型stu可以放学生的姓名、学号、英语成绩, 其中英语成绩有的老师按照“A”、“B”、“C”、“D”、“F”五个等级给的, 有的老师按照百分制给的成绩,要求该类型可以如实反映学生的情况。
使用结构体
c# include <string.h> # include <stdio.h> # include <stdlib.h> # define TYPE_INT 0 # define TYPE_FLOAT 1 # define TYPE_CHAR 2 # define TYPE_TEXT 3 struct tagScore { int nType; int nPoint; float fPoint; char cLevel; char szText[8]; }; void ShowScore(struct tagScore sc) { switch(sc.nType) { case TYPE_INT: { printf("%d\r\n",sc.nPoint); break; } case TYPE_FLOAT: { printf("%f\r\n",sc.fPoint); break; } case TYPE_CHAR: { printf("%c\r\n",sc.cLevel); break; } case TYPE_TEXT: { printf("%s\r\n",sc.szText); break; } } } int main() { struct tagScore sc1; struct tagScore sc2; struct tagScore sc3; struct tagScore sc4; sc1.nPoint = 89; sc1.nType = TYPE_INT; ShowScore(sc1); sc2.fPoint = 65.5f; sc2.nType = TYPE_FLOAT; ShowScore(sc2); sc3.cLevel = 'B'; sc3.nType = TYPE_CHAR; ShowScore(sc3); strcpy(sc4.szText,"Good"); sc4.nType = TYPE_TEXT; ShowScore(sc4); system("pause"); return(0); } /* 以上代码可以发现结构体并不能节省空间,每次使用只是使用其中一个类型,其余类型都会被闲置,所以浪费空间 */
优化一下
c# include <string.h> # include <stdio.h> # include <stdlib.h> # define TYPE_INT 0 # define TYPE_FLOAT 1 # define TYPE_CHAR 2 # define TYPE_TEXT 3 struct tagScore { int nType; char szText[8]; }; void ShowScore(struct tagScore sc) { switch(sc.nType) { case TYPE_INT: { printf("%d\r\n",*(int *)sc.szText); break; } case TYPE_FLOAT: { printf("%f\r\n",*(float *)sc.szText); break; } case TYPE_CHAR: { printf("%c\r\n",*(char *)sc.szText); break; } case TYPE_TEXT: { printf("%s\r\n",sc.szText); break; } } } int main() { struct tagScore sc1; //同一地址放不同数据类型 *(int *)sc1.szText = 89; sc1.nType = TYPE_INT; ShowScore(sc1); *(float *)sc1.szText = 65.5f; sc1.nType = TYPE_FLOAT; ShowScore(sc1); *(char *)sc1.szText = 'B'; sc1.nType = TYPE_CHAR; ShowScore(sc1); strcpy(sc1.szText,"Good"); sc1.nType = TYPE_TEXT; ShowScore(sc1); system("pause"); return(0); } /* 强转方式 */
以上代码看起来非常繁琐,所以使用共用体解决
共用体(联合体)关键字union
,语法定义类同struct
。共用体所有成员共享使用同一段内存,成员名是解释此段内存的代号。手动实现就是强转指针类型取内容,而共用体是编译器对此实现提供了一种简易方式,同时也增加了可读性。
c# include <string.h> # include <stdio.h> # include <stdlib.h> # define TYPE_INT 0 # define TYPE_FLOAT 1 # define TYPE_CHAR 2 # define TYPE_TEXT 3 union unScore { int nPoint; float fPoint; char cLevel; char szText[8]; }; struct tagScore { int nType; union unScore uScore; }; void ShowScore(struct tagScore sc) { switch(sc.nType) { case TYPE_INT: { printf("%d\r\n",sc.uScore.nPoint); break; } case TYPE_FLOAT: { printf("%f\r\n",sc.uScore.fPoint); break; } case TYPE_CHAR: { printf("%c\r\n",sc.uScore.cLevel); break; } case TYPE_TEXT: { printf("%s\r\n",sc.uScore.szText); break; } } } int main() { struct tagScore sc1; sc1.uScore.nPoint = 89; sc1.nType = TYPE_INT; ShowScore(sc1); sc1.uScore.fPoint = 65.5f; sc1.nType = TYPE_FLOAT; ShowScore(sc1); sc1.uScore.cLevel = 'B'; sc1.nType = TYPE_CHAR; ShowScore(sc1); strcpy(sc1.uScore.szText,"Good"); sc1.nType = TYPE_TEXT; ShowScore(sc1); system("pause"); return(0); }
cstruct tagScore { int nType; union unScore { int nPoint; float fPoint; char cLevel; char szText[8]; }uScore; };
此时如果要使用
可以通过层级访问
cunion tagScore::unScore uScore;
如果要设为彻底不让别人用
cstruct tagScore { int nType; union //去掉名字 { int nPoint; float fPoint; char cLevel; char szText[8]; }uScore; };
枚举关键字enum
,成员间用逗号分隔,每个成员都是一个常量值。默认的如果不指定成员值,编译将第一个成员定义为0,后面的成员累加1,如果有成员数值被显示指定,那么后面没有指定的成员在指定值的基础上累加1。
枚举实际上就是收到约束的宏
c# include <string.h> # include <stdio.h> # include <stdlib.h> union unScore { int nPoint; float fPoint; char cLevel; char szText[8]; }; struct tagScore { //如果要禁止其他人使用的话可以去掉eScoreType enum eScoreType { TYPE_INT, TYPE_FLOAT, TYPE_CHAR, TYPE_TEXT }nType; union { int nPoint; float fPoint; char cLevel; char szText[8]; }uScore; }; void ShowScore(struct tagScore sc) { switch(sc.nType) { case tagScore::TYPE_INT: { printf("%d\r\n",sc.uScore.nPoint); break; } case tagScore::TYPE_FLOAT: { printf("%f\r\n",sc.uScore.fPoint); break; } case tagScore::TYPE_CHAR: { printf("%c\r\n",sc.uScore.cLevel); break; } case tagScore::TYPE_TEXT: { printf("%s\r\n",sc.uScore.szText); break; } } } int main() { struct tagScore sc1; sc1.uScore.nPoint = 89; sc1.nType = tagScore::TYPE_INT; ShowScore(sc1); sc1.uScore.fPoint = 65.5f; sc1.nType = tagScore::TYPE_FLOAT; ShowScore(sc1); sc1.uScore.cLevel = 'B'; sc1.nType = tagScore::TYPE_CHAR; ShowScore(sc1); strcpy(sc1.uScore.szText,"Good"); sc1.nType = tagScore::TYPE_TEXT; ShowScore(sc1); system("pause"); return(0); }
本文作者:Na1r
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!