C语言--结构体(内容超级详细)

一.前言

       通过数据类型来定义一个一个的变量,当需要很多相同类型的变量时有数组。基本数据类型在使用时 很方便,但是利用它们来描述现实世界就显得捉襟见肘。例如需要保存一个班学生的信息”姓名,年龄,分 数”,按照前面的学习需要单独定义三个数组,一个保存姓名,一个保存年龄,一个保存分数。这样定义对于后面的维护,修改,删除会带来麻烦。好比你用三个记事本一个记录学生姓名,一个记录年龄,一个记录分数,如 果删除姓名记事本中的第十个学生,而在年龄,分数记事本中却删除了第十一个,这是很容易发生的。实际 中并不会这么做,我们会利用一个Excel表来记录学生的信息,一行就是一个学生的所有信息,修改,添加,删除 都非常清晰。这就是要介绍的自定义数据类型之一——结构体。

自定义数据类型:根据自己的需要定义新的数据类型。

自定义数据类型包括结构体:位段,共用体和枚举。当然最重要的就是今天介绍的结构体。


二.结构体的定义及初始化

  • 结构体的定义

struct 结构体类型名称
{结构体成员1;结构体成员2;......结构体成员n;
};

 例如:定义一个学生结构体,包含姓名和年龄。

struct Student//定义学生结构体
{char name[20]; //姓名int age; //年龄
}; //类型定义完成

这个类型定义好了之后就和基本类型一样使用,可以用来定义单个变量,数组,指针或者作为另一个结 构体的成员。 

  • 定义单个变量

类似基本数据类型,可以用来定义单个变量。

struct Student//定义学生结构体
{char name[20]; //姓名int age; //年龄
}; //类型定义完成
int main()
{struct Student stu1;//未初始化,默认是随机值struct Student stu2 = { "小红"};//初始化一部分,剩余部分为0,即小红的年龄为0struct Student stu3 = { "小刚",20 };//全部初始化return 0;
}

图解: 

 ​​​​​​

  • 访问结构体成员

结构体变量定义好之后该如何访问它的成员呢?如何输出 stu3 中的信息呢?

结构体普通变量通过”.” 号访问其成员。

printf("%s,%d\n", stu3.name, stu3.age); //stu3.name,stu3.age

输出 stu3 信息的代码如下:

 修改结构体变量的数据代码如下:

比如,stu1中的内容是:小新,18

再比如,想把stu3中的小刚改为小斌,年龄改为17

#include<stdio.h>
#include<string.h>
struct Student//定义学生结构体
{char name[20]; //姓名int age; //年龄
}; //类型定义完成int main()
{struct Student stu1;//未初始化,默认是随机值struct Student stu2 = { "小红" };//初始化一部分,剩余部分为0,即小红的年龄为0struct Student stu3 = { "小刚",20 };//全部初始化//普通变量通过 .号访问成员,例如:请打印stu3中的内容printf("%s,%d\n", stu3.name, stu3.age); //stu3.name //如何修改结构体中的数据呢?//比如,stu1中的内容是:小新,18strcpy(stu1.name, "小新"); //由于姓名是字符串,所以不能直接赋值 stu1.name="小新"是错误的stu1.age = 18;printf("%s,%d\n", stu1.name, stu1.age);//再比如,想把stu3中的小刚改为小斌,年龄改为17strcpy(stu3.name, "小斌");stu3.age = 17;printf("%s,%d\n", stu3.name, stu3.age);return 0;
}

 运行结果:

  •  结构体作为其它结构体成员

结构体定义完成后,其作用和基本类型一样,那当然是可以作为其它结构体的成员变量。例如:

#include<stdio.h>
#include<string.h>
struct Date
{int year;int month;int day;
};//一个结构体作为另一个结构体的成员
struct Person
{char name[20];  //姓名int age;		//年龄char sex[20];		//性别struct Date birthday;	//出生年月日
};int main()
{struct Person per = { "小小苏",20,"男",2003,10,11 }; //初始化//打印结构体的内容intf("姓名:%s\n年龄:%d\n性别:%s\n出生日期:%d年,%d月,%d日", per.name, per.age, per.sex,per.birthday.year, per.birthday.month, per.birthday.day);return 0;
}

运行结果:

图解:

  • 结构体指针访问其成员

结构体指针ps如何访问结构体的成员呢?一个笨办法就是(*ps).age这种形式。注意一定要加”()”,因为” *”的优先级低于”.”,这个办法不仅容易出错,写起来也繁琐,C语言有一种更简洁的表达形式。 结构体指针通过”->”访问其成员。 例如下面代码。

繁琐代码:

struct Student
{char name[20];int age;
};int main()
{struct Student stu = { "小小苏",20 };//定义结构体Student 变量stu 初始化//struct Student地位相当于int,是一个类型  struct Student* ps = &stu;//定义一个结构体指针变量 ps 用于保存stu的地址printf("%s,%d", (*ps).name, (*ps).age);//要注意优先级问题return 0;
}

 运行结果:

简介版本:一般都用这种

struct Student
{char name[20];int age;
};int main()
{struct Student stu = { "小小苏",20 };//定义结构体Student 变量stu 初始化//struct Student地位相当于int,是一个类型  struct Student* ps = &stu;//定义一个结构体指针变量 ps 用于保存stu的地址//printf("%s,%d", (*ps).name, (*ps).age);//这个方法繁琐,易错printf("%s,%d\n", ps->name, ps->age);return 0;
}

运行结果: 

我们可以发现,两种写法都可以,第二种更加简洁。另外提一嘴:人都是想要偷懒的,不论做什么事情,写代码也是一样,发明c语言的老头发现,每次都要写括号,注意优先级的问题,很容易写错,因此他们就发明了一种不要写的方法,直接用箭头指向,没办法,就是这么任性,谁让c语言是他发明的呢。要是我们也是一种语言的发明人,那我们也可以自己任性地定义。 

总结:结构体普通变量通过”.”访问其成员,结构体指针变量通过”->”访问其成员。

三.结构体数组定义及使用

  • 结构体数组定义

   结构体定义完成后和内置类型一样使用,能定义变量,指针当然也可以定义数组。

struct Student
{char name[20];int age;
};int main()
{//内置类型,定义指针,变量,数组int a = 10;int* p = &a;int arr[10] = {};//结构体类型,定义指针,变量,数组struct Student stu = { "小小苏",20 }; //结构体类型定义普通变量struct Student* ps = &stu;//结构体类型定义指针变量struct Student brr[3] = {};struct Student crr[3] = { {"曹操",23},{"刘备",25},{"孙权",18} };struct Student drr[3] = { "曹操",23,"刘备",25,"孙权",18 };struct Student err[] = { "曹操",23,"刘备",25,"孙权",18 };//结构体类型定义数组return 0;
}

 图解:

  

四.结构体数组的使用 

          例如上图中的crr,该如何访问其每个元素呢?

方法一:通过下标遍历数组

方法二:通过指针遍历数组

#include<stdio.h>
struct Student
{char name[20];int age;
};int main()
{struct Student crr[3] = { {"曹操",18},{"刘备",19},{"孙权",20} };//方法一:通过下标遍历数组//for (int i = 0;i < sizeof(crr) / sizeof(crr[0]);i++)//{//	printf("%s,%d\n", crr[i].name, crr[i].age);//}//方法二:通过指针遍历数组struct Student* ps = &crr[0];while (ps <= &crr[2]){printf("%s,%d\n", ps->name, ps->age);ps++;}return 0;
}

  类似数组的访问形式,可以通过下标访问,也可以通过指针遍历。 如果要将上面的输出语句改成一个函数,那么结构体该如何通过参数传递呢?当然也是类似数组的传 递形式,一个指针,一个长度。如下:

void Show(struct Student* arr, int len) //数组首地址和数组长度
{for (int i = 0; i < len; i++){printf("%s,%d\n", arr[i].name, arr[i].age);}
}
int main()
{struct Student crr[3] = { {"曹操",23},{"刘备",25},{"孙权",18} };Show(crr, sizeof(crr) / sizeof(crr[0]));//传数组的首元素地址和数组长度//也可以这样//Show(&crr[0], sizeof(crr) / sizeof(crr[0])); //这种写法与上面的写法是一样的return 0;
}

 五.结构体的应用

例.有3个候选人,每个选民只能投票选一人,要求编一个统计选票的程序,先后输入被选人的名 字,最后输出各人得票结果。 解题思路: 设一个结构体数组,数组中包含3个元素; 每个元素中的信息应包括候选人的姓名和得票数; 输入被选人的姓名,然后与数组元素中的“姓名”成员比较,如果相同,就给这个元素中的“得票数”成 员的值加1; 输出所有元素的信息。

struct Person //定义候选人
{char name[20];//姓名int count; //票数
};
void Ticket(struct Person* p, int len)//计票程序
{char name[20]; //保存投票的数据for (int i = 0; i < 5; i++)//模拟5个选民{scanf("%s", name); //读取选票for (int j = 0; j < len; j++)//和候选人比较{if (strcmp(name, p[j].name) == 0){p[j].count++;//选票加1break;//匹配成功,不需要再和后面的候选人匹配}}}
}
void Show(const struct Person* p, int len)//输出程序
{for (int i = 0; i < len; i++){printf("姓名:%s,票数:%d\n", (p + i)->name, (p + i)->count);}
}
int main()
{struct Person leader[3] = { "曹操",0,"刘备",0,"孙权",0 };Ticket(leader, sizeof(leader) / sizeof(leader[0]));Show(leader, sizeof(leader) / sizeof(leader[0]));return 0;
}

运行结果:

 今天的分享就到这里啦,感谢支持,如有错误可以与小编交流哦!

  如果喜欢的话,可以关注吗?小编将感激不尽。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使新手小白编码能力暴涨之Devchat-AI

在这个快速发展的时代&#xff0c;开发者的任务越来越繁重&#xff0c;要求他们快速、高效地完成开发任务。然而&#xff0c;传统的开发方式已经无法满足这个需求。在这种情况下&#xff0c;Devchat的出现给开发者带来了新的帮助。Devchat是一个研发效能分析平台&#xff0c;它…

Java8强大的新特性 —— “Stream API”

一、什么是Stream API&#xff1f; Java Stream API是Java 8中引入的一个重要功能&#xff0c;它允许开发者以声明性方式处理数据集合&#xff0c;使代码更加简洁、可读性更好&#xff0c;同时还提供了并行操作的能力&#xff0c;从而能够更有效地利用多核处理器。 Stream AP…

【达梦数据库】学习笔记

【达梦数据库】学习笔记 【一】如何使用idea连接达梦数据库【二】idea项目导入本地的达梦数据库驱动jar包 【一】如何使用idea连接达梦数据库 &#xff08;1&#xff09;打开idea&#xff0c;点击右上角的数据库 &#xff08;2&#xff09;把达梦数据库的jar包配置一下 找到…

Centos7部署Python3环境

一、安装Python3 ###查看是否安装Python3 Centos 7 默认安装了python 2.7.5. 因为一些命令要用它比如yum 它使用的是python2.7.5 使用 python -V 命令查看一下是否安装Python 然后使用命令 which python 查看一下Python可执行文件的位置 Python指向的是Python2.7 安装依赖 y…

武汉某母婴用品公司 - 集简云连接ERP和营销系统,实现库存管理的自动化

品牌介绍与关怀理念 武汉某母婴用品公司是一家专注于高端孕婴童护理用品的企业&#xff0c;积极响应和关怀孕产人群&#xff0c;全方位提供从待产用品到产后护理用品&#xff0c;再到婴童洗护用品和初生婴儿用品等一系列全面的母婴产品。我们的使命是满足客户的需求&#xff0…

6.判断是不是闰年

#include<stdio.h>void fun(int year){if(year%40&&year%100!0||year%4000)printf("%d 是闰年\n",year);elseprintf("%d 不是闰年\n",year);}int main(){int year;scanf("%d",&year);fun(year);return 0;}

【qemu逃逸】华为云2021-qemu_zzz

前言 虚拟机用户名&#xff1a;root 无密码 设备逆向 经过逆向分析&#xff0c;可得实例结构体大致结构如下&#xff1a; 其中 self 指向的是结构体本身&#xff0c;cpu_physical_memory_rw 就是这个函数的函数指针。arr 应该是 PCI 设备类结构体没啥用&#xff0c;就直接用…

Spring Cloud学习(二)【Eureka注册中心】

文章目录 Eureka 注册中心Eureka 的作用 动手实践搭建 EurekaServer服务注册服务发现 Ribbon 负载均衡负载均衡原理IRule 接口&#xff08;负载均衡策略&#xff09;饥饿加载 Eureka 注册中心 服务调用出现的问题 不能采用硬编码服务消费者该如何获取服务提供者的地址信息&am…

数据库数据迁移常见方式

数据库数据迁移常见方式 数据库数据迁移常见方式1、通过sql2、通过数据迁移工具3、云服务进行数据迁移什么是DRS服务如何使用DRS服务DRS云服务可以干什么 数据库数据迁移常见方式 1、通过sql 批量导入sql insert into tableName select * 2、通过数据迁移工具 在数据库里面…

分支限界法求解迷宫问题

问题描述 从入口出发&#xff0c;按某一方向向前探索&#xff0c;若能走通(未走过的&#xff09;&#xff0c;即某处可以到达&#xff0c;则到达新点&#xff0c;否则试探下一方向&#xff1b;若该点所有的方向均没有通路&#xff0c;则沿原路返回到前一点&#xff0c;换下一个…

基于springboot实现招聘信息管理系统项目【项目源码+论文说明】

基于springboot实现招聘信息管理系统演示 摘要 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括招聘信息管理系统的网络应用&#xff0c;在外国招聘信息管理系统已经是很普遍的方式&#xff0c;不过国内的线上管理系统可能还…

野火霸天虎 STM32F407 学习笔记_3 尝试寄存器映射方式点亮 LED 灯

新建工程 寄存器方式 要命啊&#xff0c;一看名字我就不想试。寄存器新建不得麻烦死。 哎算了为了学习原理&#xff0c;干了。 我们尝试自己写一个寄存器的库函数来引用。 首先我们需要引用 st 官方启动文件 stmf4xx.s&#xff0c;具体用途后面章节再展开讲解。然后我们自…

算法打卡01——求两数之和

题目&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你…

NtripShare Caster高精度定位CORS服务软件

NtripShare CORS是NtripShare GNSS系列软件中最早的软件系统&#xff0c;也是NtripShare名称的起源。 所谓GNSS CORS服务系统一般构成&#xff1a; 1&#xff09;基准站网&#xff1a;由若干个分布合理的GNSS 基准站组成&#xff1b; 2&#xff09;数据传输系统&#xff1a;…

贰[2],OpenCV函数解析

1&#xff0c;imread&#xff1a;图片读取 CV_EXPORTS_W Mat imread( const String& filename, int flags IMREAD_COLOR );//参数1(filename)&#xff1a;文件地址 //参数2(flags):读取标志 注:ImreadModes&#xff0c;参数2(flags)枚举定义 enum ImreadModes { IMREAD…

Android 接入ttf字体文件

一、业务实现 一些炫酷的App总会加一些App自己的字体。这时候需要找UI提供ttf字体文件。 然后实现 TTF&#xff08;TrueType Font&#xff09;字体文件并将其应用到 TextView。 二、大致流程 将 TTF 字体文件添加到你的 Android 项目中&#xff1a; 将 TTF 文件复制到 res/f…

K8S知识点(六)

&#xff08;1&#xff09;资源管理方式1 其他参数 其他参数以json格式显示pod信息 以yaml显示pod信息&#xff1a; 用describe描述容器的详细信息&#xff1a;包括ip啊&#xff0c;镜像啊&#xff0c;端口啊&#xff0c;容器启动经历的历程 创建命名空间Pod&#xff1a; 查询…

Excel文档名称批量翻译的高效方法

在处理大量文件时&#xff0c;我们常常需要借助一些工具来提高工作效率。例如&#xff0c;在需要对Excel文档名称进行批量翻译时&#xff0c;一个方便快捷的工具可以帮助我们省去很多麻烦。今天&#xff0c;我将介绍一款名为固乔文件管家的软件&#xff0c;它能够帮助我们轻松实…

解决 SSLError: HTTPSConnectionPool(host=‘huggingface.co‘, port=443)

看我的回答&#xff1a; https://github.com/huggingface/transformers/issues/17611#issuecomment-1794486960 能问这个问题的都是网络不太好的&#xff0c;你懂的&#xff0c;所以答案全是解决网络的。 得益于这个回答&#xff1a;#17611 (comment) 看了一下代码&#xf…

The valid characters are defined in RFC 7230 and RFC 3986

服務器通過Body 對象接收參數&#xff0c;而客戶端通過param 地址URL傳參數&#xff0c;不能解析。 return axiosHelper<Protocol<ABC[]>>({method: POST,url: ,data: _reqparams: {data: _req}}) public List<InvoiceItem> getAAAA(RequestBody Query quer…