C语言结构体(数据结构中的应用)
在学习数据结构的时候,才发觉自己C语言已经忘得差不多了,连结构体都不太晓得怎么写了,特来补习。
结构体”这个词是根据英文单词 structure 译出的。
所以结构体的关键字是 struct 。
结构体的定义
在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。
结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。
结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问。
(来自百度)
结构体是将不同类型的数据按照一定的功能需求进行整体封装,封装的数据类型与大小均可以由用户指定。
“结构体名”的命名规范是全部使用大写字母
结构体的声明
结构体的声明形式,一般为:
struct 结构体名{
成员列表
};
注意:分号不要丢。
声明结构体即声明了一种用户自定义数据类型,在平时编写代码时一般用的多的是使用 typedef 直接定义其类型,如下图所示。
typedef struct{
char a【10】;//种类
int age;//年龄
double gao;//高度
}tree;
//注意分号的位置
int main(int ac,char **P)
{
tree yinxing;//定义一个tree 类型的变量yinxing(银杏)
return 0;
定义结构体变量后即分配了相应的变量内存,一般需要进行初始化。在读写结构体变量的时候需要"."运算符,英文名称dot operator。
strcpy (yinxing.name,"银杏”);
/*strcpy() 函数用于对字符串进行复制(拷贝)
头文件:string.h
此处把银杏复制到yinxing.name中去*/
yinxing.age = 100;
yinxing.gao = 100;
声明结构体类型仅仅是声明了一个类型**,系统并不为之分配内存**,就如同系统不会为类型 int 分配内存一样。只有当使用这个类型定义了变量时,系统才会为变量分配内存。所以在声明结构体类型的时候,不可以对里面的变量进行初始化。
结构体的定义如下所示,struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。
struct tag {
member-list
} variable-list ;
在一般情况下,tag、member-list、variable-list这3部分至少要出现2个。以下为示例:
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct {
int a;
char b;
double c;
} s1;
//同上声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE{
int a;
char b;
double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
//也可以用typedef创建新类型
typedef struct{
int a;
char b;
double c;
} Simple2;
//可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
在上面的声明中,第一个和第二声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令t3=&s1,则是非法的。
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。
//此结构体的声明包含了其他的结构体
struct COMPLEX{
char string[100];
struct SIMPLE a;
};
//此结构体的声明包含了指向自己类型的指针
struct NODE{
char string[100];
struct NODE *next_node;
};
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明,如下所示: [3]
struct B;
//对结构体B进行不完整声明
//结构体A中包含指向结构体B的指针
struct A{
struct B *partner;
//other members;
};
//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B{
struct A *partner;
//other members;
};
定义结构体变量
方法一:
先声明“结构体类型”,再定义“结构体类型变量”
一般我们都是在所有函数前面声明结构体类型,就同我们希望在所有函数中都可以使用int来定义变量一样。
我们都是在所有函数前对结构体类型进行声明,然后在某个函数中再定义局部的结构体类型变量。
比如在所有函数前定义了一个结构体类型 struct STUDENT,那么就可以在所有函数中使用它来定义局部的结构体类型变量。如:
struct STUDENT stud1, stud2;
stud1 和 stud2 就是我们定义的结构体变量名。定义了结构体变量之后,系统就会为之分配内存单元。
如果 stud1 和 stud2 是在某个函数中定义的局部变量,那么就只能在该函数中使用。在其他函数中可以定义重名的结构体变量而不会相互产生影响。
方法二:
在声明结构体类型的同时定义结构体变量。
如果你在所有函数前声明结构体类型,那么定义的变量就是全局变量;
而如果要定义局部变量,那么就只能在某个函数中对结构体类型进行声明,从而导致只能在这个函数中使用这个类型。
那么声明的时候是如何定义变量的呢?我们知道,声明的时候最后有个一分号,就在那个分号前写上你想定义的变量名就行了,如:
struct STUDENT
{
char name[20];
int num;
char sex;
int age;
float score;
char addr[30];
}stud;
注意:分号的位置。
这样就声明了一个结构体类型,并用这个类型定义了一个结构体变量 stud。这个变量是一个全局变量。
“结构体类型”的声明和使用与函数的定义和使用有所不同,函数的定义可以放在调用处的后面,只需在前面声明一下即可。
但是**“结构体类型”的声明必须放在“使用结构体类型定义结构体变量”的前面。**
结构体变量的运算
结构体变量不能相加、不能相减,也不能相互乘除,但结构体变量可以相互赋值。也就是说,可以将一个结构体变量赋给另一个结构体变量。但前提是这两个结构体变量的结构体类型必须相同。
结构体变量的引用
可以引用“结构体变量成员”的地址,也可以引用“结构体变量”的地址。如“&student1.num”和“&student1”,前者表示 student1.num 这个成员在内存中的首地址,后者表示结构体变量 student1 在内存中的首地址。‘
结构体变量的引用方式决定了:
(1)“结构体变量名”可以与“结构体成员名”同名。
(2)“结构体变量名”可以与“结构体名”同名。
(3)“两个结构体类型定义的结构体变量中的成员可以同名”。就比如定义了一个结构体类型用于存放学生的信息,里面有成员“char name[20];”,那么如果又定义了一个结构体类型用于存放老师的信息,那么里面也可以有成员“char name[20];”。
因为结构体成员在引用时,必须要使用“结构体变量名.成员名”****的方式来引用,通过引用就可以区分它们,所以不会产生冲突,因此可以同名!
结构体变量的初始化
方法一:定义的时候初始化
# include <stdio.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20];
int num;
struct AGE birthday;
float score;
};
int main(void)
{
struct STUDENT student1 = {"小明", 1207041, {1989, 3, 29}, 100};
return 0;
}
注意,同字符、字符数组的初始化一样,如果是字符那么就用单引号括起来,如果是字符串就用双引号括起来。
方法二:定义之后对结构体变量进行初始化
# include <stdio.h>
# include <string.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20]; //姓名
int num; //学号
struct AGE birthday; /*用struct AGE结构体类型定义结构体变量birthday, 即生日*/
float score; //分数
};
int main(void)
{
struct STUDENT student1; /*用struct STUDENT结构体类型定义结构体变量student1*/
strcpy(student1.name, "小明"); //不能写成&student1
student1.num = 1207041;
student1.birthday.year = 1989;
student1.birthday.month = 3;
student1.birthday.day = 29;
student1.score = 100;
printf("name : %s\n", student1.name); //不能写成&student1
printf("num : %d\n", student1.num);
printf("birthday : %d-%d-%d\n", student1.birthday.year, student1.birthday.month, student1.birthday.day);
printf("score : %.1f\n", student1.score);
return 0;
}