结构体的定义和使用
##结构体的定义
结构体的定义方式为:
struct 结构体名
{
结构体所包含的变量或数组
};
举个栗子:
struct stu
{
char name[100]; //姓名
int num; //学号
};
为什么要使用结构体
那么为什么我们要学习结构体呢?因为之前学习的数组只能存放一组相同类型的数据,如果想要存放不同类型的数据,就需要使用结构体了。例如对于学生成绩管理系统,我们需要字符串类型的姓名,整型的年龄以及浮点型的成绩,请看下面的一个例子:
struct Student
{
char name[100];
int age;
float score;
}; //分号不能少
Student为结构体名,它包含了 3 个成员,分别是 name、age、score。结构体成员的定义方式与变量和数组的定义方式相同,只是不能初始化。
结构体变量
既然结构体是一种数据类型,那么就可以用它来定义变量。例如:
struct Student stu1, stu2;
这里定义了两个变量 stu1 和 stu2,它们都是 stu 类型,都由 3 个成员组成。注意关键字struct不能少。
也可以在定义结构体的同时定义结构体变量:
struct stu
{
char name[100];
int age;
float score;
} stu1, stu2;
如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名,如下所示:
struct //没有写 stu
{
char name[100];
int age;
float score;
} stu1, stu2;
但以上两种写法都不推荐,因为使用起来不够灵活。
成员的获取和赋值
结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[ ]获取单个元素,结构体使用点号.获取单个成员。获取结构体成员的一般格式为:
结构体变量名.成员名;
通过这种方式可以获取成员的值,也可以给成员赋值:
# include <stdio.h>
struct Student
{
char name;
int age;
}; //要有分号
int main(void)
{
struct Student stu1;
stu1.name = "Tom";
stu1.age = 18;
printf("%c %d\n", stu1.name, stu1.age);
return 0;
}
也可以在声明时直接赋值,例如:
struct Student stu1 = {'a', 18};
我们也可以定义一个Student类型的指针变量,然后通过变量名->成员的方式赋值,例如:
struct Student * pStu1 = &stu1;
pStu1->name = 'Jerry';
pStu1->age = 20;
结构体使用实例——学生成绩排名系统
# include <stdio.h>
# include <malloc.h>
struct Student
{
char name[100];
int age;
int score;
};
void Stu_in(struct Student * pArr, int len)
{
int i;
for(i=0;i<len;i++)
{
printf("请输入第%d个学生的信息:\n", i+1);
printf("name:");
scanf("%s", pArr[i].name);
printf("age:");
scanf("%d", &pArr[i].age);
printf("score:");
scanf("%d", &pArr[i].score);
printf("\n");
}
}
void Stu_out(struct Student * pArr, int len)
{
int i;
for(i=0;i<len;i++)
{
printf("第%d名为:\n", i+1);
printf("name:%s\n", pArr[i].name);
printf("age:%d岁\n", pArr[i].age);
printf("score:%d分\n", pArr[i].score);
printf("\n");
}
}
void exchange(struct Student * a, struct Student * b)
{
struct Student c;
c = *a;
*a = *b;
*b = c;
}
void sort(struct Student * pArr, int len)
{
int i;
int left = 0;
int right = len-1;
while(left < right)
{
int flag = 0;
for(i=left;i<right;i++)
{
if(pArr[i].score < pArr[i+1].score)
{
exchange(&pArr[i], &pArr[i+1]);
flag = 1;
}
}
if(flag == 0)
{
break;
}
right--;
flag = 0;
for(i=right;i>left;i--)
{
if(pArr[i-1].score < pArr[i].score)
{
exchange(&pArr[i-1], &pArr[i]);
flag = 1;
}
}
if(flag == 0)
{
break;
}
left++;
}
}
int main(void)
{
int amount;
struct Student * pArr;
printf("请输入您想要添加的学生的数量:");
scanf("%d", &amount);
pArr = (struct Student *)malloc(amount * sizeof(struct Student));
printf("\n");
printf("---------输入数据---------\n");
Stu_in(pArr, amount); //输入学生的相关信息
sort(pArr, amount); //使用鸡尾酒排序进行排序
printf("\n");
printf("---------学生排名---------\n");
Stu_out(pArr, amount); //输出排名后的学生信息
return 0;
}
关于结构体的内存分配
理论上讲结构体的各个成员在内存中是连续存储的,和数组非常类似。但是在编译器的具体实现中,各个成员之间可能会存在缝隙,可能会造成一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。关于这个问题,我将会在《结构体中的内存对齐问题》中详细讲解。