9.1 结构体
9.1.1 概述
数组:描述一组具有相同类型数据的有序合集,用于处理相同类型的数据运算。
有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。
C语言中给出了另一种结构数据类型——结构体。
9.1.2 结构体变量的自定义和初始化
9.1.3 结构体成员的使用
定义结构体变量的方式:
#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;
}
#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;
}
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 共用体(联合体)
#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;
}
9.3 枚举
枚举:将变量的值一一列举出来,变量的值只限于列举出来的值得范围内。
枚举类型定义:
enum 枚举名
{
枚举值表
}
#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语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型。
#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;
}