关于结构体和指针操作的学习记录

闲来无事,试着让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
posted @ 2025-04-11 02:35  ConVal  阅读(23)  评论(0)    收藏  举报