C语言的高级东东——结构体

假如有一个函数需要学生的信息:姓名、年龄、身高、体重、爱好、特长、学校名称:

void info(const char* name,int age,int height,int weight,const char *hobby,const char* good,const char* school){
}

那么,你每次调用这个函数时就要传7个参数,真是又长又臭啊!有没有办法将这些参数打包起来呢?有,那就是用结构体(struct,struct是structured data type结构化数据类型的缩写)。利用结构体就可以把不同类型的数据写在一起,封装成一个新的大数据类型。如上面学生信息:

struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
};

小知识:const 是用来保存你不想被修改的值
结构体与数组相似,除了以下两点:

  1. 结构体的大小固定;
  2. 结构体中的数据都有名字。

定义好结构体后,如何用它来创建数据呢?其实,和新建数组相似,只需要保证每条数据按照它们在结构体中定义的顺序出现即可,如:

struct student stu = {"Tom",28,170,64,"reading","program","ZhungSun University"};

也可以指定字段赋值,如:

struct student stu1 = {.name="Tom",.age=28,.height=170,64,"reading","program","ZhungSun University"};注意这里的数据类型是struct student:

这样一来,info函数要做一些调整,变成:

void info(struct student stu){

}

调用的时候只要把新自定义的数据传给它即可,就不用传递一大批零散的数据了,如:

info(stu);

接下来的问题就是在info函数中如何读取结构体中保存的数据呢?答案就是使用"."点运算符读取结构体的字段值。虽然结构体与数组相似,但不可以使用下标的形式读取,只能按名字访问

stu.name

下面给出完整的代码:
student.h

struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
};

void info(struct student stu);

student.c

#include <stdio.h>
#include "student.h"

void info(struct student stu){
printf("Hello,I am %s,%d years old.I come from %s\n",stu.name,stu.age,stu.school);
}

test.c

#include <stdio.h>
#include "student.h"
int main(){
        struct student stu = {"Tom",28,170,64,"reading","program","ZhungSun University"};
        info(stu);
        return 0;
}

编译并运行:

~$ gcc student.c test.c -o stu
~$ ./stu
Hello,I am Tom,28 years old.I come from ZhungSun University

在定义结构体时,计算机不会在内存中创建任何东西,只是一个模板,告诉它你所希望的数据类型是哪一些,只有在定义结构体变量时,计算机才会在内存中为结构体的实例创建空间。

当把一个结构体变量赋值给另一个结构体变量时,计算机会创建一个全新的结构体副本,也就是说计算机需要再分配一块存储空间,大小和原来一样,然后把每个字段都复制过去,如:

strcut student stu2 = stu;

结构体是可以嵌套的,就是结构体里的数据类型可以是结构体类型,如:

struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
};
struct classone{
        const char *className;
        struct student *stu;  //结构体类型
        //结构体类型
        struct group{
                const char *name;
                int count;
        } grp;
};

我们再给出一个运行实例来:
student.h

struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
};
struct classone{
        const char *className;
        struct student *stu;
        struct group{
                const char *name;
                int count;
        } grp;
};
void info(struct classone clas);

student.c

#include <stdio.h>
#include "student.h"

void info(struct classone clas){
printf("Hello,I am %s,%d years old.I come from %s\n,I am group %s\n,There are %d students\n",clas.stu[0].name,clas.stu[0].age,clas.stu[0].school,clas.grp.name,clas.grp.count);
}

test.c

#include <stdio.h>
#include "student.h"
int main(){
        struct student stu1 = {"Tom",28,170,64,"reading","program","ZhungSun University"};
        struct student stu2 = {"Lucy",28,170,64,"reading","program","ZhungSun University"};
        struct student stus[] = {stu1,stu2};
        struct classone class1 = {"class A",stus,{"group 1",12}};
        info(class1);
        return 0;
}

编译并运行:

~/Desktop/MyC$ gcc student.c test.c -o clas
~/Desktop/MyC$ ./clas
Hello,I am Tom,28 years old.I come from ZhungSun University
,I am group group 1
,There are 12 students

从上面的实例,我们可以清楚地知道如何读取嵌套的结构体的字段值了。

我们还可以用typedef来为结构体起一个别名,并使用别名定义结构体变量。如:

typedef struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
}student;
student stu1 = {"Tom",28,170,64,"reading","program","ZhungSun University"};

还可以定义匿名结构体,即没有名字的结构体,如:

typedef struct {
		const char *name;
		int age;
} man;

上面的结构体虽然没有名称,但是有别名,很多时候,有了别名就不需要结构体名了。

把数据放在结构体中传递除了可以将整批数据打包传递,还有一个好处就是在修改结构体的内容时,如在结构体多增加一个字段,不必修改使用它的函数。不但让代码更好阅读,还可以更好地应对变化 。值得注意的一点是结构体变量是结构本身的名字,而不是像数组变量那样是一个指针,另外在结构体里不能有方法。在C语言中,所有赋值都会复制数据,如果你想复制数据的引用,那应该赋指针,为什么要用指针,因为只有把变量在存储器中的位置告诉函数,函数才能更新保存在哪里的数据 ,才能更新变量 。
看看传递结构体指针的代码:
student.h

typedef struct student{
        const char *name;
        int age;
        int height;
        int weight;
        const char *hobby;
        const char *good;
        const char *school;
}student;
struct classone{
        const char *className;
        student *stu;
        struct group{
                const char *name;
                int count;
        } grp;
};
void info(struct classone * clas); //形参是指针类型

student.c

#include <stdio.h>
#include "student.h"

void info(struct classone *clas){
printf("Hello,I am %s,%d years old.I come from %s\n,I am group %s\n,There are %d students\n",clas->stu[0].name,clas->stu[0].age,clas->stu[0].school,clas->grp.name,clas->grp.count);
}


test.c


#include <stdio.h>
#include "student.h"
int main(){

        struct student stu1 = {"Tom",28,170,64,"reading","program","ZhungSun University"};
        struct student stu2 = {"Lucy",28,170,64,"reading","program","ZhungSun University"};
        struct student stus[] = {stu1,stu2};
        struct classone class1 = {"class A",stus,{"group 1",12}};
        info(&class1); //传递结构体变量的地址
        return 0;

}

编译并运行:

    ~/Desktop/MyC$ gcc student.c test.c -o clas2
    ~/Desktop/MyC$ ./clas2
    Hello,I am Tom,28 years old.I come from ZhungSun University
    ,I am group group 1
    ,There are 12 students

如上就可以更新结构体了,如果想让函数更新结构体变量,就不能把结构体作为参数传递,因为这样做仅仅是将数据的副本复制给了函数,取而待之,你应该传递结构体的地址。

猜你喜欢

转载自blog.csdn.net/weixin_40763897/article/details/87257515