目录
思维导图:
学习内容:
1. 结构体
1.1 定义及初始化
1.1.1 定义格式
struct 结构体名称
{
成员类型1 成员变量1;
成员类型2 成员变量2;
。。。
成员类型n 成员变量n;
};
注意事项:
1、struct是定义结构体类型的关键字,不能省略
2、结构体名称:标识符,符合命名规则,一般建议首字母大写
3、成员属性使用一对花括号包裹起来
4、成员类型可以是基本数据类型,也可以是构造数据类型、指针类型
5、定义结束后,必须加上 分号结尾
6、举个例子
struct Stu
{
char name[20]; //姓名
int age; //年龄
double score; //成绩
};
1.1.2 使用结构体类型定义变量
#include<stdio.h> //定义一个英雄类型 struct Hero { char name[30]; // 英雄名称 int blood; //英雄血量 char skill[4][20]; //技能 int kill; //击杀人头数 int die; //死亡数量 int assiant; //辅助数量 } h2; //定义类型时,顺便定义一个变量 //定义类型顺便定义变量 struct { char name[20]; //学生姓名 int age; //年龄 double score; //成绩 }s1; //该结构体称为无名结构体 int main(int argc, const char *argv[]) { //使用自定义类型,定义一个英雄变量 struct Hero h1, h3; return 0; }
1.2 结构体访问成员
1> 普通结构体变量访问成员是,使用成员运算符 ‘.’ 来进行,读作 "的"
例如:s1.name s1.score
2> 结构体指针变量访问成员,使用成员运算符 '->'来进行,读作 '的'
例如:struct Stu *ptr = &s1; ptr->name ptr->score
3> 在进行成员访问时,访问的最终的类型,就是最后一个成员所表示的结果类型
例如:s1.name 是字符数组类型, ptr->score 是double类型
4> 当一个结构体类型中的某个成员变量也是一个结构体变量时,如果要进行最深一级的访问,需要使用成员运算符一级一级进行访问
例如:
#include<stdio.h> //定义生日结构体类型 struct Date { int year; //年份 int month; //月份 int day; //日期 }; //定义学生类型 struct Stu { char name[20]; //姓名 double score; //成绩 struct Date birthday; //生日 }; /***************主程序**********************/ int main(int argc, const char *argv[]) { //定义一个学生,并初始化 struct Stu s = {"张三", 99.5, {2000,1,1}}; s.score = 100; //访问成员更改内容 printf("%s, %.2lf, %d-%d-%d\n",s.name, s.score, s.birthday.year, s.birthday.month, s.birthday.day); //更改名字 strcpy(s.name , "lisi"); printf("%s, %.2lf, %d-%d-%d\n",s.name, s.score, s.birthday.year, s.birthday.month, s.birthday.day); printf("*********************************************\n"); struct Stu *ptr = &s; //定义指针变量指向结构体变量 printf("%s, %.2lf, %d-%d-%d\n", ptr->name, ptr->score, ptr->birthday.year, ptr->birthday.month, ptr->birthday.day); return 0; }
1.3 结构体变量的输入输出
通过成员运算符,找到结构体变量的普通成员后,本质上就是一个普通变量的输入输出
例如:
#include<stdio.h> //定义生日结构体类型 struct Date { int year; //年份 int month; //月份 int day; //日期 }; //定义学生类型 struct Stu { char name[20]; //姓名 double score; //成绩 struct Date birthday; //生日 }; /***************主程序**********************/ int main(int argc, const char *argv[]) { struct Stu s1; //定义一个结构体变量 printf("请输入学生的姓名:"); scanf("%s", s1.name); printf("请输入学生的成绩:"); scanf("%lf", &s1.score); printf("请输入学生的出生年月日(用空格隔开):"); scanf("%d%d%d", &s1.birthday.year, &s1.birthday.month, &s1.birthday.day); printf("%s, %.2lf, %d-%d-%d\n", s1.name, s1.score, s1.birthday.year, s1.birthday.month, s1.birthday.day); return 0; }
1.4 结构体数组
1> 结构体数组本质上也是一个数组,只是每个元素是结构体变量
2> 定义格式:strcut 结构体名 数组名[常量];
例如:
#include<stdio.h> //定义结构体类型 struct Hero { char name[20]; //姓名 int blood; //血量 int kill; //斩获人头数 int die; //死亡次数 int ass; //辅助次数 }; //宏定义 #define MAX 10 //主程序 int main(int argc, const char *argv[]) { //定义一个英雄数组 struct Hero hero[MAX]; int size = 0; //实际使用的个数 //初始化数组 memset(hero, 0, sizeof(hero)); printf("请输入英雄个数:"); scanf("%d", &size); //循环输入英雄的相关信息 for(int i=0; i<size; i++) { printf("请输入第%d个英雄的名称:", i+1); scanf("%s", hero[i].name); printf("请输入第%d个英雄的血量:", i+1); scanf("%d", &hero[i].blood); printf("请输入第%d个英雄的人头数:", i+1); scanf("%d", &hero[i].kill); printf("请输入第%d个英雄的死亡数:", i+1); scanf("%d", &hero[i].die); printf("请输入第%d个英雄的辅助数:", i+1); scanf("%d", &hero[i].ass); printf("\n"); } //输出英雄的信息 printf("本局比赛的结果如下:\n"); printf("英雄\t血量\t人头\t死亡\t辅助\n"); for(int i=0; i<size; i++) { printf("%s\t%d\t%d\t%d\t%d\n", hero[i].name, hero[i].blood, hero[i].kill, hero[i].die, hero[i].ass); } //求出本局的 mvp struct Hero mvp; //存放最有价值的英雄 double mvp_value = 0; //存放数据 double value; //存放当前英雄的数据 //先将第一个当做最值 mvp = hero[0]; for(int i=0; i<size; i++) { //跟任意一个英雄的数据进行比较 value = hero[i].kill*0.8 - hero[i].die*0.2 + hero[i].ass*0.4; mvp_value = mvp.kill*0.8 - mvp.die*0.2 + mvp.ass*0.4; if(mvp_value < value) { //退位让新 mvp = hero[i]; } } printf("本局的mvp为:%s, %d, %d, %d\n", mvp.name, mvp.kill, mvp.die, mvp.ass); //按斩获人头数进行降序排序 for(int i=1; i<size; i++) { for(int j=0; j<size-i; j++) { if(hero[j].kill < hero[j+1].kill) { struct Hero temp = hero[j]; hero[j] = hero[j+1]; hero[j+1] = temp; } } } printf("排序后的结果为:\n"); printf("英雄\t血量\t人头\t死亡\t辅助\n"); for(int i=0; i<size; i++) { printf("%s\t%d\t%d\t%d\t%d\n",hero[i].name, hero[i].blood, hero[i].kill, hero[i].die, hero[i].ass); } return 0; }
1.5 结构体的大小
1> 结构体变量所占内存空间的大小,是各个成员所占内存空间之和
2> 要遵循字节对齐原则,有两个
1、结构体中的每个成员,在分配内存时,要以数据类型对齐一次
2、所有成员分配内存结束后,整体需要对齐一次:
32位系统以 min(最大字节的成员,4) 对齐
64位系统以 min(最大字节的成员,8)对齐
3> 在C语言中一个空的结构体类型,占0字节
#include<stdio.h> //一个空的结构体在内存中占0个字节 struct A { }; //定义结构体类型 struct B { short value_a; short value_b; // 1122 }; //定义结构体类型 struct C { short value_a; char value_b; //1120 }; //定义结构体类型 struct D { char value_b; short value_a; //1022 }; //定义结构体类型 struct E { char value_a; int value_b; short value_c; // 100022223300 }; //定义结构体类型 struct F { char value_a; short value_c; int value_b; // 10223333 }; //定义结构体类型 struct G { char *value_a; short value_c; int value_b; //1111111122003333 }; //定义结构体类型 struct H { int value_b; char *value_a; short value_c; //111100002222222233000000 }; int main(int argc, const char *argv[]) { printf("sizeof(struct A) = %ld\n", sizeof(struct A)); //0 printf("sizeof(struct B) = %ld\n", sizeof(struct B)); //4 printf("sizeof(struct C) = %ld\n", sizeof(struct C)); //4 printf("sizeof(struct D) = %ld\n", sizeof(struct D)); //4 struct D d; printf("&d = %p, &d.value_b = %p, &d.value_a = %p\n", \ &d, &d.value_b, &d.value_a); printf("sizeof(struct E) = %ld\n", sizeof(struct E)); //12 printf("sizeof(struct F) = %ld\n", sizeof(struct F)); //8 printf("sizeof(struct G) = %ld\n", sizeof(struct G)); //16 printf("sizeof(struct H) = %ld\n", sizeof(struct H)); //24 return 0; }
课外作业:
使用结构体完成学生(学号、姓名、性别、成绩)管理系统
1> 使用菜单实现
2> 功能1:完成对学生信息的录入,确定人数,完成输入
2> 功能2:完成对学生信息的输出
3> 功能3:输出成绩最高和最低学生的信息
4> 功能4:输出学生的总成绩和平均成绩
5> 功能5:对学生信息按成绩进行排序,根据传入的升降序,确定排序功能、
6> 功能6:提示并输入要查找的学生名字,查找该名字是否存在于该班级
7> 功能0:退出
解析:
#include<stdio.h> #include<string.h> #define MAX 20 //定义结构体变量 struct stu{ int id; char names[MAX]; char sex[10]; int score; }; //菜单 void print_menu(){ printf("\n学生管理系统\n"); printf("功能1:完成对学生信息的录入,确定人数,完成输入\n"); printf("功能2:完成对学生信息的输出\n"); printf("功能3:输出成绩最高和最低学生的信息\n"); printf("功能4:输出学生的总成绩和平均成绩\n"); printf("功能5:对学生信息按成绩进行排序,根据传入的升降序,确定排序功能\n"); printf("功能6:提示并输入要查找的学生名字,查找该名字是否存在于该班级\n"); printf("功能0:退出\n"); printf("请选择操作(0-6):"); } //定义学生录用信息函数 int enterstu(struct stu stu[],int *count){ printf("请输入学生个数:"); scanf("%d",count); //输入学生个数 for (int i = 0; i < *count; i++) // 循环遍历输入各个学生信息 { printf("输入学生 %d 的姓名:", i + 1); scanf("%s",stu[i].names); printf("输入学生 %d 的学号:", i + 1); scanf("%d",&stu[i].id); printf("输入学生 %d 的性别:", i + 1); scanf("%s",stu[i].sex); printf("输入学生 %d 的成绩:", i + 1); scanf("%d",&stu[i].score); } } //打印学生信息函数 void print_stu(struct stu stu[],int count){ printf("姓名\t学号\t性别\t成绩\n"); for (int i = 0; i < count; i++) // 循环遍历学生信息,打印出来 { printf("%s\t%d\t%s\t%d\n",stu[i].names,stu[i].id,stu[i].sex,stu[i].score); } } //求出学生成绩最大最小值函数 void maxminstu(struct stu stu[],int count){ int maxscore=0; //定义初始值 int minscore=0; //定义初始值 for (int i = 0; i < count; i++) { //判断最大值 if(stu[i].score >stu[maxscore].score) { maxscore = i; } //判断最小值 if(stu[i].score <stu[minscore].score){ minscore = i; } } //打印输出成绩最大最小值的信息 printf("最高成绩的名字为%s,学号为%d,性别为%s,成绩为%d\n",stu[maxscore].names,stu[maxscore].id,stu[maxscore].sex,stu[maxscore].score); printf("最低成绩的名字为%s,学号为%d,性别为%s,成绩为%d\n",stu[minscore].names,stu[minscore].id,stu[minscore].sex,stu[minscore].score); } //统计总成绩和平均成绩函数 void sumavestu(struct stu stu[],int count){ float sum=0; float ave=0; for (int i = 0; i < count; i++) { sum += stu[i].score; //累加 } ave = sum/count; //求平均值 printf("学生的总成绩为%.2f,平均成绩为%.2f\n",sum,ave); } //排序函数 void sortstu(struct stu stu[],int count,int flag){ if( flag == 1){ //flag==1;则为升序 for(int i = 1; i < count; i++){ //交换三部曲 for(int j = 0; j < count-i; j++){ if(stu[j].score < stu[j+1].score){ struct stu temp = stu[j]; stu[j] = stu[j+1]; stu[j+1] = temp; } } } }else if(flag == 0 ){ //flag==0;则为降序 for(int i = 1; i < count; i++){ //交换三部曲 for(int j = 0; j < count-i; j++){ if(stu[j].score > stu[j+1].score){ struct stu temp = stu[j]; stu[j] = stu[j+1]; stu[j+1] = temp; } } } } printf("\n"); print_stu(stu,count); //调用打印函数输出结果 printf("\n"); } //查找学生姓名函数 int seachstu(struct stu stu[],int count,char *seach){ for (int i = 0; i < count; i++) { if (strcmp(stu[i].names,seach) ==0){ //判断查找值与输入值是否相当 return 1; //相等返回1 } } return 0; //否则为0 } int main(int argc, char const *argv[]) { int menu=0; struct stu student[MAX]; //定义学生结构体数组 int stucount=0; while (1) { //提示用户输入功能 print_menu(); scanf("%d",&menu); switch (menu) { case 1: enterstu(student,&stucount); break; case 2: print_stu(student, stucount); break; case 3: maxminstu(student,stucount); break; case 4: sumavestu(student,stucount); break; case 5:{ int flag=0; //提示用户用升序还是降序 printf("请输入你要查询升序还是降序(升序输入1,降序输入0):"); scanf("%d",&flag); sortstu(student,stucount,flag);} break; case 6:{ // 提示用户输入要查找的学生姓名 char seach[MAX]=""; printf("请输入你要查找的学生姓名:"); scanf("%s",&seach); if(seachstu(student,stucount,seach)){ printf("%s该名字存在在班级中\n",seach); }else { printf("%s该名字不存在在班级中\n",seach); } } break; case 0: goto END; default:printf("您输入的功能有误,请重新输入\n"); } } END: return 0; }