关于结构体和指针操作的学习记录
闲来无事,试着让AI出点C语言基础题来练手一下,
没想到我的底子太浅小问题就一团糟T^T
然后好不容易做完了一堆语法错误 狠狠补习
(澄清一下,曾经确实学了,但是忘了1000%)
问题
编写一个C程序,实现以下功能:
定义结构体Student,包含姓名(字符数组,长度20)和成绩(整数)。
实现函数Student* findMaxScore(Student* students, int n),在给定的学生数组中查找成绩最高的学生,
返回其指针(若多个同分,返回第一个)。
在main函数中初始化包含5个学生的数组,调用函数找到最高分学生,并输出其姓名和成绩。
要求:
使用结构体和指针操作。
数组需包含至少5个学生数据。
分析
本题需要了解结构体的定义,结构体指针的相关内容
定义结构体/联合体,枚举的拓展
普通模板是先定义一个结构体类型,再定义一个结构体变量
struct strStudent
{
char name[20];
unsigned int score;
};
struct strStudent Student;
此时我便出问题了,我写的是strStudent* findMaxScore(strStudent* students, int n)
提示报错,原因是结构体的struct
是类型前缀后面strStudent
是标签,两者在一起才是一个完整的类型名,如果用普通模板写,这个地方必须带上前缀!于是就变成了struct strStudent* findMaxScore(struct strStudent* students, int n)
这样一看...眼花缭乱的还麻烦的很,于是聪明人们都用另一种写法
typedef struct strStudent
{
char name[20];
unsigned int score;
}Student;
Student* findMaxScore(Student* students, int n);
在typedef的帮助下我们定义了一个别名Student
的结构体类型,同时省去了定义变量时的struct
。其实还有其他定义方法,但是第二种方法实为简便,不做展开。
除了结构体,枚举类型和联合体类型也必须和前缀一起使用,于是乎也可以使用typedef
typedef union AunionType
{
int a;
float b;
}AunionType;
AunionType UN1;
typedef enum Order //不常用
{
One,
Two,
Three
}Order;
Order num1;
函数实现
Student* findMaxScore(Student* students, int n)
中接收一个Student*
类型的指针(结构体数组的指针)和数组长度,返回了一个Student类型的结构体指针。因此函数实现中只需要遍历每一个结构体的分数,保存第一个最高分的结构体指针即可。
Student* findMaxScore(Student* students, int n)
{
Student* p; //创建一个结构体指针用于保存返回值
unsigned int goat = 0;
for(int i = 0 ; i<n ; ++i)
{
unsigned int temp = (students + i)->score;//传递分数
if(temp > goat)//保存第一个,不能取等
{
goat = temp;
p = &students[i];//取当前第一个最高分结构体的指针,存入p
}
}
return p;//遍历完毕,返回p
}
此处传递分数使用了(students + i)->score;
其实也可以用students[i].score
箭头操作符->
和点操作符.
区别是什么呢?
->
操作符作用于指针类型,通过成员地址的偏移量计算出需要的成员地址,解引用得到变量值。
相当于:
*(unsigned*)((char*)students + 20)
//20为地址偏移量,char类型在系统中偏移量为1
.
操作符作用于变量,所以需要[i]
(此操作编译器会自动根据i值偏移到对应变量的地址),如果对其取指针后可以看作上式来计算。
所以甚至可以写成&(students[i])->score
程序实现
#include "stdio.h"
typedef struct strStudent
{
char name[20];
unsigned int score;
}Student;
Student* findMaxScore(Student* students, int n)
{
Student* p;
unsigned int goat = 0;
for(int i = 0 ; i<n ; ++i)
{
unsigned int temp = (students + i)->score;
if(temp > goat)
{
goat = temp;
p = &students[i];
}
}
return p;
}
int main(void)
{
Student a[5] = { //初始化一个Student类型的数组
{"jake",11},
{"mike",10},
{"john",19},
{"aily",25},
{"jay",7}
};
printf("测试初始化效果:%s:%u\r\n",a[0].name,(&a[0])->score);
Student* stumax = findMaxScore(a,5);
printf("第一个最高分为%s:%u\r\n",(*stumax).name,stumax->score);
}
输出:
测试初始化效果:jake:11
第一个最高分为aily:25