第八章 结构体
完结散花,C语言全部章节更新完毕
文章目录
-
- [第八章 结构体](#第八章 结构体)
1.初识
1.1为什么要用结构体
整型数,浮点型数,字符串是分散的数据表示,有时候我们需要用很多类型的数据来表示一个整体,比如学生信息
类比与数组:数组是元素类型一样的数据集合。如果是元素类型不同的数据集合,就要用到结构体了。
1.2定义一个结构体
它算是一个模板,一般不给赋具体的值,每一项在实际应用中并不是都要使用。
成员列表------也称为域表------每个成员都是结构体中的一个域
在声明的同时,定义变量,尽量少用
1.3初始化一个结构体变量并引用
c
//初始化结构体
#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;//02
stu2.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例题
例题:输入两个学生的名字,学号,成绩,输出成绩高的学生的信息
重点认知:结构体没什么特殊的,只是把变量藏在结构体里面,而内部的变量,以前学习的东西是通用的,只是"触达的方式"不同
c
#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,"北京"};//01
struct Student stu2;//02
struct 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.结构体数组
c
#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.应用练习:选票系统
c
#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
c
#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.指针在结构体数组中的偏移
c
#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;
}
c
//用结构体指针来替换原先的选票系统
#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.概念引入
- 有时候同一个内存空间存放类型不同,不同类型的变量共享一块空间
- 结构体元素有各自单独空间
共用体元素共享空间,空间大小有最大类型确定 - 结构体元素互不影响
共用体赋值会导致覆盖
c
#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;
}
c
#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需要加分号
c
#include <stdio.h>
struct student{char name;int sex} stu1
int main()
{
return 0;
}