C语言程序设计—结构体(Part Ⅰ)

C语言程序设计—结构体 的整理笔记,若有错误,欢迎指正。
C语言程序设计—结构体(Part Ⅱ)

C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体(structure)。


自己建立结构体类型
  • 声明一个结构体类型的一般形式为:
struct 结构体名
{成员表列};
  • 成员表列中的各个成员都应进行类型声明,即:类型名 成员名;
    例1:
struct student //student为结构体名
{
	int num; // 学号为整型
	char name[20]; //姓名为字符串
	float score; //成绩为实型
}; //注意最后有一个分号

程序分析:

  • 上面由程序设计者指定了一个新的结构体类型struct student(struct是声明结构体类型时所必须使用的关键字,不能省略),它向编译系统声明这是一个“结构体类型”,它包括num、name、score三个不同类型的子项。
  • 经过上面的指定,struct student就是一个在程序中可以使用的合法类型名,它和系统提供的标准类型(如int、char、float、double等)具有类似的作用,都可以用来定义变量的类型,只不过int等基本类型是系统已定义了的,而结构体类型是根据用户需要由程序设计者在程序中指定的。
  • !注意:结构体类型的名字是由一个关键字struct和结构名二者组合而成的(例如struct student)。结构体名是由用户指定的,又称“结构体标记”(structure tag)以区别于其他的结构体类型。上面的结构体声明中student就是结构体名(结构体标记)。
  • 大括号内是该结构体所包括的子项,称为结构体的成员(member)。上例中的num、name、score等都是成员。对各成员都应进行类型声明,“成员表列”(member list)也称为“域表"(field list),每一个成员是结构体中的一个域。成员名命名规则与变量名相同。

说明:

  • 结构体类型并不是只有一种,而是可以设计出许多种结构体类型,例如除了可以建立上面的struct student结构体类型外,还可以根据需要建立名为struct teacher、struct worker、struct date等结构体类型,各自包含不同的成员。
  • 成员可以是另一个结构体变量(就是在一个结构体内包含了另一个结构体作为其成员)。
    例2:
struct date //声明一个结构体类型struct date
{
	int month; //月
	int day; //日
	int year; //年
};

struct student //声明一个结构体类型struct student
{
	char sex; //性别为字符型
	int age; //年龄为整型
	struct date birthday; //生日是struct date类型
};

程序分析:

  • 先声明一个struct date类型,它代表“日期”,包括3个成员: month(月)、day(日)、year(年)。然后在声明struct student类型时,将成员birthday指定为struct date类型。已声明的类型struct date与其他类型(如int、char)一样可用来定义成员的类型。
    在这里插入图片描述

定义结构体类型变量

  • 以下三种方法都可以定义结构体变量
  1. 先声明结构体类型,再定义该类型的变量。
    例3:
struct student //student为结构体类型名
{
	int num; // 学号为整型
	char name[20]; //姓名为字符串
	float score; //成绩为实型
};
struct student student1,student2; //student1、student2为结构体变量名

在定义了结构体变量后,系统会为之分配内存单元。根据结构体类型中包含的成员情况,在Visual Studio 2019中,student1和student2在内存中占28个字节。(int:4 + char:1×20 + float:4)
这种方式是声明类型和定义变量分离,在声明类型后可以随时定义变量,比较灵活。

  1. 在声明类型的同时定义变量
    其一般形式为:
struct 结构体名
{
成员表列
}变量名表列;

例4:

struct student //声明一个结构体类型struct student
{
	int num; // 学号为整型
	char name[20]; //姓名为字符串
	float score; //成绩为实型
}student1,student2; //student1、student2为结构体变量名
  • 声明类型和定义变量放在一起进行,能直接看到结构体的结构,比较直观,在写小程序时用此方式比较方便,但写大程序时,往往要求对类型的声明和变量的定义分别在不同的地方,以使程序结构清晰,便于维护,所以不宜用这种方式。
  • 声明结构体类型仅仅是声明了一个类型,系统并不为之分配内存,就如同系统不会为类型int分配内存一样。只有当使用这个类型定义了变量时,系统才会为变量分配内存。所以在声明结构体类型的时候,不可以对里面的变量进行初始化。
  1. 不指定类型名而直接定义结构体类型变量
    其一般形式为:
struct
{
成员表列
}变量名表列;

例5:

struct
{
	int num; // 学号为整型
	char name[20]; //姓名为字符串
	float score; //成绩为实型
}student1,student2; //student1、student2为结构体变量名
  • 指定了一个无名的结构体类型,它没有名字(不出现结构体名)。显然不能再以此结构体类型去定义其他变量,这种方式用得不多。

说明:

  • 结构体类型与结构体变量是不同的概念。只能对变量赋值、存取或运算,而不能对类型赋值、存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。
  • 结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象。例如,程序中可以另外定义一个变量num,它与struct student中的num是两回事,互不于扰。
  • 对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。

结构体变量的初始化和引用
  • 在定义结构体变量时,可以对它初始化,然后可以引用这个变量。

例:把一个学生的信息放在一个结构体变量中,然后输出这个学生的信息。

#include<stdio.h>
int main()
{
	struct student //声明结构体类型 struct student
	{
		int num;
		char name[20];
		char sex;
		char addr[20];
	}student1= {10101, "Li Lin", 'M',"123 Beijing Road"}; //对变量student1初始化

printf("NO.:%d\nname:%s\nsex:%c\naddress:%s\n", student1.num, student1.name, student1.sex, student1.addr);
return 0;
}
//输出结果为:
NO.:10101
name:Li Lin
sex:M
address:123 Beijing Road

程序分析:

  • 程序中指定了一个结构体名为student的结构体类型,有4个成员(num、name、sex、addr)。
  • 在声明类型的同时定义了结构体变量student1,这个变量具有struct student类型所规定的结构。

引用结构体变量应遵守以下规则:

  1. 可以引用结构体变量中成员的值,引用方式为:结构体变量名,成员名
    例如,student1.num表示student1变量中的num成员,即student1的num(学号)项,在程序中可以对变量的成员赋值。
    例:student1.num=10010; “.”是成员运算符,它在所有的运算符中优先级最高。

    !注意:不能通过结构体变量名来得到结构体变量中所有成员的值,只能对结构体变量中的各个成员分别进行输入和输出。
    例:(错误❌)printf("%s\ n", student1); //企图用结构体变量名输出所有成员的值

  2. 如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员。只能对最低级的成员进行赋值或存取以及运算。

#include<stdio.h>
int main()
{
	struct date //声明一个结构体类型struct date
	{
		int month; //月
		int day; //日
		int year; //年
	};

	struct student //声明一个结构体类型struct student
	{
		char sex; //性别为字符型
		int age; //年龄为整型
		struct date birthday; //生日是struct date类型
	}student1 = { 'M' , 21, {10,31,1999} }; //对变量student1初始化
	printf("sex:%c\nage:%d\nmonth:%d/n", student1.num, student1.birthday.month);
	return 0;
}
//输出结果为:
sex:M
age:21
month:10

程序分析:

  • 如果在结构体中包含另一个结构体struct date类型的变量birthday,则引用成员的方式为:student1.birthday.month;
  • 不能用student1.birthday来访问student1变量中的成员birthday,因为birthday本
    身是一个结构体变量。
  1. 对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。
    例4中:
student2.score=studentl.score; //(赋值运算)
sum=student1.score+student2.score; //(加法运算)
student1.age++; //(自加运算)
  • 由于“."运算符的优先级最高,因此 student.age++是对student.age进行自加运算,而不是先对age进行自加运算。
  1. 同类的结构体变量可以互相赋值,例: student1=student2; //假设student1和student2已定义为同类型的结构体变量
    例5:
#include<stdio.h>
int main()
{
	struct date //声明一个结构体类型struct date
	{
		int month; //月
		int day; //日
		int year; //年
	};

	struct student //声明一个结构体类型struct student
	{
		int num; // 学号为整型
		char name[20]; //姓名为字符串
		float score; //成绩为浮点型
		struct date birthday; //生日是struct date类型
	}student1 = { 10101, "Li Lin", 71.6, {10,31,1999} }, student2 = { 20202, "Xi Xin",82.4, {12,25,1998} };
	printf("NO.:%d\nname:%s\nscore:%.2f\nmonth:%d\n", student1.num, student1.name, student1.score, student1.birthday.month);
	printf("\n");

	student1 = student2;
	printf("NO.:%d\nname:%s\nscore:%.2f\nmonth:%d\n", student1.num, student1.name, student1.score, student1.birthday.month);
	return 0;
}
//输出结果为:
NO.:10101
name:Li Lin
score:71.60
month:10

NO.:20202
name:Xi Xin
score:82.40
month:12

程序分析:

  • 由于student2是一个“组合项”,内放有关联的一组数据,因此,同类的结构体变量进行赋值时,全部成员的值会随之改变。例5中将结构体变量student2赋值给student1,从输出结果来看,赋值后,student1中所有成员的值都发生了变化。

例6:输出两个学生的学号、姓名和成绩,输出成绩较高的学生的学号、姓名和成绩。

#include<stdio.h>
int main()
{
	struct student
	{
		int num;
		char name[20];
		float score;
	}student1, student2;
	scanf("%d%s%f", &student1.num, student1.name, &student1.score);
	scanf("%d%s%f", &student2.num, student2.name, &student2.score);
	printf("The higher score is:\n");
	if (student1.score > student2.score)
		printf("%d %s %.2f\n", student1.num, student1.name, student1.score);
	else if (student1.score < student2.score)
		printf("%d %s %.2f\n", student2.num, student2.name, student2.score);
	else
	{
		printf("%d %s %.2f\n", student1.num, student1.name, student1.score);
		printf("%d %s %.2f\n", student2.num, student2.name, student2.score);
	}
	return 0;
}

//输入:
10101 Li 71.6
20202 Xi 82.4

//输出结果为:
The higher score is:
20202 Xi 82.40

程序分析:

  • 用scanf()函数输入结构体变量时,必须分别输入它们的成员的值,不能在scanf函数中使用结构体变量名一次性输入全部成员的值。
  • !注意:在scanf函数中,成员student.num和student.score的前面都有地址符&,而在student1.name前面没有&。这是因为name是数组名,本身就代表地址,故不能画蛇添足地再加一个&。
  • 从这里可以看到利用结构体变量的好处:由于student是ー个“组合项”,内放有关联的一组数据,student.score是属于student变量的一部分,因此如果确定了student1.core是成绩较高的,从而输出student的全部信息是轻而易举的。因为它们本来是互相关联,绑定在一起的,如果用普通变量是难以方便地实现这一目的的。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值