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

C语言—再学习(结构体)

一、建立结构体

用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体。

struct Student 
{  int num;       //学号char name[20]; //名字为字符串char sex;       //性别int age;         //年纪float score;     //分数char addr[30];   地址为字符串
};   //注意最后有分号

可以看到先是指定一个结构体类型  struct Student (struct 是声明, 结构体类型时候必须压迫使用的关键字,不能省略!!!!),它向编译系统声明:这是一个“结构体类型”,它包括num,name,sex,age,score,addr等不同类型成员。

所以一般形式为:

struct 结构体名

{

 成员列表

} ;            //别忘了分号

花括号里的成员列表:  类型名  成员名;

二、定义一个结构体变量

开头声明的Student 结构体,可以用它来定义变量。 

1.先声明结构体,再定义变量。

例如:  struct Student  student1 , student2;

这样student1和student2就具有和Student类型的结构了。

2.在声明类型的同时定义变量

struct Student 
{  int num;       //学号char name[20]; //名字为字符串char sex;       //性别int age;         //年纪float score;     //分数char addr[30];   地址为字符串
}student1,student2;

引用结构体变量: student1.age=23;

三、结构体数组

例题:有三个候选人,每个选民只能投票一个人,要求编写一个统计选票程序,先输入被选人的名字,最后输出各人得票结果。

#include <stdio.h>
#include <string.h>struct Person{       // 声明结构体类型char name[20];   //候选人姓名int count;        //候选人得票数
}leader[3] = {"Li",0,"Zhang",0,"Sun",0};   //定义结构体数组并且初始化int main(){int i,j;char leader_name[20];      //定义字符数组for(i=1;i<=10;i++){scanf("%s",leader_name);  //输入所选的候选人姓名for(j=0;j<3;j++){if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;}   //strcmp 是比较字符串的意思,字符串不相等则输出0}printf("\nResult:\n");for(i=0;i<3;i++)printf("%5s:%d\n",leader[i].name,leader[i].count);return 0;
}

结果:

Li
Zhang
Sun
Zhang
Li
Zhang
Sun
Zhang
Li
ZhangResult:Li:3
Zhang:5Sun:2

 首先定义了一个全局的结构体数组leader,它有三个元素,每个元素包含两个成员name和count。

再定义数组时使之初始化,将“Li”赋给leader[0].name , 0赋给leader[0].count,"Zhang"赋给leader[1].name , 0赋给leader[1].count。......这三个候选人的票数全部先置0。

所以定义结构体数组的一般形式为:

struct 结构体名{
成员列表
}数组名[数组长度]//还可以:结构体类型  数组名[数组长度];struct Person leader[3];

四、结构体指针

1.指向结构体变量的指针

例题:通过指向结构体变量的指针变量输出结构体变量中成员的信息。

#include <stdio.h>
#include <string.h>int main(){struct Student{long num;char name[20];char sex;float score;}; struct Student stu_1;   //定义struct Student类型变量stu_1 struct Student *p;      //定义指向struct Student类型数据的指针变量p p = &stu_1;             //p指向stu_1 stu_1.num = 10101;     //对结构体变量的成员赋值 strcpy(stu_1.name,"Li Lin");  //用字符串赋值函数给stu_1.name赋值 stu_1.sex= 'M';stu_1.score = 89.5;printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",stu_1.num,stu_1.name,stu_1.sex,stu_1.score) ;printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",(*p).num,(*p).name,(*p).sex,(*p).score) ;return 0;
} 

结果:

No.:10101
name:Li Lin
sex:M
score: 89.5

No.:10101
name:Li Lin
sex:M
score: 89.5

分析:将结构体变量stu_1的起始地址赋给指针变量p,也就是使p指向stu_1,然后对stu_1的各个成员赋值。

⚠️:为了方便,(*p).num  可以用p->num 代替

2.指向结构体数组的指针

例题:有三个学生的信息,放在结构体数组里,要求输出全部学生的信息。

#include <stdio.h>struct Student{int num;char name[20];char sex;int age;
};
struct Student stu[3]={
{10101,"Li Lin",'M',18},{10102,"Zhang Fang",'M',19},{10104,"Wang Min",'F',20}
};
int main(){
struct Student *p;
printf(" No.  Name                 sex  age\n");
for(p=stu;p<stu+3;p++)printf("%5d %-20s %2c %4d\n",p->num,p->name,p->sex,p->age)	;return 0;
}

结果:

 No.  Name                 sex  age
10101 Li Lin                M   18
10102 Zhang Fang            M   19
10104 Wang Min              F   20

分析:在for循环里面,首先条件是先让p=stu,也就是stu中序号为0的元素的起始地址,第一次循环输出stu[0]的各个成员的置。然后执行p++,使p自加1。此时p的值就等于stu+1。指向了stu[1]了。

五、用指针处理链表

1.什么是链表?

一种线性数据结构,它由一系列节点(Node)组成,这些节点通过指针(或引用)连接成一个链条。与数组不同,链表的节点在内存中不需要连续存储,数据的逻辑顺序通过节点之间的指针来维持。

链表有一个”头指针“变量,图中是head表示,它存放着一个地址,该地址指向一个元素。链表中每个元素称为”节点“。可以看到head指向第一个元素,第一个元素有指向第二个元素......直到最后一个元素,该元素不在指向其它元素,它称为”表尾“,它的地址部分放一个“NULL”,表示空地址,链表到此结束。

节点至少包含两部分:

数据域:存储具体的数据值(如整数、字符串等)。

指针域:存储下一个节点的内存地址(或引用),用于连接节点。

⚠️:链表中各个元素的地址可以不连续,要找到某个元素,必须找到上一个元素,根据它提供的下一个元素地址才能找到下一个元素。如果不提供“头指针”则整个链表都无法访问。链表如同一条铁链一样。一环扣一环,中间无法断开。

打个比方:幼儿园老师带领孩子出来散步,老师牵着第一个孩子的手,第一个孩子牵着第二个孩子的手,......,最后一个孩子有一只手是空的,他是链尾。

2.建立简单的静态链表

例题:建立一个简单的静态链表,它由3个学生数据的节点组成,要求输出个节点中的数据

#include <stdio.h>// 定义学生结构体
struct Student {int num;         // 学号float score;     // 分数struct Student *next;  // 指向下一个节点的指针
};int main() {// 定义三个学生节点并初始化数据struct Student s1 = {101, 85.5, NULL};struct Student s2 = {102, 90.0, NULL};struct Student s3 = {103, 78.2, NULL};// 建立链表连接关系s1.next = &s2;s2.next = &s3;s3.next = NULL;  // 尾节点指针置为NULL// 定义指针指向头节点struct Student *ptr = &s1;// 使用do-while循环遍历链表并输出数据do {printf("学号: %d, 分数: %.1f\n", ptr->num, ptr->score);ptr = ptr->next;  // 移动到下一个节点} while (ptr != NULL);  // 当指针不为NULL时继续循环return 0;
}

输出结果:

学号: 101, 分数: 85.5
学号: 102, 分数: 90.0
学号: 103, 分数: 78.2

所有节点都是在程序中定义的,不是临时开辟的,也不能用完之后释放,这种链表称为“静态链表”

⚠️:还有很多关于链表的东西,待等到RTOS部分再学习

相关文章:

  • 高频面试题(含笔试高频算法整理)基本总结回顾120
  • 3、ubantu系统 | 通过vscode远程安装并配置anaconda
  • B站锁定三倍速(自用)
  • C/C++实践(十)C语言冒泡排序深度解析:发展历史、技术方法与应用场景
  • Windows系统信息收集指南
  • python如何做数据预测
  • C++ deque双端队列、deque对象创建、deque赋值操作
  • 软件设计师教程—— 第二章 程序设计语言基础知识(上)
  • DeepSeek指令微调与强化学习对齐:从SFT到RLHF
  • 【Linux笔记】——Linux线程封装
  • Transformer 架构在目标检测中的应用:YOLO 系列模型解析
  • 进阶-数据结构部分:3、常用查找算法
  • [Windows] 系统综合优化工具 RyTuneX 1.3.1
  • 最小二乘法拟合平面(线性回归法、梯度下降、PCA法)
  • 2025年PMP 学习十七 第11章 项目风险管理 (11.1~11.4)
  • GitHub文档加载器设计与实现
  • mAP、AP50、AR50:目标检测中的核心评价指标解析
  • 如何分析动态采样引起的计划不稳定 | OceanBase SQL 调优实践
  • MODBUS RTU通信协议详解与调试指南
  • 建筑兔零基础人工智能自学记录94|模式识别(上)-9
  • 陈刚:推动良好政治生态和美好自然生态共生共优相得益彰
  • 《风林火山》千呼万唤始出来,戛纳首映后口碑崩盘?
  • 李伟任山东省委常委、省纪委书记
  • “9+2”复式票,浦东购彩者拿下体彩大乐透1153万头奖
  • 订婚不等于性同意!山西订婚强奸案入选最高法案例
  • 将人工智能送上太空,我国太空计算卫星星座成功发射