当前位置: 首页 > 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部分再学习

http://www.xdnf.cn/news/500347.html

相关文章:

  • 【springcloud学习(dalston.sr1)】Zuul路由访问映射规则配置及使用(含源代码)(十二)
  • 玩转 AI · 思考过程可视化
  • 【gitee 初学者矿建仓库】
  • 【Ragflow】22.RagflowPlus(v0.3.0):用户会话管理/文件类型拓展/诸多优化更新
  • 51单片机课设基于GM65模块的二维码加条形码识别
  • python第二十八天
  • Oracle APEX IR报表下载CSV文件的方法
  • [Java] 方法和数组
  • FauxGen:一款由 CodeBuddy 主动构建的假数据生成器
  • 语音转文字
  • 使用Spring Boot与Spring Security构建安全的RESTful API
  • 基于大疆Mini 3无人机和指定软件工具链的完整3D建模工作
  • JavaScript防抖与节流全解析
  • C# lock
  • 端到端自动驾驶系统实战指南:从Comma.ai架构到PyTorch部署
  • 通义千问-langchain使用构建(三)
  • 2025年渗透测试面试题总结-百度面经(题目+回答)
  • YOLO (You Only Look Once)版本历程学习
  • Java泛型详解
  • Vue百日学习计划Day21-23天详细计划-Gemini版
  • Elasticsearch 官网阅读之 Term-level Queries
  • 关于软件测试开发的一些有趣的知识
  • ElasticSearch 8.x新特性面试题
  • 【论文阅读】针对BEV感知的攻击
  • python:gimp 与 blender 两个软件如何协作?
  • 5.27本日总结
  • JSP链接MySQL8.0(Eclipse+Tomcat9.0+MySQL8.0)
  • markdown 文档编辑软件 MarkText 使用教程
  • QT软件安装
  • 项目复习(1)