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.5No.: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
所有节点都是在程序中定义的,不是临时开辟的,也不能用完之后释放,这种链表称为“静态链表”