单独的一条学生信息我们可以使用结构体类型的数据来保存,但是如果学生信息是多条,那么我们就要用另外一些方法来保存这些信息
保存多条结构体数据的方式大致有两种:数组和链表
1 结构体数组
一个结构体可以看作是和int,char,这些基本数据类型类似的自定义数据类型,那么需要我们保存多条具有相同类型的数据,首先想到的就是数组
![c630fba9893a4d232d307c5bae8c1f5c.png](https://i-blog.csdnimg.cn/blog_migrate/8b31726376b0fcc322f7f70c1c4efec7.jpeg)
#include<stdio.h>
int main(){
//定义结构体
struct student{
int num;
char* name;
char sex;
int age;
};
//结构体数据
struct student stu1={1,"张三",'m',18};
struct student stu2={2,"李四",'f',19};
struct student stu3={3,"王五",'m',20};
struct student stu4={4,"赵六",'f',21};
//结构体数组
struct student stus[4]={stu1,stu2,stu3,stu4};
//打印结果
printf("编号t姓名t性别t年龄n");
for(int i=0;i<4;i++){
printf("%dt%st%st%dn",stus[i].num,stus[i].name,stus[i].sex=='m'?"男":"女",stus[i].age);
}
return 0;
}
stus就是一个结构体数组,有struct student类型的数据构成,stus[i]找到数组当中的第i个结构体数据
![6d3542e2defb0ccfb51e3e842c885b77.png](https://i-blog.csdnimg.cn/blog_migrate/86d6bb1fedf0397445825352327dc5e4.png)
也可以直接建立结构体数组
#include<stdio.h>
int main(){
//直接定义结构体数组
struct student{
int num;
char* name;
char sex;
int age;
}stus[4]={{1,"张三",'m',18},{2,"李四",'f',19},{3,"王五",'m',20},{4,"赵六",'f',21}};
//打印结果
printf("编号t姓名t性别t年龄n");
for(int i=0;i<4;i++){
printf("%dt%st%st%dn",stus[i].num,stus[i].name,stus[i].sex=='m'?"男":"女",stus[i].age);
}
return 0;
}
结果和上面相同
![f1af3c7fdfab7735c079ab2f164f943c.png](https://i-blog.csdnimg.cn/blog_migrate/8e21c32103830ae778b630bce2858fb4.png)
2 链表
使用数组保存数据有一个问题,那就是在c语言当中,数组的长度是固定的,也就是说当我们创建好数组之后,再向数组当中添加新的元素会比较困难,所以我们还可以采用链表的方式来保存数据
具体的做法就是在结构体当中添加一个和结构体类型相同的指针,指向结构体保存的下一条数据
![0377ab3c34463d0a24ad3367cdf33a7e.png](https://i-blog.csdnimg.cn/blog_migrate/c031bcb09876953704b27fd1712b1b2a.jpeg)
我们找到一条结构体数据,都可以通过next指针找到下一条数据,这样我们的每条数据就像被一条无形的链条串到一起,当找到最后一条数据的时候可以把next设为NULL,这样我们就可以判断当前的数据是不是最后一条
#include<stdio.h>
int main(){
//定义结构体
struct student{
int num;
char* name;
char sex;
int age;
struct student * next;
};
//结构体数据
struct student stu1={1,"张三",'m',18,NULL};
struct student stu2={2,"李四",'f',19,NULL};
struct student stu3={3,"王五",'m',20,NULL};
struct student stu4={4,"赵六",'f',21,NULL};
//把数据串起来
stu1.next=&stu2;
stu2.next=&stu3;
stu3.next=&stu4;
//打印结果可以通过判断next是否为空来结束循环
struct student * p=&stu1; //定义一个指向第一个元素的指针
printf("编号t姓名t性别t年龄n");
while(p!=NULL){
printf("%dt%st%st%dn",p->num,p->name,p->sex=='m'?"男":"女",p->age);
p=p->next;//把指针移到下一个元素
}
return 0;
}
这里需要定义一个指针,指向链表的第一个元素,然后通过 p=p->next,把指针移动到第二个元素,以此类推,直到p指向最后一个元素为止
![f9c7557de5dddd1520ece2b41f06d4b1.png](https://i-blog.csdnimg.cn/blog_migrate/2f19b5d5ed56d3709dcbc7bc881deecd.png)
3 数组和链表的选择
数组的优点是每条数据都是在内存当中连续保存的,可以利用数组的索引快速的找到数据;数组的缺点就是,长度固定,添加或者移除数据会比较麻烦
链表的优点是可以通过把next指针指向新数据来向链表当中添加新纪录,移除数据也比较方便;链表的缺点就是数据在内存当中是不连续的,所以想要找到某条数据,没有办法直接通过索引获得,只能移动指针,越靠后的元素,指针移动的次数越多,查询的效率比较低
所以
- 当我们的数据改动少查询多的时候可以使用数组
- 当数据需要频繁的改动的时候,我们可以使用链表
数组和链表的具体操作(数据的增删改查),是数据结构的基本内容,我们之后再仔细讲