当前位置: 首页 > news >正文

【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. 回忆:指针就是地址 指针变量就是存放地址的变量
    结构体也是变量
    变量访问有两种方式 : 1.变量名 2.地址
    之前案例,是用变量名访问
  2. 通过结构体变量地址来访问该结构体
    需要一个变量来保持这个地址:
    这和之前说的指针,其实是一样的
    只是指针类型是结构体
  3. 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.概念引入
  1. 有时候同一个内存空间存放类型不同,不同类型的变量共享一块空间
  2. 结构体元素有各自单独空间
    共用体元素共享空间,空间大小有最大类型确定
  3. 结构体元素互不影响
    共用体赋值会导致覆盖
#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;
}

相关文章:

  • 【全开源】多功能投票小程序系统源码(ThinkPHP+FastAdmin+Uniapp)
  • 软件安全技术【太原理工大学】
  • Java面向对象-方法的重写、super
  • 【C++】<知识点> C++11新特性
  • 视觉大模型(VLLM)学习笔记
  • 华为策略流控
  • 网络编程(UPD和TCP)
  • 拓扑排序-java
  • 类和对象的学习总结(一)
  • Android --- MVVM+DataBinding+Fragment+Retrofit+Adapter 简单示例
  • Django学习(1)Model
  • Qt图标字体文件中提取字体保存为图片
  • iOS18 新变化提前了解,除了AI还有这些变化
  • Java基础知识:为面试做好准备
  • 店匠科技亮相VivaTech,新零售解决方案引关注
  • 网络传输文件的问题
  • $translatePartialLoader加载失败及解决方式
  • JavaScript 基本功--面试宝典
  • JAVA多线程机制解析-volatilesynchronized
  • LeetCode29.两数相除 JavaScript
  • linux安装openssl、swoole等扩展的具体步骤
  • Mac转Windows的拯救指南
  • PHP的Ev教程三(Periodic watcher)
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 电商搜索引擎的架构设计和性能优化
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 开源地图数据可视化库——mapnik
  • 听说你叫Java(二)–Servlet请求
  • 一天一个设计模式之JS实现——适配器模式
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • #单片机(TB6600驱动42步进电机)
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (12)Hive调优——count distinct去重优化
  • (12)目标检测_SSD基于pytorch搭建代码
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (SpringBoot)第二章:Spring创建和使用
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (三十)Flask之wtforms库【剖析源码上篇】
  • (数据结构)顺序表的定义
  • (学习日记)2024.01.19
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .net 调用php,php 调用.net com组件 --
  • .Net 中Partitioner static与dynamic的性能对比
  • .NetCore项目nginx发布
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析