C语言_9复合类型(自定义类型)

9 复合类型(自定义类型)

9.1 结构体
9.1.1 概述
数组:描述一组具有相同类型数据的有序合集,用于处理相同类型的数据运算。
有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。
C语言中给出了另一种结构数据类型——结构体。
C语言_9复合类型(自定义类型)_第1张图片
9.1.2 结构体变量的自定义和初始化
9.1.3 结构体成员的使用
定义结构体变量的方式:

  • 先声明结构体类型再定义变量名
  • 在声明类型的同时定义变量
  • 直接定义结构体类型变量(无类型名)
    C语言_9复合类型(自定义类型)_第2张图片
    结构体类型和结构体变量关系:
  • 结构体类型:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。
  • 在声明类型的同时定义变量
  • 直接定义结构体类型变量(无类型名)
#include
/*
//结构体成员列表
struct 结构体名
{
	姓名
	年龄
	成绩
};
*/
struct student
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
};
//struct student
//{
     
//	char name[21];
//	int age;
//	int score;
//	char addr[51];
//}stu1,stu2,stu3;
//struct student
//{
     
//	char name[21];
//	int age;
//	int score;
//	char addr[51];
//}stu1={"张三",18,100,"河北省"};//定义结构体同时赋值
int main01()
{
     
	//创建结构体变量
	struct student stu;//student结构体类型名 stu结构体变量名
	//stu.name="张三";//数组名是常量,不允许被赋值
	strcpy(stu.name,"张三")//结构体中为数组赋值 字符串拷贝 或 stu.name[0]="";
	stu.age=18;
	stu.score=100;
	strcpy(stu.addr,"河北省");

	//struct student stu={"张三",18,100,"河北省"};

	printf("姓名:%s\n",stu.name);
	printf("年龄:%d\n",stu.age);
	printf("成绩:%d\n",stu.score);
	printf("地址:%s\n",stu.addr);
	return 0;
}
int main02()
{
     
	struct student stu;
	scanf("%s%d%d%s",stu.name,&stu.age,&stu.score,stu.addr);
	printf("姓名:%s\n",stu.name);
	printf("年龄:%d\n",stu.age);
	printf("成绩:%d\n",stu.score);
	printf("地址:%s\n",stu.addr);
	return 0;
}

9.1.4 结构体数组

#include
struct student
{
     
	//结构体成员偏移对齐 int占的空间为4的倍数 21空3个才能对齐上int 所以下面96>89
	char name[21];
	int age;
	char sex;
	int score;
	char addr[51];
};
int main03()
{
     
	//int a;	int arr[3];
	struct student stu[3]=
	{
     
		{
     "张三"22'M',88,99,0,"河北省"};
		{
     "李四"18'F',59,59,59,"河北省"};
		{
     "王五"30'M',100,100,100,"黑龙江"};
		//{.addr="北京市",24,'M',88,99,0,.name="赵六"};
	};
	//sizeof()计算数据类型在内存中占的字节大小
	printf("结构体数组大小:%d\n",sizeof(stu));//288
	printf("结构体元素大小:%d\n",sizeof(stu[0]));//96 21+4+1+12+51=89
	printf("结构体元素个数:%d\n",sizeof(stu)/sizeof(stu[0]));//3
	for(int i=0;i<3;i++)
	{
     
		printf("姓名:%s\n",stu[i].name);
		printf("年龄:%d\n",stu[i].age);
		printf("性别:%s\n",stu[i].sex=='M'?"男":"女");
		printf("成绩1:%d\n",stu[i].score[0]);
		printf("成绩2:%d\n",stu[i].score[1]);
		printf("成绩3:%d\n",stu[i].score[2]);
		printf("地址:%s\n",stu[i].addr);
	}
	return 0;
}
//结构体数组排序
int main04()
{
     
	struct student stu[3]=
	{
     
		{
     "张三"22'M',88,99,0,"河北省"};
		{
     "李四"18'F',59,59,59,"河北省"};
		{
     "王五"30'M',100,100,100,"黑龙江"};
	}	
	for(int i=0;i<3-1;i++)
	{
     
		for(int j=0;j<3-1-j;j++)
		{
     
			if(stu[j].age>stu[j+1].age)
			{
     
				struct student temp=stu[j];
				stu[j]=stu[j+1];
				stu[j+1]=temp;
			}
		}
		for(int i=0;i<3;i++)
	{
     
		printf("姓名:%s\n",stu[i].name);
		printf("年龄:%d\n",stu[i].age);
		printf("性别:%s\n",stu[i].sex=='M'?"男":"女");
		printf("成绩1:%d\n",stu[i].score[0]);
		printf("成绩2:%d\n",stu[i].score[1]);
		printf("成绩3:%d\n",stu[i].score[2]);
		printf("地址:%s\n",stu[i].addr);
	}
	return 0;
}
#include
#include
struct student
{
     
	//结构体成员偏移对齐 int占的空间为4的倍数 21空3个才能对齐上int 所以下面96>89
	char name[21];
	int age;
	char sex;
	int score;
	char addr[51];
};
//开辟堆空间存储结构体
typedef struct student ss;//取别名
int main05()
{
     
	//printf("%d\n",sizeof(struct student));
	//struct student *p=(struct student *)malloc(sizeof(struct student)*3);
	ss *p=(ss *)malloc(sizeof(ss)*3);
	printf("结构体指针大小:%d",sizeof(p));//sizeof(ss *)
	//32位操作系统 4;64位操作系统 8 所有数据指针大小:4/8,结构体指针为指针的一种
	for(int i=0;i<3;i++)
	{
     				
		scanf("%s%d,%c%d%d%d%s",p[i].name,&p[i].age,&p[i].sex,
				&p[i].score[0],&p[i].score[1],&p[i].score[2],p[i].addr);//年龄后为性别字符,输入空格或换行会被接收,用 , 隔开
		//张三 62,M 66 37 86 荆州
	}
	for(int i=0;i<3;i++)
	{
     
		printf("姓名:%s\n",p[i].name);
		printf("年龄:%d\n",p[i].age);
		printf("性别:%s\n",p[i].sex=='M'?"男":"女");
		printf("成绩1:%d\n",p[i].score[0]);
		printf("成绩2:%d\n",p[i].score[1]);
		printf("成绩3:%d\n",p[i].score[2]);
		printf("地址:%s\n",p[i].addr);
	}
	free(p);
	return 0;
}

9.1.5 结构体套结构体

#include
/*
struct 技能
{
	名称
	等级
	伤害
	范围
	耗蓝
	冷却
};
struct 人物信息
{
	等级
	经验
	金钱
	hp
	mp
	力量
	智力
	敏捷
	struct 技能 skills[4]
};
struct 人物信息 info:
info.skills[0].名称
*/
/*
struct 消费记录
{
	消费金额
	消费时间
	消费编号
	消费地点
	付款方式
	备注
};
struct 银行卡
{
	卡号
	密码
	持有人
	属性
	余额
	struct 消费记录[20]
};
*/
//结构体嵌套结构体
struct scores
{
     
	int c1;//C语言
	int cpp;//C++
	int cs;//C#
};
typedef struct student stu;
struct student
{
     
	char name[21];
	int age;
	struct scores ss;//同类型可以写数组进行嵌套
	char addr[51];
};
int main07()
{
     
	//struct student stu;
	stu s;
	printf("学生结构体大小:%d\n",sizeof(stu));//sizeof(s) 92 = 21+4+12+51 
	printf("成绩结构体大小:%d\n",sizeof(s.ss));//12
	printf("名称数组大小:%d\n",sizeof(s.name));//21
}
int main06()
{
     
	//struct student stu={"貂蝉",18,99,99,99,"徐州"};
	struct student stu;
	strcpy(stu.name,"小乔")
	stu.age=20;
	stu.ss.c1=88;
	stu.ss.spp=88;
	stu.ss.cs=88;
	strcpy(stu.addr,"江东");
	printf("%s\n%d\n%d\n%d\n%d\n%s\n",stu.name,stu.age,
				stu.ss.c1,stu.ss.cpp,stu.ss.cs,stu.addr);
	return 0;
}

9.1.6 结构体赋值

#include
struct student
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
};
int main08()
{
     
	//int a=10;	int b=a; b=20;
	struct student stu={
     "貂蝉",18,60,"徐州"};
	struct student s1=stu;
	strcpy(s1.name,"小乔");
	stu.age=20;
	stu.score=88;
	
	printf("%s\n",stu.name);//小乔
	printf("%d\n",stu.age);//20
	printf("%d\n",stu.score);//88
	return 0;
}

C语言_9复合类型(自定义类型)_第3张图片
9.1.7 结构体和指针

#include
#include
//结构体成员为指针变量
struct student
{
     
	char *name;
	int age;
	int *scores;
	char *addr;
};
int main09()
{
     
	struct student stu;
	//stu.name="张三";//err
	stu.name=(char *)malloc(sizeof(char)*21);
	stu.scores=(int *)malloc(sizeof(int)*3);
	stu.addr=(char *)malloc(sizeof(char)*51);
	strcpy(stu.name,"张三");
	stu.age=20;
	stu.score[0]=88;
	stu.score[1]=99;
	stu.score[2]=100;
	strcpy(stu.addr,"北京市");
	
	printf("%s\n",stu.name);//张三
	printf("%d\n",stu.age);//20
	printf("%d\n",stu.score[0]);//88
	printf("%d\n",stu.score[1]);//99
	printf("%d\n",stu.score[2]);//100
	printf("%s\n",stu.addr);//北京市
	free(stu.name);
	free(stu.score);
	free(stu.addr);
	return 0;
}
#include
struct stu
{
     
	char name[21];
	int age;
	int scores[3];
	char addr[51];
};
int main10()
{
     
	//int a=10;	int *p=&a;
	//结构体指针
	struct stu ss={
     "貂蝉",18,60,100,100,"徐州"};
	//struct stu *p;
	//p=&ss;
	struct stu *p=&ss;
	(*p).//.比*优先级别高,加()
	//printf("%s\n",(*p).name);//貂蝉
	//printf("%d\n",(*p).age);//18
	//->指向云算符  结构体指针->成员	结构体变量.成员
	printf("%s\n",p->name);
	printf("%d\n",p->age);
	printf("%d\n",p->score[0]);
	printf("%d\n",p->score[1]);
	printf("%d\n",p->score[2]);
	printf("%s\n",p->addr);
	return 0;
}
#include
struct student
{
     
	char name[21];
	int age;
	int scores[3];
	char addr[51];
};
int main11()
{
     
	//int a=10;	int *p=&a;
	//结构体指针
	struct student ss={
     "貂蝉",18,60,100,100,"徐州"};
	//struct stu *p;
	//p=&ss;
	struct stu *p=&ss;
	(*p).//.比*优先级别高,加()
	//printf("%s\n",(*p).name);//貂蝉
	//printf("%d\n",(*p).age);//18
	//->指向云算符  结构体指针->成员	结构体变量.成员
	printf("%s\n",p->name);
	printf("%d\n",p->age);
	printf("%d\n",p->score[0]);
	printf("%d\n",p->score[1]);
	printf("%d\n",p->score[2]);
	printf("%s\n",p->addr);
	return 0;
}
#include
#include
typedef struct student ss;
struct student
{
     
	char *name;
	int age;
	int *scores;
	char *addr;
};
int main12()
{
     
	ss *p=(ss *)malloc(sizeof(ss)*3);
	for(int i=0;i<3;i++)
	{
     
		//(p+i)->name;
		p[i].name=(char *)malloc(sizeof(char)*21);
		p[i].scores=(int *)malloc(sizeof(int)*21);
		p[i].addr=(char *)malloc(sizeof(char)*51);
	}
	for(int i=0;i<3;i++)
	{
     
		scanf("%s%d%d%d%d%s",p[i].name,&p[i].age,&p[i].scores[0],
		&p[i].scores[1],&p[i].scores[2],p[i].addr);
	}
	for(int i=0;i<3;i++)
	{
     
		printf("%s ",p[i].name);
		printf("%d ",p[i].age);
		printf("%d ",p[i].score[0]);
		printf("%d ",(p+i)->score[1]);
		printf("%d ",(p+i)->score[2]);
		printf("%s\n",(p+i)->addr);
	}
	for(int i=0;i<3;i++)
	{
     
		free(p[i].name);
		free(p[i].scores);
		free(p[i].addr);
	}
	free(p);
	return 0;
}

C语言_9复合类型(自定义类型)_第4张图片
9.1.8 结构体做函数参数
(1)结构体普通变量做函数参数

#include
#include
//结构体普通变量做函数参数
typedef struct student ss;
struct student
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
};
void fun01(ss stu)
{
     	
	strcpy(stu.name,"小乔");
	printf("%s\n",stu.name);//小乔
}
int main13()
{
     
	ss stu={
     "貂蝉",18,100,"徐州"};
	fun01(stu);
	printf("%s\n",stu.name);//貂蝉
	return 0;
}
#include
#include
typedef struct student ss;
struct student
{
     
	char *name;
	int age;
	int score;
	char addr[51];
};
void fun01(ss stu1)
{
     	
	//stu1.name=(char *)malloc(sizeof(char)*21);//若在开辟一个空间,两个独立的空间 函数里打印小乔 main里打印貂蝉 这两个对应同一空间地址
	strcpy(stu1.name,"小乔");
	printf("%s\n",stu1.name);//小乔
}
int main13()
{
     
	ss stu={
     NULL,18,100,"徐州"};
	stu.name=(char *)malloc(sizeof(char)*21);
	strcpy(stu.name,"貂蝉");
	fun01(stu);
	printf("%s\n",stu.name);//小乔
	return 0;
}

(2)结构体指针变量做函数参数

#include
#include
//结构体指针作为函数参数
typedef struct student ss;
struct student
{
     
	char *name;
	int age;
	int score;
	char addr[51];
};
void fun02(ss *p)//地址传递可以改变形参的值
{
     
	strcpy(p->name,"貂蝉");
	printf("%s\n",p->name);//貂蝉
}
int main14()
{
     
	ss stu={
     "小乔",18,100,"徐州"};
	fun02(&stu);
	printf("%s\n",stu.name);//貂蝉
	return 0;
}

(3)结构体数组名做函数参数

#include
#include
//结构体指针作为函数参数
typedef struct student ss;
struct student
{
     
	char *name;
	int age;
	int score[3];
	char addr[51];
};
void BubbleSort(ss *stu,int len)
{
     
	//数组作为函数参数 退化为指针 丢失元素精度 需要传递个数
	//printf("%d\n",sizeof(stu));//4
	for(int i=0;i<len-1;i++)
	{
     
		for(int j=0;j<len-1-j;j++)
		{
     
			if(stu[j].age>stu[j+1].age)
			//if((stu+j)->age>stu+j+1)->age)
			{
     
				ss temp=stu[j];
				stu[j]=stu[j+1];
				stu[j+1]=temp;
			}
		}
	}
}
int main15()
{
     
	ss stu[3]={
     
	{
     "小乔",18,100,88,88,"徐州"},
	{
     "貂蝉",20,98,88,88,"徐州1"},
	{
     "三三",22,22,88,88,"徐州2"}
	};
	BubbleSort(stu,3);
	for(int i=0;i<3;i++)
	{
     
		printf("%s ",p[i].name);
		printf("%d ",p[i].age);
		printf("%d ",p[i].score[0]);
		printf("%d ",(p+i)->score[1]);
		printf("%d ",(p+i)->score[2]);
		printf("%s\n",(p+i)->addr);
	}
	return 0;
}

(4)const修饰结构体指针形参变量

#include
#include
typedef struct student ss;
struct student
{
     
	char name[21];
	int age;
	int score[3];
	char addr[51];
};
int main16()
{
     
	ss stu1={
     "小乔",18,100,88,88,"徐州"};
	ss stu2={
     "貂蝉",20,98,88,88,"徐州1"};
	//const修饰结构体指针类型 可以修改结构体指针变量值,不能改变结构体指针指向内存空间的值
	const ss *p=&stu1;
	//p=&stu2;//ok
	//p->age=888;//err
	//*p.age=888;//err
	return 0;
}
int main17()
{
     
	ss stu1={
     "小乔",18,100,88,88,"徐州"};
	ss stu2={
     "貂蝉",20,98,88,88,"徐州1"};
	//const修饰结构体指针变量 不可以修改结构体指针变量值,能改变结构体指针指向内存空间的值
	ss *const p=&stu1;
	//p=&stu2;//err
	//p->age=888;//ok
	//p->name="张三";//err修改方式不对
	strcpy(p->name,"张三");//ok
	//*p.age=888;//ok
	return 0;
}
int main18()
{
     
	ss stu1={
     "小乔",18,100,88,88,"徐州"};
	ss stu2={
     "貂蝉",20,98,88,88,"徐州1"};
	//const修饰结构体指针类型和变量 不可以修改结构体指针变量值,不能改变结构体指针指向内存空间的值
	const ss *const p=&stu1;
	//p=&stu2;//err
	//p->age=888;//err
	ss **pp=&p;
	
	*pp=&stu2;
	//(*pp)->age=888//pp二级指针加*一级指针,指向可以修改
	(**pp).age=888;//**pp变量值,加.可以修改
	//结构体指针->成员	结构体变量.成员
	return 0;
}

struct stu
{
     
	char name[50];
	int age;
}
void fun1(struct str * const p)
{
     
	//p=NULL;//err
	p->age=10;//ok
}
//void fun2(struct stu const *p)
void fun2(const struct stu *p)
{
     
	p=NULL;//ok
	//p->age=10;//err
}
void fun3(const struct stu *const p)
{
     
	//p=NULL;//err
	//p->age=10;//err
}

9.2 共用体(联合体)

  • 联合union是一个能在同一个存储空间存储不同类型数据的类型
  • 联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体
  • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用
  • 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖
  • 共用体变量的地址和它的各成员的地址都是同一地址
#include
union Var
{
     
	int a;
	float b;
	double c;//16
	char d;
	short f[6];//12
};
int main19()
{
     
	union Var var;
	var.a=100;
	var.b=3.14;
	printf("%d\n",var.a);//乱码
	printf("%d\n",var.b);//3.140000 只有最后一次存入的值有效
	
	printf("%p\n",&var);//同一地址
	printf("%dp\n",&var.a);
	printf("%dp\n",&var.b);
	printf("%dp\n",&var.c);printf("大小%d\n",sizeof(var));//16
	return 0;
}

C语言_9复合类型(自定义类型)_第5张图片
9.3 枚举
枚举:将变量的值一一列举出来,变量的值只限于列举出来的值得范围内。
枚举类型定义:
enum 枚举名
{
枚举值表
}

  • 在枚举值表中应列出所有可用值,也称为枚举元素
  • 枚举值是常量,不能在程序中用赋值语句再对它赋值
  • 枚举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2…
#include
enum Color()
{
     
	red,blue,green,pink,yellow,black,white
}color;//color枚举变量
int main20()
{
     
	switch(color)//Tab会自动出现下面的
	{
     
		case red:
			break;
		case blue:
			break;
		case green:
			break;
		case pink:
			break;
		case yellow:
			break;
		case black:
			break;	
		case white:
			break;
		default:
			break;		
	}
	return 0;
}
//
enum Color()
{
     
	red,blue,green,pink,yellow,black,white//默认 0 1 2 3 4 5 6 
	//red=10,blue,green,pink,yellow20,black,white//10 11 12 13 21 22 23 
};
int main20()
{
     
	int value;
	scanf("%d",&value);
	switch(value)
	{
     
		case red:
			printf("红色\n");
			break;
		case blue:
			printf("蓝色\n");
			break;
		case green:
			printf("绿色\n");
			break;
		case pink:
			printf("粉色\n");
			break;
		case yellow:
			printf("黄色\n");
			break;
		case black:
			printf("黑色\n");
			break;	
		case white:
			printf("白色\n");
			break;
		default:
			break;		
	}
	return 0;
}
#include
enum TYPE()
{
     
	run,attack,skill,dance=10,showUI,frozen=20,dizz,dath,moti=30
};//type;写完之后再删掉
int main21()
{
     
	int value;
	while(1)
	{
     
		scanf("%d",&value);
		switch(value)//(type)
		{
     
			case run:
				printf("英雄正在移动中...\n");
				//value=30;
				break;
			case attack:
				printf("英雄正在攻击中...\n");
				break;
			case skill:
				printf("英雄正在释放技能中...\n");
				break;
			case dance:
				printf("英雄正在跳舞中...\n");
				break;
			case showUI:
				printf("英雄正显示徽章...\n");
				break;
			case frozen:
				printf("英雄被冰冻中...\n");
				break;	
			case dizz:
				printf("英雄被眩晕中...\n");
				break;
			case dath:
				printf("英雄死亡\n");
				return 0;
				break;
			case moti:
				printf("英雄等待释放命令...\n");
				break;
			default:
				break;		
		}	
	}
	return 0;
}
/*
enum 交易
{
	插卡,读卡,锁卡,输入密码,查询,取款,退卡,解锁
}
*/

9.4 typedef
typedef为C语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型

  • 与#define不同,typedef仅限于数据类型,而不是能使表达式或具体的值
  • #define发生在预处理,typedef发生在编译阶段
#include
typedef unsigned int ui;
typedef unsigned long long ull;
//1.为已存在的数据类型起别名
//2.定义函数指针
struct stu
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
}ss;//此处ss为结构体变量名
typedef struct stu
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
}ss;//此处ss为结构体别名
//typedef struct stu ss;
typedef struct stu//stu结构体别名
{
     
	char name[21];
	int age;
	int score;
	char addr[51];
}ss;
int main22()
{
     
	ui a=10;
	ull b=20;
	printf("%d\n",a);
	printf("%d\n",b);
	return 0;
}

你可能感兴趣的:(C语言)