任务描述
上一任务我们学了结构体的声明,以及结构体变量的定义和使用,已经对结构体有了初步的了解和认识,本任务我们将会继续学习结构体相关的高级知识,包括结构体数组、结构体指针,学完之后我们就满足结构体在我们的程序中使用了。
学习目标
掌握结构体数组。
掌握结构体指针。
掌握结构体的typedef的使用。
相关知识
1.结构体数组引入
一个结构体变量可以存放一个学生的一组信息,可是如果有 10 个学生呢?难道要定义 10 个结构体变量吗?难道上面的程序要复制和粘贴 10 次吗?很明显不可能,这时就要使用数组。结构体中也有数组,称为结构体数组。
2.结构体数组的定义
结构体数组是其元素都是具有相同结构体变量。同一般数组一样,结构体数组也必须先定义或说明,才能引用。结构体数组定义的一般格式如下:
struct结构体名 结构体数组名[元素个数];
其中“struct结构体名”是已定义过的结构体类型。存储类型是结构体数组的存储类型。
例如
struct STUDENT student[5];
这就定义了一个结构体数组,共有 5 个元素,每个元素都是一个结构体变量,当然STUDENT是我们在使用结构体数组之前必须先定义的,如下。
struct STUDENT {
char name[20];
int age;
char sex;
char num[20];
};
3.结构体数组的初始化
结构体数组也是可以直接出初始化的。结构体数组的初始化与前面讲的数值型数组的初始化是一样的,数值型数组初始化的方法和需要注意的问题在结构体数组的初始化中同样适用,因为不管是数值型数组还是结构体数组都是数组,例如:
struct STUDENT stu[5] = {
{"黄明杰", 18,'F',"Z1207031"},
{"王明明", 22, 'F',"Z1207035"},
{"李志华", 20, 'F',"Z1207022"},
{"江海鹏", 21, 'F',"Z1207015"},
{"任志鹏", 24, 'F',"Z1207024"}
};
在初始化数组的时候,数组元素的成员变量的赋值要与之定义的成员变量一一对应。
4.结构体的引用
结构体数组的引用是指对结构体数组元素的引用,由于每个结构体数组元素都是一个结构体变量,因此,结构体数组元素的引用方式与结构体变量类似,其语法格式如下所示:
数组元素名称.成员名;
为了帮助大家更好地掌握结构体数组初始化和引用的使用,接下来通过一个案例来输出结构体变量中所有成员的值。
实例10- 3 输出结构体变量中所有成员的值。
# include
struct STUDENT {
char name[20];
int age;
char sex;
char num[20];
}
;
int main() {
struct STUDENT stu[5] = { {
"黄明杰",18,'F', "Z1207031"
}
, {
"王明明", 22, 'F', "Z1207035"
}
, {
"李志华", 20, 'F', "Z1207022"
}
, {
"江海鹏", 21, 'F', "Z1207015"
}
, {
"任志鹏", 24, 'F', "Z1207024"
}
}
;
int i=0;
printf("学生信息如下\n");
for (i=0; i<5; i++) {
printf("学生姓名:%s 学生年龄:%d 学生性别:%c 学生学号:%s\n", stu[i].name, stu[i].age, stu[i].sex, stu[i].num);
}
getchar();
return 0;
}
运行结果 如图 10-9所示。
图10- 9 实例10-3的运行结果
上述案例,首先定义了一个结构体,然后定义结构体数组,最后引用结构体数组的元素的成员。
1.结构指针的定义
结构体指针即指向结构体变量的指针,它是一个指针变量,而且其目标变量是一个结构体变量,其内容是结构体变量的首地址。结构体指针的定义类似一般指针,其一般格式如下:
struct 结构体名 *指针变量名
例如:
struct person per;
struct perspn* p_per=&per;
其中per为结构体变量,p_per为结构体指针,per的地址赋给指针变量 p_per,即
p_per指向结构体变量per。
2.结构体指针引用结构体成员
在 C 语言中,通过结构体指针 p 也可以引用结构体中的成员,有以下两种方式:
方式一 (*p).成员名;
例如:struct perspn* p_per=&per;
(*p_per)表示指向的结构体变量 per,(*p_per).age 表示指向的结构体变量 per中的成age。注意,“.”运算符优先级是最高的,(*p_per)两侧的括号不能省略。
方式二 p->成员名;
为了简化操作,C 语言允许将(*p).成员名用 p->成员名替换,(*p_per).age 等价于
p_per->age,“->”称为指向运算符。
两种方式如下图10-10所示。
图10- 10 结构体指针引用结构体成员的方式
为了帮助大家更好地掌握结构体指针使用,接下来通过一个案例演示。
实例10- 4 指针指向结构的运用。
#include
struct teacher
{
char name[8];
int age;
int id;
int salary;
};
int main()
{
struct teacher tea={"王永敢",28,1,10000};
struct teacher *p_tea=&tea;
printf("教师个人信息如下\n");
printf("教师的姓名:%s\n", (*p_tea).name);//指针引用成员name
printf("教师的年龄:%d\n", (*p_tea).age);//指针引用成员age
//指针引用成员id等价于(*p_tea).id
printf("教师的编号:%d\n",p_tea->id);
//指针引用成员salary等价于(*p_tea).salary
printf("教师的薪水:%d\n", p_tea->salary);
getchar();
return 0;
}
运行结果, 如图10-11所示。
图10- 11 实例10-4 运行结果
函数的形参不仅可以传递简单的变量、数组、指针等类型的数据,当然结构体作为数据类型的一种也是可以传递的,接下来我们就来学习结构体数据类型怎么作为函数参数传递。
结构体变量作为函数参数的用法与普通变量作为函数的参数形式上一样,实参传递给形参,被调用的函数拿到数据,实现数据传递。
接下来,通过一个案例来演示如何将结构体变量作为函数参数传递数据,如例10-5所示。
实例10- 5 结构体变量作为函数参数传递数据。
#include
struct Person //定义结构体
{
char name[10];
int age;
};
void show(struct Person person)
{
printf("结构体作为参数传递过来的数据\n");
printf("name: %s\n", person.name);
printf("age: %i\n", person.age);
}
int main()
{
struct Person per = {"李志军", 16};//实例结构体
show(per);//调用show方法实现传递结构体数据
getchar();
return 0;
}
运行结果如图所示 10-12所示实现结构体数据的传递。
图10- 12 实例10-5运行结果
上述案例,定义了Person结构体,并在main函数里实例化了结构体,在调用show()函数的时候实例化之后的Person结构体变量传递给了show()函数。
所谓将结构体指针指针作为函数参数传递时,其实就是传递结构体变量的首地址。
接下来,通过一个案例来演示如何将结构体指针作为函数参数传递数据,如例10-6所示。
实例10- 6 将结构体指针作为函数参数传递数据。
#include
struct Person
{
char name[10];
int age;
};
void show(struct Person* person)
{
printf("结构体指针作为参数传递过来的数据\n");
printf("name: %s\n",(* person).name);
printf("age: %i\n", (* person).age);
}
int main()
{
struct Person per = {"李志军", 16};//实例结构体
show(&per);//获取结构体的地址值
getchar();
return 0;
}
运行结果如图所示 10-13所示实现指针结构体数据的传递。
图10- 13 实例10-6运行结果
上述的案例中,与实例10-4不同的就是在参数传递的是结构体指针通过&运算符获取结构体变量的地址值,然后将其作为函数进行传递。
最后我们来讲结构体数组怎么进行参数传递,实现数据的传递,其实也和普通数组的传递形式一致。
接下来,通过一个案例来演示如何将结构体数组作为函数参数传递数据,如例10-7所示。
实例10- 7 结构体数组作为函数参数传递数据
#include
struct Person
{
char name[10];
int age;
};
void show(struct Person person[])
{
printf("结构体数组作为参数传递过来的数据\n");
int i=0;
for(i=0;i<2;i++) {
printf("name: %s\t",person[i].name);
printf("age: %i\n", person[i].age);
}
}
int main()
{
struct Person pers[2] = {{"李志军", 16},{"冯佳", 23}
};
show(pers);
getchar();
return 0;
}
运行结果如图所示 10-14所示实现指针结构体数组的传递。
图10- 14 实例10-7 运行结果
在此案例中,结构体数组作为函数的参数进行了传递,show()函数接收到数据之后,对数组进行了遍历。
C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称等。一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。
typedef 的一般使用形式为:
typedef 原类型名 新类型名
例如:
typedef int integer
其中 integer 是 int 类型的别名,在程序中可以使用 integer 代替 int 来定义整型变量。例如:
integer a,b;等价于int a,b;
下面通过例子来了解 typedef 在结构体的中的的应用。
实例10- 8 typedef 在结构体的中的的应用。
#include
struct Student
{
char name[8];
int age;
int id;
};
typedef struct Student t_Student;
int main()
{
printf("typedef的使用\n");
t_Student stu={"黄明建",12,1,10000};
printf("学生姓名:%s\n",stu.name);
printf("学生年龄:%d\n",stu.age);
printf("学生编号:%d\n",stu.id);
getchar();
return 0;
}
运行的结果如图 10-15所示。
图10- 15 实例10-8运行结果
上述案例中,typedef struct Student t_Student;其中 struct Studen 为自定义结构体类型名,t_Studen 为 struct Studen 的别名。