前言
大家好,我是卷卷,本节课的主题是结构体。本节课主要有以下三个部分:结构体的定义与使用,学生成绩管理,作业。(文末附课程资源和讨论q群号)
一、结构体的定义与使用
所谓结构体,是自定义的数据类型。所以它也有一般数据类型的性质,比如定义数组,定义指针等等。在结构体中,可存放多个不同类型的数据,这是与一般数据类型的最大区别。结构体的语法如下:
struct 结构名{
数据类型1 变量名1;
数据类型2 变量名2;
......;
};
注意花括号后要加分号!结构体定义变量和普通数据类型定义变量的格式差不多,假设结构名为stu,则有struct stu a;这就定义了一个名为a的,数据类型为stu的变量。a中也包含了一个stu的所有成员。一般结构体定义变量需要加struct,为使定义变得更简单,可用typedef关键字定义结构体,语法如下:
typedef struct 名称1{
数据类型1 变量名1;
数据类型2 变量名2;
......;
}名称2;
这样,如果使用名称2定义变量,就无需加struct。其中typedef针对的是struct这个整体,也就是从s开始到花括号结束的部分,是typedef的对象。以上描述可简化为:typedef 结构体 结构体别名;使用结构体别名即可像普通数据类型那样定义变量。另外,名称1和名称2可以是相同的。如果使用C++语法,还可以进一步简化,语法如下:
struct 名称1{
数据类型1 变量名1;
数据类型2 变量名2;
......;
};
这样就可以直接使用名称1,像普通数据类型那样定义变量了。在cpp文件中,这样定义结构体后,用不用struct效果都一样。但在c文件中,必须加上struct。C++还支持在花括号后再加一个名称来作为别名。别名定义变量时也无需加struct。访问结构体成员很简单,只需在结构体变量后面加“点”。举例如下:
#include<stdio.h>
struct student{
int no;
double grade;
char name[20];
};
student stu;
int main(){
stu.grade=80;
return 0;
}
以上代码定义了一个叫作student的结构体,有int,double等变量。还定义了一个student类型的变量stu。由于全局变量只能在花括号内被修改,所以在主函数内访问stu的成员。如果stu是一个student类型的指针,则点号就要变成箭头,即:->。当然,既然是非空指针,肯定要指向一块空间。可以用C或C++语法动态分配一块空间,这里不再赘述。
二、学生成绩管理
例1:输入n(n<50)个学生的成绩信息,自定义函数stu_sort(),对每个学生的平均成绩排序。自定义函数stu_update(),修改学生信息。在主函数中调用这两个函数。分析:显然需要定义一个表示学生的结构体,存放课程成绩,平均分等。题目包含多个学生,所以需要定义结构体数组。因为要对数组元素操作,所以自定义函数的参数类型是结构体指针。因为只有修改功能,所以返回类型为void。函数体内,可以用指针++的方式访问结构体成员,但需要用箭头符号。也可以用方括号,需要用点号访问。排序函数内,可以选择不同的排序算法排序。注意这里的交换元素操作,也是对整个结构体变量操作。代码:
#include<stdio.h>
struct student{
int no;
char name[10];
int comp,en,math;
double avg;
};
void stu_sort(student* stu,int n);
void stu_update(student* stu,int n);
int find_no(student* stu,int n,int num);
void input_data(student* stu,int index);
int main(){
int n;
student students[50];
printf("输入学生数:");
scanf("%d",&n);
printf("输入学生信息:\n");
for(int i=0;i<n;i++){
printf("输入第%d个学生的信息:\n",i+1);
input_data(students,i);
students[i].avg=(students[i].comp+
students[i].en+students[i].math)/3.0;
}
printf("\n平均分排序前:\n");
for(int i=0;i<n;i++)
printf("%s:%.2f ",students[i].name,
students[i].avg);
stu_sort(students,n);
printf("\n平均分排序后:\n");
for(int i=0;i<n;i++)
printf("%s:%.2f ",students[i].name,
students[i].avg);
printf("\n");
stu_update(students,n);
return 0;
}
void stu_sort(student* stu,int n){
for(int i=0;i<n-1;i++){
int k=i;
for(int j=k+1;j<n;j++)
if(stu[j].avg<stu[k].avg)
k=j;
if(k!=i){
student temp=stu[k];
stu[k]=stu[i];
stu[i]=temp;
}
}
}
void input_data(student* stu,int index){
printf("输入学号:");
scanf("%d",&stu[index].no);
printf("输入姓名:");
scanf("%s",stu[index].name);
printf("输入计算机成绩:");
scanf("%d",&stu[index].comp);
printf("输入英语成绩:");
scanf("%d",&stu[index].en);
printf("输入数学成绩:");
scanf("%d",&stu[index].math);
}
int find_no(student* stu,int n,int num){
for(int i=0;i<n;i++)
if(stu[i].no==num)
return i;
return -1;
}
void stu_update(student* stu,int n){
int num;
printf("输入要修改的学生学号:");
scanf("%d",&num);
int index=find_no(stu,n,num);
if(index==-1){
printf("学号不存在,修改失败!\n");
return;
}
printf("输入要修改的信息:\n");
input_data(stu,index);
stu[index].avg=(stu[index].comp+
stu[index].en+stu[index].math)/3.0;
printf("修改成功!\n");
}
这就是本题的全部代码了。定义结构体,我想大家应该没有什么问题。选择排序函数,如果大家之前的作业有认真做的话,选择排序应该不是问题。需要注意这里传入的是一个结构体指针,由于这里定义了一个结构体数组,所以传入的是数组名,结构体的元素用点号访问。查找学号函数,其中num是要查找的学号,如果要查找的学号和已有的相同,就返回当前下标,如果循环结束,说明学号未找到,就返回-1。修改函数,首先输入要修改的学生学号,然后再利用查找函数去查找,这里用了嵌套调用,一个函数体内调用另一个函数。这是一个比较方便的做法,这种形式能够提高编程效率,可减少很多重复的代码。如果找不到,则给出提示,然后直接返回。如果找到学号,就输入要修改的信息。这就是自定义函数的基本介绍了。主函数里也要用到输入函数input_data,所以如果一段代码用的非常频繁的话,建议把它封装成一个函数,方便调用,也能够提高编程效率。我们验证一下,为了更直观地表示运行结果,我们来进行一次调试。在调试之前,我们需要先准备好一些数据,以方便调试和运行。数据如下:
好,现在开始调试。首先在这个地方打断点: 然后粘贴数据,按下回车: 这样,结构体数组就接收了全部的数据。我们来观察下,双击students,点击“添加查看”: 左边就是结构体数组的信息了: 可以看到,输入正常。然后我们不断点“下一步”,直到第30行,然后查看结果: 结果显示了排序前的数据。由于已经调用了排序函数,我们可以提前在查看窗口查看排序结果: 排序功能正常。然后我们不断点“下一步”,直到第35行,然后查看结果: 正常输出。接下来是修改函数,为了节约时间,我们直接点下一步,修改结构体成员,然后查看变化: 可以看到,修改功能正常。点击上方的红叉,结束调试。好了,这就是本题的讲解了,下一讲大家要做一个学生管理系统,代码量会比这个大的多,中间肯定要经过一些调试,调试就按我之前的方法操作即可。
三、作业
最后是作业,1道练习题加两道练习题,总共3道题。练习1: 这道题很简单,找最大值和最小值的算法,我想大家之前都已经练习过,只不过这里的数据类型不是int,也不是字符串,而是结构体。练习2: 题目只包括生日,没有直接包括年龄,所以不能定义这个属性。既然给出一个生日,它要比较大小,我想大家应该已经知道了,用string compare函数。特别注意,年龄和出生日期的大小比较是相反的,也就是出生日期越大,年龄越小,出生日期越小,年龄越大。然后还要注意一下string compare函数的比较方式,第一个和第二个比较,如果第一个小于第二个,那么就输出一个负数,如果第一个大于第二个,那么就输出一个正数。好了,这就是本讲的全部内容了,我们下讲见! 课后作业和参考答案 提取码:l2du 讨论群号:1028887052
|