上次我们讲解了结构体,这里还有高级应用就是结构体数组(集合的集合)
(这里提醒一句,想要在北京参加NCRE考试的朋友们今天开始报名了)
定义
还是拿上回那个学生数据的结构体
typedef struct {
int year;
int month;
int day;
} Date;
typedef struct {
int num;
char name[20];
char sex;
Date birth;
float score;
} Student;
Student S[10]; //可以存放10个学生数据
然后就是循环操作录入输出,这一块优点就是好理解,集合嘛,大家或多或少都了解
数据结构的一大功能就是能够把无序的、海量的数据有条理的分类储存从而方便修改、加工输出,可以说学好数据结构对我们的生活都有帮助,帮助我们把生活有序化(比如把各种东西分类存放在箱子里,程序员爱穿格子衫也是对这种有序的规则热爱的体现)
接下来操作就和数组没什么区别了,唯一不同就是这个数组一个元素里面可以存放多个东西
可以看出来很有条理与结构,这也是数据结构最终目标,因为有了条理与结构就可以把现实生活中各种东西数字化然后在n维空间变成各种向量再交给计算机(机器)重复单一操作,没错这就是人工智能大模型底层逻辑(线性代数实际应用)
遍历
#include <stdio.h>
#include <string.h>
typedef struct date {
int year;
int month;
int day;
} Date;
typedef struct {
int num;
char name[20];
char sex;
Date birth;
float score;
} Student;
// 函数声明
void InputStudentInfo(Student *s);
void OutputStudentInfo(const Student *s);
int main() {
Student S[10]; // 假设有一个学生数组
// 输入学生信息
for (int i = 0; i < 10; ++i) {
printf("Enter information for student %d:\n", i + 1);
InputStudentInfo(&S[i]);
}
// 输出学生信息
for (int i = 0; i < 10; ++i) {
printf("Information for student %d:\n", i + 1);
OutputStudentInfo(&S[i]);
}
return 0;
}
// 输入学生信息的函数实现
void InputStudentInfo(Student *s) {
if (s != NULL) {
printf("Enter student number: ");
scanf("%d", &s->num);
printf("Enter student name: ");
scanf("%s", s->name); // 注意:这里假设输入的名字不会超过19个字符,以避免缓冲区溢出
printf("Enter student sex (M/F): ");
scanf(" %c", &s->sex); // 注意:在%c前加一个空格,以忽略前面的换行符
printf("Enter student birth (year month day): ");
scanf("%d %d %d", &s->birth.year, &s->birth.month, &s->birth.day);
printf("Enter student score: ");
scanf("%f", &s->score);
}
}
// 输出学生信息的函数实现
void OutputStudentInfo(const Student *s) {
if (s != NULL) {
printf("Student number: %d\n", s->num);
printf("Student name: %s\n", s->name);
printf("Student sex: %c\n", s->sex);
printf("Student birth: %d-%02d-%02d\n", s->birth.year, s->birth.month, s->birth.day);
printf("Student score: %.2f\n", s->score);
}
}
语法注意
有没有发现一个不同?
之前我们都是
&s1.num
&s1.birth.year
但是今天对于数组来说发生变化
&s->num
&s->birth.year
看来有必要说一说 -> 和 . 的区别
. 是针对具体的,用于直接访问结构体变量的成员
比如上次的s1就是一个具体的实际的(不是一个数组)Student变量,如果上面的例子想用点就是具体的(数组中一个具体元素如s[0]),如果想要用 . 就应如下这么写
#include <stdio.h>
typedef struct {
int year;
int month;
int day;
} Date;
typedef struct {
int num;
char name[20];
char sex;
Date birth;
float score;
} Student;
// 函数声明
void InputStudentInfo(Student *s, int index);
void OutputStudentInfo(const Student *s, int index);
int main() {
Student S[10]; // 假设我们有一个最多包含10个学生的数组
// 输入学生信息
for (int i = 0; i < 10; ++i) {
InputStudentInfo(S, i);
}
// 输出学生信息
for (int i = 0; i < 10; ++i) {
OutputStudentInfo(S, i);
}
return 0;
}
// 输入学生信息的函数
void InputStudentInfo(Student *s, int index) {
printf("Enter information for student %d:\n", index + 1);
printf("Number: ");
scanf("%d", &s[index].num);
printf("Name: ");
scanf("%s", s[index].name); // 注意:这里没有考虑字符串长度限制,可能会引起缓冲区溢出
printf("Sex (M/F): ");
scanf(" %c", &s[index].sex); // 注意:前面的空格用于消耗前一个输入后的换行符
printf("Birth (year month day): ");
scanf("%d %d %d", &s[index].birth.year, &s[index].birth.month, &s[index].birth.day);
printf("Score: ");
scanf("%f", &s[index].score);
}
// 输出学生信息的函数
void OutputStudentInfo(const Student *s, int index) {
printf("\nInformation for student %d:\n", index + 1);
printf("Number: %d\n", s[index].num);
printf("Name: %s\n", s[index].name);
printf("Sex: %c\n", s[index].sex);
printf("Birth: %d-%02d-%02d\n", s[index].birth.year, s[index].birth.month, s[index].birth.day);
printf("Score: %.2f\n", s[index].score);
}
->是指向操作,用于通过结构体指针访问结构体的成员,是用在抽象的指针上的
上文中数组s就是一个指针不是具体的,s->num
是通过结构体指针 s
访问 num
成员的方式,在这种情况下,&s->num
表示取 num
成员的地址,这时候就应该用箭头
但是注意嵌套的Birth是个Date类型结构体,是个具体的,所以是
&s->birth.year
个人建议
如果是简单操作,可以用具体的那种办法操作数组,毕竟简单直白
但是复杂任务还是推荐底下那个针对指针的,这块就是链表用的,我没法规定一个数组(要不链表又成数组了) ,每一个链表部分都是抽象的不是具体的(假如p是一个链表结构体变量,链表可没用过p[i]这么表述,因此 . 的用法完全用不了)
给大伙来点乐子保持对C语言的热情
这几天颂乐人偶(还在go)放出了新的PV,其中睦对祥子说过一句及其人机的话
祥 移动(轻推w移动)
我们就以此为切入点写个关于动漫人物的结构体然后定义一下
#include<stdio.h>
#include<string.h>
#define saki TogawaSakiko
//定义saki就是大祥老师全名
typedef struct date
{
int year;
int month;
int day;
}Date;
typedef struct
{
char name[20];
char sex;
struct date birth;
float money; //日常迫害大祥
char hobby[20];
char story[100];
......
}Character;
void move(Character a);
int main()
{
Character saki; //人物大祥
move(saki);
return 0;
}
void move(Character a) //move函数
{
......
}
很抽象是不是,但是确实是实际应用(实际写游戏还真是这样),编程其实另一层意思就是把现实世界的东西变成一条一条的数据(人工智能领域有个工作就是整理生活中的事物变成电脑数据喂给ai)。
U3d也干了
U3d可以这么写程序
typedef struct {
float x, y; // 位置坐标
int health; // 生命值
int attack; // 攻击力
// 其他属性
} GameObject;
然后就是接入接口啊什么的让u3d能读懂这一块c语言,就需要琢磨了
总结
1、学习了结构体数组
2、强调了 . 和 -> 的区别以及具体使用方法
3、整活激发热情
4、解开了数据结构目标与本质--把日常生活中各种东西数据化方便计算机处理
以上均是本人理解,如有不对欢迎各位大佬评论区指出~