结构体
出现前景 : 同时需要对多种数据进行操作
结构体--他就将不同类型的数据存放在一起,作为一个整体进行处理。
声明:
struct Test
{
int a[20];
char c;
};//注意分号不能少,这也相当于一条语句;
结构体初始化:
1.先定义再一个个初始化
typedef struct {
int bandrate;
int databits;
int stopbits;
int parity;
int dtr;
}serial_hard_config_def;
serial_hard_config_def serial;
serial.bandrate = 115200;
serial.databits = 8;
serial.stopbits = 1;
serial.parity = 0;
serial.dtr = 0;
2.定义的同时初始化
2.1 顺序初始化
typedef struct {
int bandrate;
int databits;
int stopbits;
int parity;
int dtr;
}serial_hard_config_def;
serial_hard_config_def serial = {
115200,
8,
1,
0,
0
};
2.2 乱序初始化:
typedef struct {
int bandrate;
int databits;
int stopbits;
int parity;
int dtr;
}serial_hard_config_def;
serial_hard_config_def serial = {
.dtr = 0,
.bandrate = 115200,
.databits = 8,
.stopbits = 1,
.parity = 0,
};
结构体数组初始化:
typedef struct {
int bandrate;
int databits;
int stopbits;
int parity;
int dtr;
}serial_hard_config_def;
serial_hard_config_def serial[2] = {
[0] = {
.dtr = 0,
.bandrate = 115200,
.databits = 8,
.stopbits = 1,
.parity = 0,
},
[1] = {
.dtr = 0,
.bandrate = 115200,
.databits = 8,
.stopbits = 1,
.parity = 0,
}
};
访问结构体成员:
1.变量名 .
2.指针 ->
===================================================
结构体数组-test -- 选票系统
test:
选票程序
#include<stdio.h>
#include<string.h>struct XuanMing
{
int tickets;
char name[30];
};
int main()
{
struct XuanMing xm[3];
struct XuanMing max;
int len =sizeof(xm)/sizeof(xm[0]);
char tName[30];
int i,j;
int flag=0;
int total=5;
int lose=0;
//初始化选民信息:
for(i=0;i<len;++i)
{
xm[i].tickets=0;
puts("请输入选民的姓名:");
scanf("%s",xm[i].name);
}
//投票环节
for(i=0;i<5;++i)
{
flag=0;
memset(tName,'\0',sizeof(tName));
puts("请输入你支持的选民的姓名:");
scanf("%s",tName);
for(j=0;j<len;++j)
{
if(!strcmp(xm[j].name,tName))
{
xm[j].tickets++;
flag=1;
}
}
if(!flag)
{
lose++;
puts("输出错误视为弃票");
}
}
puts("======================");
for(int i=0;i<len;++i)
{
printf("姓名:%s 得票:%d\n",xm[i].name,xm[i].tickets);
}
printf("弃票数:%d\n",lose);
puts("=====公布结果====");
max=xm[0];
for(int i=0;i<len;++i)
{
if(xm[i].tickets>max.tickets)max=xm[i];
}
printf("恭喜!!!最终d当选者:%s 得票:%d\n",max.name,max.tickets);
return 0;
}
结构体指针:
结构体的两种访问方式:
1.结构体变量名 -- 用 . 访问
2.指针访问 -- 用 -> 访问
#include<stdio.h>
struct Test
{
int idata;
char cdata;
};int main()
{
struct Test tt={12,'a'};
struct Test *ptt=&tt;
printf("idata= %d\n",tt.idata);
printf("idata= %d\n",ptt->idata);
printf("cdata= %c\n",tt.cdata);
printf("cdata= %c\n",ptt->cdata);
return 0;
}
// 指针 操作 注意
1.把以前的普通变量名,or下标访问 . 元素符改为 指针的->
2.指针++,用完记得复位
报错注意:
struct Test tt=NULL; //避免野指针
yy={12,'a'};
================================
结构体二级指针:
我们知道如果要修改一个变量的值,就要传递他的地址给函数,指针变量也一样,要传入二级指针
这样初始化就不用接收返回值,直接在初始化函数里面修改
p=(struct XuanMin*)malloc(sizeof(struct XuanMin)*n);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct XuanMin
{
char name[30];
int tickets;
};struct XuanMin* initXms(struct XuanMin *p,int *len)
{
int i;
int n=0;
if(p==NULL){
printf("请输入选民人数:\n");
scanf("%d",len);
n=*len;
p=(struct XuanMin*)malloc(sizeof(struct XuanMin)*n);
}
for(i=0;i<n;++i)
{
printf("请输入第%d位选民的姓名:\n",i+1);
scanf("%s",p->name);
p->tickets=0;
p++;
}
return p-n;
}void printXms(struct XuanMin*p,int len)
{
int i;
for(i=0;i<len;++i)
{
printf("姓名:%s 得票:%d\n",(p+i)->name,(p+i)->tickets);
//printf("姓名:%s 得票:%d\n",p->name,p->tickets);
//p++;
}
}int doVote(struct XuanMin*p,int len)
{
int i,j;
int flag=0;
int lose=0;\
char tName[30];
struct XuanMin*sta=p;
//投票环节
for(i=0;i<5;++i)
{
p=sta;
flag=0;
memset(tName,'\0',sizeof(tName));
puts("请输入你支持的选民的姓名:");
scanf("%s",tName);
for(j=0;j<len;++j)
{
if(!strcmp(p->name,tName))
{
p->tickets++;
flag=1;
break;
}
p++;
}
if(!flag)
{
lose++;
puts("输出错误视为弃票");
}
}
return lose;
}
struct XuanMin *getWiner(struct XuanMin*p,int len)
{
struct XuanMin *max=p;
for(int i=0;i<len;++i)
{
if(p->tickets>max->tickets)
max=p;
++p;
}
printf("恭喜!!!最终d当选者:%s 得票:%d\n",max->name,max->tickets);
return 0;
}int main()
{
struct XuanMin *xm=NULL;
int total=0;
xm=initXms(xm,&total); //初始化指针 -- 避免野指针
//printf("%d",total);
//printXms(xm,total);
int lose= doVote(xm,total);
printf("弃票数:%d\n",lose);
printXms(xm,total);
getWiner(xm,total);
return 0;
}// 要修改一个变量 就要传入他的实参 -- 地址 修改int *,传入int**
void initXms2(struct XuanMin **pxm,int *pt)
{
int i;
if(*pxm==NULL) {
puts("请输入选民人数:");
scanf("%d",pt);
*pxm=(struct XuanMin *)malloc(sizeof(struct XuanMin)*(*pt));
}
for(i=0;i<*pt;++i)
{
printf("请输入第%d位选民的姓名:\n",i+1);
scanf("%s",(*pxm)->name);
(*pxm)->tickets=0;
(*pxm)++;
}
*pxm=*pxm-*pt; //实现 初始化
}
共用体/联合体: -- union
定义和 结构体一样,把struct 换成 union
特性 -- 不同类型的变量,共享同一空间
结构体 和联合体的区别;
1. 结构体元素有各自单独的空间 , 联合体共享空间
2.结构体元素互不影响,联合体赋值会导致覆盖
结构体大小占用规则
1、第一个成员在与结构体变量偏移量为0的地址处。(即结构体的首地址处,即对齐到0处)2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
3、结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4、如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
对齐数 = 该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值。
注:VS中的默认对齐数为8,不是所有编译器都有默认对齐数,当编译器没有默认对齐数的时候,成员变量的大小就是该成员的对齐数。
联合体的内存 == 其中元素中的占用最大内存的元素
验证程序:
#include<stdio.h>struct Test1
{
int idata;
char cdata;
double ddata;
};union Test2
{
int idata;
char cdata;
double ddata;
};int main()
{
struct Test1 t1;
union Test2 t2;
puts("大小区别");
printf("结构体: %d\n",sizeof(t1)); // 16
printf("联合体: %d\n",sizeof(t2)); //8 -- double
puts("存放地址区别");
printf("结构体idata: %p\n",&t1.idata);
printf("联合体idata: %p\n",&t2.idata);
puts("====================================");
printf("结构体cdata: %p\n",&t1.cdata);
printf("联合体cdata: %p\n",&t2.cdata);
puts("====================================");
printf("结构体ddata: %p\n",&t1.ddata);
printf("联合体ddata: %p\n",&t2.ddata);
puts("存放数值区别");
t1.idata=4;
t1.cdata='a';
t1.ddata=12.5;
printf("idata=%d cdata=%c ddata%.2lf\n",t1.idata,t1.cdata,t1.ddata);
puts("====================================");
t2.idata=12;
t2.cdata='a';
printf("t2.idata:%d\n",t2.idata); // 97
return 0;
}
test:
现在有学生和老师的成员数据,学生数据包括:姓名,号码,性别,年龄,职业,班级
老师的数据包括:姓名,号码,性别,年龄,职业,职务,要求使用同一个表格来处理
// 思路: 根据观察,学生和老师 数据类型只差, 班级和职务不同 -- 可以都存在联合体里面去处理
#include<stdio.h>
struct Person
{
char name[20];
char occup;//occupation
union D
{
int class;
char subject[20];
}uu;
};
int main()
{
struct Person p[2];
int i;
for(i=0;i<2;++i)
{
puts("请输入您的职业: s-学生 t-老师");
scanf("%c",&(p[i].occup));
getchar();
if(p[i].occup=='s')
{
puts("请输入学生姓名:");
scanf("%s",p[i].name);
puts("请输入学生班级:");
scanf("%d",&(p[i].uu.class));
}
else
{
puts("请输入老师姓名:");
scanf("%s",p[i].name);
puts("请输入;老师所教科目:");
scanf("%s",p[i].uu.subject);
}
}
for(int i=0;i<2;++i)
{
if(p[i].occup=='s')
{
puts("一名学生");
printf("姓名:%s 班级:%d\n",p[i].name,p[i].uu.class);
}
else
{
puts("一位老师");
printf("姓名:%s 所教科目:%s\n",p[i].name,p[i].uu.subject);
}
}
}