C语言基础内容(七)——第07章_结构体与共同体

文章目录

  • 第07章_结构体与共用体
    • 本章专题脉络
    • 1、结构体(struct)类型的基本使用
      • 1.1 为什么需要结构体?
      • 1.2 结构体的理解
      • 1.3 声明结构体
      • 1.4 声明结构体变量并调用成员
      • 1.5 举例
      • 1.6 小 结
    • 2、进一步认识结构体
      • 2.1 结构体嵌套
      • 2.2 结构体占用空间
      • 2.3 结构体变量的赋值操作
    • 3、结构体数组
      • 3.1 对比结构体与数组
      • 3.2 结构体数组的声明
      • 3.3 初始化数组元素
      • 3.4 结构体数组元素的成员的调用
    • 4、结构体指针
      • 4.1 结构体指针格式
      • 4.2 结构体传参
      • 4.3 -> 操作符
      • 4.4 指向结构体数组的指针
    • 5、结构体在数据结构中的应用
      • 5.1 声明结点的结构体
      • 5.2 声明结点变量
      • 5.3 两种方式对比
      • 5.4 malloc()模板
      • 5.5 举 例
    • 6、共用体类型(union)
      • 6.1 共用体概述
      • 6.2 声明共用体
      • 6.3 声明共用体变量
      • 6.4 调用共同体变量的成员
      • 6.5 ->操作符
      • 6.6 补充说明
      • 6.7 练习
    • 7、typedef 的使用(熟悉)
      • 7.1 为什么使用typedef
      • 7.2 使用格式
      • 7.3 举 例
      • 7.4 小 结
      • 7.5 应用场景

第07章_结构体与共用体

本章专题脉络

在这里插入图片描述

1、结构体(struct)类型的基本使用

1.1 为什么需要结构体?

C 语言内置的数据类型,除了几种原始的基本数据类型,只有数组属于复合类型,可以同时包含多个值,但是只能包含相同类型的数据,实际使用场景受限。

举例:隔壁老王养了两只猫咪。一只名字叫小黄,今年2岁,橘色;另一只叫小黑,今年3岁,黑色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示老王没有这只猫。

传统的解决方法

尝试1:单独定义多个变量存储,实现需求。但是,多个变量,不便于数据的管理。

尝试2:使用数组,它是一组具有相同类型的数据的集合。但在编程中,往往还需要一组类型不同的数据,例如猫的名字使用字符串、年龄是int,颜色是字符串,因为数据类型不同,不能用一个数组来存放。

尝试3:C语言提供了结构体。使用结构体,内部可以定义多个不同类型的变量作为其成员。

考研中见的最多的就是指针和结构体结合起来构造结点(如链表的结点、二叉树的结点等)。

1.2 结构体的理解

C 语言提供了 struct关键字,允许自定义复合数据类型,将不同类型的值组合在一起,这种类型称为结构体(structure)类型。

C 语言没有其他语言的对象(object)和类(class)的概念,struct 结构很大程度上提供了对象和类的功能。

比如:

在这里插入图片描述

1.3 声明结构体

构建一个结构体类型的一般格式:

struct 结构体名{
    
    数据类型1 成员名1;   //分号结尾
    数据类型2 成员名2; 
    ……
    数据类型n 成员名n;
}; //注意最后有一个分号

举例:学生

struct Student{
          // 定义结构体:学生
    int id;           //学号
    char name[20];    //姓名
    char gender;      //性别
    char address[50]; //家庭住址
};  

举例:猫

struct Cat{
   
    char name[20];   //名字
    int age;         //年龄
    char color[20];  //颜色
};

举例:人类

struct Person{
   
    char name[20];    //姓名
    char gender;      //性别
    int age;          //年龄
    double weight;    //体重
}; 

举例:通讯录

struct Contacts{
               
    char name[50];          //姓名
    int year;               //年
    int month;              //月
    int day;                //日
    char email[100];        //电子邮箱
    char phone_number[15]; //手机号
};

举例:员工

struct Employee {
     
    int id;               //员工编号 
    char name[20];		  //员工姓名
    char gender;		  //员工性别
    int age;			  //员工年龄
    char address[30];	  //员工住址
};

1.4 声明结构体变量并调用成员

定义了新的数据类型以后,就可以声明该类型的变量,这与声明其他类型变量的写法是一样的。

声明结构体变量格式1:

struct 结构体类型名称 结构体变量名;

注意,声明自定义类型的变量时,类型名前面,不要忘记加上 struct 关键字。

举例:

struct Student stu1;

调用结构体变量的成员:

结构体变量名.成员名 [= 常量或变量值]

举例:

#include <stdio.h>
#include <string.h>
int main() {
   

    struct Student stu1; //声明结构体变量
	
    //调用结构体成员
    stu1.id = 1001;
    //stu1.name = "Tom"; //报错,不能直接通过赋值运算符来给字符数组赋值
    strcpy(stu1.name, "Tony");
    stu1.gender = 'M';
    strcpy(stu1.address, "北京市海淀区五道口");

    printf("id = %d,name = %s,gender = %c,address = %s\n", 
           stu1.id, stu1.name, stu1.gender, stu1.address);

    return 0;
}

说明:

1)先声明了一个 struct Student类型的变量 stu1,这时编译器就会为 stu1 分配内存,接着就可以为 stu1 的不同属性赋值。可以看到,struct 结构的属性通过点( . )来表示,比如 id 属性要写成 stu1.id。

2)字符数组是一种特殊的数组,直接改掉字符数组名的地址会报错,因此不能直接通过赋值运算符来对它进行赋值。你可以使用字符串库函数 strcpy() 来进行字符串的复制操作。

声明结构体变量格式2:

除了逐一对属性赋值,也可以使用大括号,一次性对 struct 结构的所有属性赋值。此时,初始化的属性个数最好与结构体中成员个数相同,且成员的先后顺序一一对应。格式:

struct 结构体名 结构体变量={
   初始化数据};

举例:

//声明结构体
struct Car {
   
  char* name;
  double price;
  int speed;
};

//声明结构体变量
struct Car audi = {
   "audi A6L", 460000.99, 175};

注意:如果大括号里面的值的数量少于属性的数量,那么缺失的属性自动初始化为 0 。

struct Student {
   
    int id;
    char name[20];
    char gender;
    int score;  //学生成绩

};

int main() {
   
    struct Student stu = {
   1001, "songhk", 'M'};
    printf("Name: %s\n", stu.name);
    printf("Score: %d\n", stu.score);

    return 0;
}

声明结构体变量格式3:

方式2中大括号里面的值的顺序,必须与 struct 类型声明时属性的顺序一致。此时,可以为每个值指定属性名。

格式:

struct 结构体名 结构体变量={
   .成员1=xxx,.成员2=yyy,...};

举例:

struct Car audi = {
   .speed=175, .name="audi A6L"};

同样,初始化的属性少于声明时的属性,剩下的那些属性都会初始化为 0 。

声明变量以后,可以修改某个属性的值。

struct Car audi = {
   .speed=175, .name="audi A6L"};
audi.speed = 185;  //将 speed 属性的值改成 185

声明结构体变量格式4: 声明类型的同时定义变量

struct 的数据类型声明语句与变量的声明语句,可以合并为一个语句。格式:

struct 结构体名 {
   
    成员列表
} 变量名列表;

举例:同时声明了数据类型 Circle 和该类型的变量 c1

struct Circle {
   
	int id;
    double radius;
} c1;

举例:

struct Employee {
   
    char name[20];
    int age;
    char gender;
    char phone[11];
} emp1, emp2;

声明结构体变量格式5: 不指定类型名而直接定义结构体类型变量

如果类型标识符(比如Student、Circle、Employee等)只用在声明时这一个地方,后面不再用到,那就可以将类型名省略。 该结构体称为匿名结构体

格式:

struct {
   
    成员列表;
} 变量名列表;

举例:

struct {
   
    char name[20];
    int age;
    char gender;
    char phone[11];
} emp1, emp2;

struct 声明了一个匿名数据类型,然后又声明了这个类型的两个变量emp1、emp2 。与其他变量声明语句一样,可以在声明变量的同时,对变量赋值。

举例:

struct {
   
    char name[20];
    int age;
    char gender;
    char phone[11];
} emp1 = {
   "Lucy", 23, 'F', "13012341234"},
  emp2 = {
   "Tony", 25, 'M', "13367896789"};

上例在声明变量 emp1 和 emp2 的同时,为它们赋值。

**声明结构体变量格式6:**使用 typedef 命令

使用 typedef 可以为 struct 结构指定一个别名,这样使用起来更简洁。

举例:

//声明结构体
typedef struct cell_phone {
   
    int phone_no;              //电话号码
    double minutes_of_charge;  //每分钟费用
} Phone;

//声明结构体变量
Phone p = {
   13012341234, 5};

上例中, Phone 就是 struct cell_phone 的别名。声明结构体变量时,可以省略struct关键字。

这种情况下,C 语言允许省略 struct 命令后面的类型名。进一步改为:

//声明匿名结构体
typedef struct {
   
    int phone_no;
    double minutes_of_charge;
} Phone;

//声明结构体变量
Phone p = {
   13012341234, 5};

进一步,在考研中,还会出现如下的声明方式:

typedef struct {
   
    int phone_no;
    double minutes_of_charge;
} Phone,*pPhone;

这里多了个*pPhone,其实在定义一个结点指针p时,Phone *p; 等价于 pPhone p; ,前者的写法类似于int *a、char *b等更方便记忆,不必再加个pPhone p来增加记忆负担。所以在考研中我们不采用这种方法,统一删掉 *pPhone的写法。

说明:

1、在创建一个结构体变量后,需要给成员赋值。在没有给成员赋值的情况下调用,打印的值是垃圾数据,可能导致程序异常终止。

2、不同结构体变量的成员是独立的,互不影响,一个结构体变量的成员更改,不影响另外一个。

1.5 举例

练习:盒子案例

(1)编程创建一个Box结构体,在其中定义三个成员表示一个立方体的长、宽和高,长宽高可以通过控制台输入。

(2)定义一个函数获取立方体的体积(volume)。

(3)创建一个结构体,打印给定尺寸的立方体的体积。

#include <stdio.h>

// 1. 定义Box结构体
struct Box {
   
    double length;
    double width;
    double height;
};

// 2. 获取立方体体积的函数
double getVolume(struct Box box) {
   
    return box.length * box.width * box.height;
}

int main() {
   

    // 3. 创建结构体实例
    struct Box box;
    printf("输入长度:");
    scanf("%lf", &box.length);

    printf("输入宽度:");
    scanf("%lf", &box.width);

    printf("输入高度:");
    scanf("%lf", &box.height);

    // 调用函数获取体积并打印
    printf("体积为: %.2lf\n", getVolume(box));

    return 0;
}

1.6 小 结

区分三个概念:结构体、结构体变量、结构体变量的成员。

  • 结构体是自定义的数据类型,表示的是一种数据类型。

  • 结构体变量代表一个具体变量。类比:

    int num1 ; // int 是数据类型, 而num1是一个具体的int变量
    
    struct Car car1; // Car 是结构体数据类型,而car1是一个Car变量
    
  • Car 就像一个“汽车图纸”,生成出来的具体的一辆辆汽车,就类似于一个个的结构体变量。这些结构体变量都含有相同的成员,将结构体变量的成员比作“零件”,同一张图纸生产出来的零件的作用都是一样的。

2、进一步认识结构体

2.1 结构体嵌套

结构体的成员也是变量,那么成员可以是基本数据类型,也可以是数组指针结构体等类型 。如果结构体的成员是另一个结构体,这就构成了结构体嵌套。

举例1:

#include <stdio.h>
#include <string.h>

struct Name {
   
    char firstName[50];
    char lastName[50];
};

struct Student {
   
    int age;
    struct Name name;
    char gender;
} stu1;

int main(){
   
    strcpy(stu1.name.firstName, "美美");
    strcpy(stu1.name.lastName, "韩");
    //stu1.age = 18;
    //stu1.gender = 'F';

    //或者
    struct Name myname = {
   "美美","韩"};
    stu1.name = myname;
    //stu1.age = 18;
    //stu1.gender = 'F';
    return 0;
}

举例2:

struct Date {
       //声明一个结构体类型 struct Date 
    int year;    //年
    int month;   //月
    int day;     //日
};

struct Employee {
    //声明一个结构体类型 struct Employee
    int id;
    char name[20];
    int age;
    struct Date birthday; //成员birthday属于struct Date类型
};

声明结构体变量并调用成员:

#include <stdio.h>
#include 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/321433.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JDK8-JDK17版本升级

局部变量类型推断 switch表达式 文本块 Records 记录Records是添加到 Java 14 的一项新功能。它允许你创建用于存储数据的类。它类似于 POJO 类&#xff0c;但代码少得多&#xff1b;大多数开发人员使用 Lombok 生成 POJO 类&#xff0c;但是有了记录&#xff0c;你就不需要使…

保卫战小游戏

欢迎来到程序小院 保卫战 玩法&#xff1a;当鬼子进入射击范围内点击鼠标左键射击&#xff0c;不要让鬼子越过炮台哦&#xff0c;快去杀鬼子去吧^^。开始游戏https://www.ormcc.com/play/gameStart/249 html <div style"position: relative;" id"gameDiv&q…

K 个一组翻转链表(链表反转,固定长度反转)(困难)

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你链表的头节点head&#xff0c;每k个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是k的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。…

Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c…

Spring Boot - 利用Resilience4j-RateLimiter进行流量控制和服务降级

文章目录 Resilience4j概述Resilience4j官方地址Resilience4j-RateLimiter微服务演示Payment processorPOM配置文件ServiceController Payment servicePOMModelServiceRestConfigController配置验证 探究 Rate Limiting请求三次 &#xff0c;观察等待15秒连续访问6次 Resilienc…

安装nodejs出现问题

Error: EPERM: operation not permitted, mkdir… 全局安装express模块进行测试时&#xff1a; npm install express -g出现&#xff1a; 表示nodejs的安装目录无权限&#xff0c;根据错误日志的信息&#xff0c;定位到安装目录下&#xff1a; 点击属性&#xff1a; 点击编…

优先级队列(Priority Queue)

文章目录 优先级队列&#xff08;Priority Queue&#xff09;实现方式基于数组实现基于堆实现方法实现offer(E value)poll()peek()isEmpty()isFull() 优先级队列的实现细节 优先级队列&#xff08;Priority Queue&#xff09; 优先级队列是一种特殊的队列&#xff0c;其中的元素…

Jsqlparser简单学习

文章目录 学习链接模块访问者模式parser模块statement模块Expression模块deparser模块 测试TestDropTestSelectTestSelectVisitor 学习链接 java设计模式&#xff1a;访问者模式 github使用示例参考 测试 JSqlParser使用示例 JSqlParse&#xff08;一&#xff09;基本增删改…

第02章_变量与运算符拓展练习

文章目录 第02章_变量与运算符拓展练习1、辨别标识符2、数据类型转换简答3、判断如下代码的运行结果(难)4、判断如下程序的运行结果5、判断如下程序的运行结果6、Java的基本数据类型有哪些&#xff1f;String是基本数据类型吗&#xff1f;7、语法判断8、char型变量中是否可以存…

LeeCode前端算法基础100题(20)找出字符串中第一个匹配项的下标

一、问题详情: 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 示例 1: 输入:haystack = "sadbutsad", needle = "s…

【现代密码学】笔记 补充7-- CCA安全与认证加密《introduction to modern cryphtography》

【现代密码学】笔记7-- CCA安全与认证加密《introduction to modern cryphtography》 写在最前面7 CCA安全与认证加密 写在最前面 主要在 哈工大密码学课程 张宇老师课件 的基础上学习记录笔记。 内容补充&#xff1a;骆婷老师的PPT 《introduction to modern cryphtography》…

鸿蒙应用开发学习:让page页面强制横屏

一、学习做了个适合横屏的页面但进入页面后是竖屏显示的 前几天在B站上跟着 黑马程序员的 HarmonyOS4.0开发应用教学视频学习了显式动画&#xff08;animateTo&#xff09;和属性动画&#xff08;animation&#xff09;功能&#xff0c;并参照教学视频的内容做了个小鱼动画。…

助力工业园区作业违规行为检测预警,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建工业园区场景下作业人员违规行为检测识别系统

在很多工业园区生产作业场景下保障合规合法进行作业生产操作&#xff0c;对于保护工人生命安全降低安全隐患有着非常重要的作用&#xff0c;但是往往在实际的作业生产中&#xff0c;因为一个安全观念的淡薄或者是粗心大意&#xff0c;对于纪律约束等意思薄弱&#xff0c;导致在…

绝地求生:【PC】第27赛季第2轮更新公告

各位玩家大家好&#xff01;欢迎收看本期闲游盒更新公告。 正式服维护时间 ※ 下列时间可能会根据维护情况而发生变化。 1月10日上午8:00 – 下午4:30 地图轮换 ※ 地图轮换将于每周三上午10点进行。 ※ 在随机选择地图的地区中&#xff0c;第1周可选择荣都地图&#xff0c…

UML-通信图和交互概览图(通信图和顺序图的区别与联系)

UML-通信图和交互概览图&#xff08;通信图和顺序图的区别与联系&#xff09; 一、通信图简介1.消息2.链接 二、通信图和[顺序图](https://blog.csdn.net/weixin_65032328/article/details/135587782)的联系与区别三、交互概览图四、顺序图转化为通信图练习 一、通信图简介 通…

CSC8021_computer network_The Transport Layer

Role of the transport layer • The transport layer is responsible for providing a reliable end-to-end connection between two application processes in a network • Abstracting away the physical subnet • Does not involve intermediate nodes • Takes a netwo…

2024--Django平台开发-Redis集群(十一)

内容回顾 主从复制。 哨兵&#xff1a;实例启动了&#xff0c;哨兵节点没启动&#xff0c;Python通过redis-py连接报错。一定要确保实例节点和哨兵节点都启动了。 搭建集群用的是虚拟机的多台centos服务器&#xff0c;你在跟着学习的时候&#xff0c;一定要全部都是虚拟机&am…

MySQL面试题2

文章目录 面试题 (9-15) 面试题 (9-15) 09&#xff09;查询学过「张三」老师授课的同学的信息 SELECT s.*,c.cname,t.tname FROM t_mysql_teacher t,t_mysql_student s,t_mysql_course c,t_mysql_score sc WHERE t.tidc.tid and c.cidsc.cid and sc.sids.sid and tname ‘张…

EI级 | Matlab实现VMD-TCN-BiLSTM变分模态分解结合时间卷积双向长短期记忆神经网络多变量光伏功率时间序列预测

EI级 | Matlab实现VMD-TCN-BiLSTM变分模态分解结合时间卷积双向长短期记忆神经网络多变量光伏功率时间序列预测 目录 EI级 | Matlab实现VMD-TCN-BiLSTM变分模态分解结合时间卷积双向长短期记忆神经网络多变量光伏功率时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基…

QLExpress和Groovy对比

原理 Groovy groovy基于JVM运行。 编译时&#xff1a;将源文件编译成class文件后&#xff0c;用java的classLoader加载&#xff1b;运行时&#xff1a;直接用groovy classLoader加载 QLExpress QLExpress将文本解析成AST&#xff0c;用java对象表达后执行。 特点 Groo…