【C语言从入门到入土】第八章 结构体
第八章 结构体
完结散花,C语言全部章节更新完毕
文章目录
- 第八章 结构体
- 1.初识
- 1.1为什么要用结构体
- 1.2定义一个结构体
- 1.3初始化一个结构体变量并引用
- 1.4例题
- 2.结构体数组
- 3.应用练习:选票系统
- 4.结构体指针
- 1.概念引入
- 2.小应用
- 1.指针在结构体数组中的偏移
- 5.共用体/联合体
- 1.概念引入
- 6.宏定义define
- 7.typedef
1.初识
1.1为什么要用结构体
整型数,浮点型数,字符串是分散的数据表示,有时候我们需要用很多类型的数据来表示一个整体,比如学生信息
类比与数组:数组是元素类型一样的数据集合。如果是元素类型不同的数据集合,就要用到结构体了。
1.2定义一个结构体
它算是一个模板,一般不给赋具体的值,每一项在实际应用中并不是都要使用。
成员列表——也称为域表——每个成员都是结构体中的一个域
在声明的同时,定义变量,尽量少用
1.3初始化一个结构体变量并引用
//初始化结构体
#include <stdio.h>
#include <string.h>
struct Student
{int num;char name[32];char sex;int age;double score;char addr[32];
}; //注意这里的分号不要丢
int main()
{int a;//struct Student (这里可以看做 int) stu1(这个就属于a,变量名)struct Student stu1 = {2,"张三",'g',17,99.5,"北京"};//01//001.那么如何赋值呢?两种赋值方式 1.int a=10 2.int a; a=10;对比以前的struct Student stu2;//02stu2.num = 2;//1.点运算符来访问结构体中的成员变量(域)stu2.age = 18;//2.结构体里面的成员变量不是非要用上的,只用一部分也是可以的stu2.score = 88.8;strcpy(stu2.name,"李四");strcpy(stu2.addr,"湖南");//002.那么如何去引用呢?printf("学号:%d,年龄:%d,分数:%.2f,名字:%s,地址:%s\n",stu2.num,stu2.age,stu2.score,stu2.name,stu2.addr);return 0;
}
1.4例题
例题:输入两个学生的名字,学号,成绩,输出成绩高的学生的信息
重点认知:结构体没什么特殊的,只是把变量藏在结构体里面,而内部的变量,以前学习的东西是通用的,只是“触达的方式”不同
#include <stdio.h>
#include <string.h>
struct Student
{int num;char name[32];char sex;int age;double score;char addr[32];
};
int main()
{int a;//int tmp;struct Student stu1 = {2,"张三",'g',17,9,"北京"};//01struct Student stu2;//02struct Student max;//注意要把这个定义出来stu2.num = 2;stu2.age = 18;stu2.score = 88.8;strcpy(stu2.name,"李四");strcpy(stu2.addr,"湖南");max = stu1;//做一个变量的话,可以省写很多,要不然两个需要一一打印if(stu1.score<stu2.score){max = stu2;}printf("学号:%d,年龄:%d,分数:%.2f,名字:%s,地址:%s\n",max.num,max.age,max.score,max.name,max.addr);return 0;
}
2.结构体数组
#include <stdio.h>
#include <string.h>
struct Student
{int num;char name[32];char sex;int age;double score;char addr[32];
};
int main()
{int arr[3] ={1,2,3};int i;int len;// len = sizeof(arr)/sizeof(arr[0]);//类比数组来做结构体的数组struct Student arr2[3] ={{1,"张三",'g',17,9,"河北"},{2,"李四",'g',18,9,"广东"},{3,"王五",'g',17,9,"湖南"}};len = sizeof(arr2)/sizeof(arr2[0]);for(i=0;i<len;i++){printf("学号:%d,年龄:%d,分数:%.2f,名字:%s,地址:%s\n",arr2[i].num,arr2[i].age,arr2[i].score,arr2[i].name,arr2[i].addr);}return 0;
}
3.应用练习:选票系统
#include <stdio.h>
#include <string.h>struct xuanmin{int tickets;char name[32];
};
int main()
{int total = 5;char person[32];int mark;int qipiao = 0;int j;
//第二个思路我想要选择出弃票的有几个,然后票数最高的是谁struct xuanmin arr[3];struct xuanmin max;max.tickets = 0;int len =sizeof(arr)/sizeof(arr[0]);//1.输入候选人for(int i =0;i<len;i++){arr[i].tickets = 0;printf("请输入第%d候选人的名字\n",i+1);scanf("%s",arr[i].name);}//2.你要投那个候选人(一人一票,共五个人)for(int i = 0;i<total;i++){printf("请输入你想投的给谁一票\n");memset(person,'\0',sizeof(person));scanf("%s",person);mark = 0;for(int j =0;j<3;j++){if(strcmp(person,arr[j].name)==0){arr[j].tickets++;mark = 1;} }if(mark == 0){qipiao++;}}//3.公布结果for(int i=0;i<3;i++){printf("%s候选人共%d票\n",arr[i].name,arr[i].tickets); }for(int i =0;i<len;i++){if(max.tickets<arr[i].tickets){max = arr[i];//这是一个出彩的点,直接用一个票数换了整个结构体 j = i;}}printf("%s候选人以%d票当选,弃票%d人\n",max.name,max.tickets,qipiao);return 0;
}
4.结构体指针
1.概念引入
- 回忆:指针就是地址 指针变量就是存放地址的变量
结构体也是变量
变量访问有两种方式 : 1.变量名 2.地址
之前案例,是用变量名访问 - 通过结构体变量地址来访问该结构体
需要一个变量来保持这个地址:
这和之前说的指针,其实是一样的
只是指针类型是结构体 - int a; struct Test t;
int *p; struct Test *p;
p = &a; p = &t
#include <stdio.h>
#include <string.h>
struct student{char name;int numble;
};
int main()
{//我们对照以前的int a;int *p =&a;char c;char *p2=&c;struct student stu1 ={'c',21};struct student *stu = &stu1; //结构体指针的定义//那我如果想要访问里面的数据呢?printf("%d\n",stu1.numble);//普通的变量名访问printf("%C\n",stu1.name); //用最常见的.运算符stu ->name ='d';printf("%c\n",stu->name[32]); //间接的地址访问printf("%d\n",stu->numble);//用->运算符
}
2.小应用
1.指针在结构体数组中的偏移
#include <stdio.h>
#include <string.h>
struct Student
{int num;char name[32];char sex;int age;double score;char addr[32];
};
int main()
{int arr[3] ={1,2,3};int i;int len;// len = sizeof(arr)/sizeof(arr[0]);//类比数组来做结构体的数组struct Student arr2[3] ={{1,"张三",'g',17,9,"河北"},{2,"李四",'g',18,9,"广东"},{3,"王五",'g',17,9,"湖南"}};struct Student *p = arr2;len = sizeof(arr2)/sizeof(arr2[0]);for(i=0;i<len;i++){printf("学号:%d,年龄:%d,分数:%.2f,名字:%s,地址:%s\n",p->num,p->age,p->score,p->name,p->addr);//指针指向结构体p++;//指针偏移}return 0;
}
//用结构体指针来替换原先的选票系统
#include <stdio.h>
#include <string.h>struct xuanmin{int tickets;char name[32];
};
int main()
{int total = 5;char person[32];int mark;int qipiao = 0;//第二个思路我想要选择出弃票的有几个,然后票数最高的是谁struct xuanmin arr[3];struct xuanmin max;struct xuanmin *p = arr;max.tickets = 0;int len =sizeof(arr)/sizeof(arr[0]);//1.输入候选人for(int i =0;i<len;i++){arr[i].tickets = 0;printf("请输入第%d候选人的名字\n",i+1);scanf("%s",p->name);p++;}p = arr; //2.你要投那个候选人(一人一票,共五个人)for(int i = 0;i<total;i++){p =arr;printf("请输入你想投的给谁一票\n");memset(person,'\0',sizeof(person));scanf("%s",person);mark = 0;for(int j =0;j<3;j++){if(strcmp(person,p->name)==0){(p->tickets)++;mark = 1;} p++; }if(mark == 0){qipiao++;}}p = arr;//3.公布结果for(int i=0;i<3;i++){printf("%s候选人共%d票\n",p->name,p->tickets);p++; }p = arr;max = arr[0];for(int i =1;i<len;i++){if(max.tickets<p->tickets){max = arr[i];//这是一个出彩的点,直接用一个票数换了整个结构体 }p++;}printf("%s候选人以%d票当选,弃票%d人\n",max.name,max.tickets,qipiao);return 0;
}
5.共用体/联合体
1.概念引入
- 有时候同一个内存空间存放类型不同,不同类型的变量共享一块空间
- 结构体元素有各自单独空间
共用体元素共享空间,空间大小有最大类型确定 - 结构体元素互不影响
共用体赋值会导致覆盖
#include <stdio.h>
#include <string.h>//1.联合体的大小取决于最大的整数数
//2.联合体里面的变量值都是在同一个地址里面存放着
struct Test{int idata;char cdata;double ddata;
};
union Testu{int idata;char cdata;double ddata;
};
int main()
{struct Test t;union Testu u;printf("结构体的大小为%d\n",sizeof(t));printf("联合体的大小为%d\n",sizeof(u));printf("idata:%p\n",&t.idata);printf("cdata:%p\n",&t.cdata);printf("ddata:%p\n",&t.ddata);printf("idata:%p\n",&u.idata);printf("cdata:%p\n",&u.cdata);printf("ddata:%p\n",&u.ddata);return 0;
}
#include <stdio.h>
#include <string.h>//1.联合体的大小取决于最大的整数数
//2.联合体里面的变量值都是在同一个地址里面存放着
struct Test{int idata;char cdata;double ddata;
};
union Testu{int idata;char cdata;double ddata;
};
int main()
{struct Test t;union Testu u;printf("结构体的大小为%d\n",sizeof(t));printf("联合体的大小为%d\n",sizeof(u));
//3.共同体的数据会被覆盖t.idata = 10;t.cdata = 'a';printf("idata:%p,%d\n",&t.idata,t.idata);printf("cdata:%p,%d\n",&t.cdata,t.cdata);printf("ddata:%p\n",&t.ddata);u.idata = 20;u.cdata = 'a';printf("idata:%p,%d\n",&u.idata,u.idata);printf("cdata:%p,%d\n",&u.cdata,u.cdata);printf("ddata:%p\n",&u.ddata);return 0;
}
6.宏定义define
宏定义define的新变量在左边,
- 关键字:#define
- 用途:用一个字符串代替一个数字(字符也可以),便于理解,防止出错;提取程序中经常出现的参数,便于快速修改定义
- 宏定义: #define ABC 12345
- 引用宏定义: int a = ABC; //等效于int a = 12345;
7.typedef
给变量类型结合,一般跟结构体配合较多
- 关键字:typedef
- 用途:将一个比较长的变量类型名换个名字,便于使用
- 定义typedef: typedef unsigned char uint8_t;
- 引用typedef: uint8_t a; //等效于unsigned char a;
- 注意typedef不需要加分号,define需要加分号
#include <stdio.h>struct student{char name;int sex} stu1
int main()
{return 0;
}