C语言基础(四)——结构体

引子

假设我们想统计学生的成绩,每一个学生的统计中都要包含以下内容:学生姓名、学号、成绩。我们已经知道,可以使用字符数组(char)表示姓名,整型(int)表示年龄,长整型(long int)表示学号,浮点型(float)表示成绩。这里每一位学生的数据都是一个整体。正因如此,我们可以使用结构体来表示它们。

  • A:为什么要使用结构体?
  • B:使用结构体的好处就是将不同的数据类型整合在一起,方便程序员在后续进行修改和增添。

结构体基础

结构体声明和初始化

在C语言中,结构体通过关键字 struct声明 ,struct的全称为structured data type(结构化数据类型)。

结构体的声明

在程序中,我们声明结构体的位置一般在函数外。如果把结构体的声明放在某一个函数内,比如主函数内,那么结构体就只能在主函数内应用。

struct Student 
{
    char name[50];
    int age;
    long int StudentID;
    float score;    
}student1;

上面的代码中,struct Student是我们声明的数据类型,大括号内的代码块声明数据类型。student1是对应于stuct Studnt的变量名,每个结构化数据类型都可以对应多个不同的变量。

使用typedef为结构命名

在创建结构化数据类型时,我们每一次都不得不使用struct关键字。为了简化这种表述,可以在struct之前使用typedef为结构起一个别名。

typedef struct STUDENT//这里的typedef表示为结构起一个新的别名
{
    char name[50];
    int age;
    long int StudentID;
    float score;    
}student;//stedent将成为struct STUDENT的别名

结构体初始化

在声明结构体之后,我们可以在函数中直接初始化结构体:
初始化结构体

"."运算符

在C语言中,我们可以使用“点运算符”(.)来访问结构体中的元素。

访问结构体中的元素

我们可以通过点操作符(.)访问结构体zhangsan中 的某一个元素:

#include <stdio.h>
struct Student {
	char name[50];
	int age;
	long int StudentID;
	float score;

};
int main()
{
	struct Student zhangsan = { "zhangsan",18,20230001,100};
	printf("%f\n",zhangsan.score);
	return 0}

更改结构体中的元素

如果我们想单独更改结构体中的某一个信息,我们不必要再次初始化整个结构体,可以直接针对某个元素更改数据。

#include <stdio.h>
struct Student {
	char name[50];
	int age;
	long int StudentID;
	float score;
};
int main()
{
	struct Student zhangsan = { "zhangsan",18,20230001,100};
	printf("%f\n",zhangsan.score);
	zhangsan.score=61;
	printf("%f\n", zhangsan.score);
	struct Student lisi = { "lisi",18,20230002,100 };
	return 0;
}

下面是程序运行结果:
运行结果

结构体数组

  • A:假如一个班级有四十个人,我们难道只能像上面一样,逐一初始化结构体吗?
  • B:那也太麻烦了,显然是不行的。
  • A:那怎么办?
  • B:我们可以使用结构体数组简化步骤。

下面是一个例子:

struct Student {
    char name[50];
    int age;
    long int StudentID;
    float score;
    
}class1[41];

直接初始化

结构体数组可以使用下面的代码在程序中直接进行初始化:

struct Student class2[2] = {
    {"Alice", 30, 5.5},
    {"Bob", 25, 5.8}
};

从外部导入数据

如果想从键盘或文件中导入数据,我们可以使用循环来声明数组(下面的代码使用的是标准输入):

#include <stdio.h>
struct Student {
	char name[50];
	int age;
	long int StudentID;
	float score;

}student[41];
int main()
{
	for (int i = 0; i <= 40; i++)
	{
		scanf("%s%d%ld%f", student[i].name, student[i].age, student[i].StudentID, student[i].score);
	}
	return 0;
}

嵌套结构体

结构体可以嵌套使用,即一个结构体成为了另一个结构体的元素。这种嵌套的结构体方便了我们模拟复杂的数据结构。

struct Date {
    int day;
    int month;
    int year;
};

struct Student {
    char name[50];
    int age;
    long int StudentID;
    float score;
    struct Date birthday;//这里是嵌套的结构体
}

结构体的深入理解

存储器中的结构体

  1. 当我们声明新结构化变量时,实际上是告诉计算机一个模板,告诉计算机这个变量长什么样。
  2. 当我们初始化新的结构体变量时,计算机会在存储器中按照模板创建一片足够大的空间。当然,同一个结构体的变量在存储器中的地址是相邻的。
  3. 当我们把一个结构变量赋值给另一个结构变量时,计算机会在存储器中创建另一片空间,大小和原来完全相同,然后把每一个字段复制过去。
    在这里插入图片描述

从第3点可知,如果我们想要在某一个函数中调用结构体,结构体在实参与形参的传输过程中,还是会出现那个老问题——函数中参数地址和原地址不同。

为了解决这个问题,我们必须调用结构指针。

结构指针

结构体和数组的区别

结构体与数组不一样,它的地址虽然相邻,但是却不能通过编号、加1和减1等方式进行访问。

  • A:那如果想用指针访问结构体那应该怎么办?
  • B:我们可以使用.操作符访问结构体中的元素,还可以使用->符号访问结构体。

结构指针的应用

struct Student *ptr = &zhangsan;
printf("%s is %d years old.\n", ptr->name, ptr->age);
printf("%s is %d years old.\n", (*ptr).name, (*ptr).age);
  • A:为什么要使用(*ptr)->name而不是*ptr->name
  • B:这里的*ptr->name*(ptr->name)相同,如果这里的ptr是指针变量,那么从第一步开始就无法完成。

总结:

这篇文章中主要讲了结构体的有关知识点,可以说是比较详细的,可是在结构体应用方面是比较粗浅的,结构体还有更多的深奥的秘密等待着我们的学习与探寻。

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mottte

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值