师承clc
初始
为什么要用结构体
整型数,浮点型数,字符串是分散的数据表示,有时候我们需要用很多类型的数据来表示一个整体,比如学生信息
![](https://i-blog.csdnimg.cn/blog_migrate/b24a52115d7a0bfa56e208f417dbfb80.png)
类比与数组:数组是元素类型一样的数据集合,如果是元素类型不同的数据集合,就要用到结构体了
定义一个结构体
![](https://i-blog.csdnimg.cn/blog_migrate/a9334a16b3c3833aa831dcd7e6238bee.png)
它算是一个模板,一般不给赋具体的值,每一项在实际应用中并不是都要使用
成员列表
也称为域表--每个成员都是结构体中的一个域
在声明的同时,定义变量,尽量少用
![](https://i-blog.csdnimg.cn/blog_migrate/e29bf0d5e3b7c7e908450500ba267b50.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f5714bcd0391f268b6b4ed877c075f27.png)
初始化一个结构体变量并引用
初始化
![](https://i-blog.csdnimg.cn/blog_migrate/a38c9ffd811cc31364ca74e61368c2ca.png)
引用
![](https://i-blog.csdnimg.cn/blog_migrate/6ce87b433ffd8e7ecdb085d1d1f27640.png)
重点认知
结构体没什么特殊的,只是把变量藏在结构体里面,而内部的变量,以前学习的东西是通用的,只是“触达的方式”不同
例题
输入两个学生的名字,学号,成绩,输出成绩高的学生的信息
#include <stdio.h>
struct Student
{
char name[12];
int num;
int sor;
};
int main()
{
struct Student stu[1];
struct Student max;
max = stu[0];
for(int i=0;i<2;i++){
printf("输入第%d个学生名字:\n",i+1);
scanf("%s",&(stu[i].name));
printf("输入第%d个学生学号:\n",i+1);
scanf("%d",&(stu[i].num));
printf("输入第%d个学生分数:\n",i+1);
scanf("%d",&(stu[i].sor));
}
if(stu[0].sor < stu[1].sor){
max = stu[1];
}
printf("成绩最高的学生名字是:%s,成绩是%d\n",max.name,max.sor);
return 0;
}
结构体数组
![](https://i-blog.csdnimg.cn/blog_migrate/e58e15efeff176b7bf758a123214d452.png)
应用练习:选票系统
#include <stdio.h>
#include <string.h>
struct XuanMin
{
char name[12];
int tickets;
};
int main()
{
int i,j;
int n = 1;
int totalPer;
int totalTic;
int mark;
int feipiao = 0;
char tempName[12] = {'\0'};
printf("请输入参选人数:\n");
scanf("%d",&n);
struct XuanMin xm[n-1];
struct XuanMin max;
printf("请输入参加投票人数:\n");
scanf("%d",&totalPer);
for(i=0;i<n;i++){
printf("请输入第%d个选名的名字",i+1);
scanf("%s",xm[i].name);
xm[i].tickets = 0;
}
for(j=0;j<totalPer;j++){
mark = 0;
printf("请输入你投给谁:\n");
memset(tempName,'\0',sizeof(tempName));
scanf("%s",tempName);
for(i=0;i<n;i++){
if(strcmp(tempName,xm[i].name) == 0){
xm[i].tickets++;
mark = 1;
}
}
if(mark == 0){
printf("没有此人,此票作废\n");
feipiao++;
}
}
for(i=0;i<n;i++){
printf("名字:%s,票数:%d \n",xm[i].name,xm[i].tickets);
}
max = xm[0];
for(i=0;i<n;i++){
if(max.tickets < xm[i].tickets){
max = xm[i];
}
}
printf("%s 以 %d 票当选,废票是 %d 票\n",max.name,max.tickets,feipiao);
return 0;
}
结构体指针
概念引入
回忆:
指针就是地址,指针变量就是存放地址的变量,结构体也是变量,变量访问有两种方式 : 1.变量名 2.地址
之前案例,是用变量名访问
通过结构体变量地址来访问该结构体,需要一个变量来保持这个地址:,这和之前说的指针,其实是一样的,只是指针类型是结构体
![](https://i-blog.csdnimg.cn/blog_migrate/cd709c9acb7485ab50cd7c7ed46efc5e.png)
通过结构体指针访问结构体
![](https://i-blog.csdnimg.cn/blog_migrate/b21bc551c62ad58bca7f63e731f234db.png)
结构体数组,指针,函数应用
根据选票系统进行修改
#include <stdio.h>
#include <string.h>
struct XuanMin
{
char name[12];
int tickets;
};
int main()
{
int i,j;
int n = 1;
int totalPer;
int totalTic;
int mark;
int feipiao = 0;
char tempName[12] = {'\0'};
printf("请输入参选人数:\n");
scanf("%d",&n);
struct XuanMin xm[n-1];
struct XuanMin max;
struct XuanMin *p;
p = xm;
printf("请输入参加投票人数:\n");
scanf("%d",&totalPer);
for(i=0;i<n;i++){
printf("请输入第%d个选名的名字",i+1);
scanf("%s",p->name);
p->tickets = 0;
p++;
}
p = xm;
for(j=0;j<totalPer;j++){
mark = 0;
printf("请输入你投给谁:\n");
memset(tempName,'\0',sizeof(tempName));
scanf("%s",tempName);
p = xm;
for(i=0;i<n;i++){
if(strcmp(tempName,p->name) == 0){
p->tickets++;
mark = 1;
}
p++;
}
if(mark == 0){
printf("没有此人,此票作废\n");
feipiao++;
}
}
p = xm;
for(i=0;i<n;i++){
printf("名字:%s,票数:%d \n",p->name,p->tickets);
p++;
}
p = xm;
max = xm[0];
for(i=0;i<n;i++){
if(max.tickets < p->tickets){
max = xm[i];
p++;
}
}
printf("%s 以 %d 票当选,废票是 %d 票\n",max.name,max.tickets,feipiao);
return 0;
}
选民系统小综合(函数)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct XuanMin
{
char name[12];
int tickets;
};
struct XuanMin* initXM(struct XuanMin *p,int *pn, int *ptotalPer)
{
if(p == NULL){
printf("请输入有几人参选:");
scanf("%d",pn);
p = (struct XuanMin*)malloc(*pn * sizeof(struct XuanMin));
}
printf("请输入参加投票人数:\n");
scanf("%d",ptotalPer);
for(int i=0;i<*pn;i++){
printf("请输入第%d个选名的名字",i+1);
scanf("%s",p->name);
p->tickets = 0;
p++;
}
return p-*pn;
}
void printfXM(struct XuanMin *p,int n)
{
for(int i=0;i<n;i++){
printf("名字:%s,票数:%d \n",p->name,p->tickets);
p++;
}
}
int doVot(struct XuanMin *p,int totalPer,int n)
{
int i;
int j;
int mark;
int feipiao = 0;
char tempName[12] = {'\0'};
struct XuanMin *pbak = p;
for(j=0;j<totalPer;j++){
mark = 0;
printf("请输入你投给谁:\n");
memset(tempName,'\0',sizeof(tempName));
scanf("%s",tempName);
p = pbak;
for(i=0;i<n;i++){
if(strcmp(tempName,p->name) == 0){
p->tickets++;
mark = 1;
}
p++;
}
if(mark == 0){
printf("没有此人,此票作废\n");
feipiao++;
}
}
return feipiao;
}
struct XuanMin* getMax(struct XuanMin *p,int n)
{
struct XuanMin *max;
int i;
max = p;
for(i=0;i<n;i++){
if(max->tickets < p->tickets){
max = p;
}
p++;
}
return max;
}
int main()
{
int n = 0;
int totalPer;
int totalTic;
struct XuanMin *final;
struct XuanMin *xm = NULL;
xm = initXM(xm,&n,&totalPer);
int feip = doVot(xm,totalPer,n);
printfXM(xm,n);
final = getMax(xm,n);
printf("%s 以 %d 票当选!!,废票数是 %d \n",final->name,final->tickets,feip);
return 0;
}
选民系统改进(二级指针版)
struct XuanMin* initXM(struct XuanMin **p,int *pn, int *ptotalPer)
{
if(*p == NULL){
printf("请输入有几人参选:");
scanf("%d",pn);
*p = (struct XuanMin*)malloc(*pn * sizeof(struct XuanMin));
}
printf("请输入参加投票人数:\n");
scanf("%d",ptotalPer);
for(int i=0;i<*pn;i++){
printf("请输入第%d个选名的名字",i+1);
scanf("%s",(*p)->name);
(*p)->tickets = 0;
(*p)++;
}
(*p) = (*p) - *pn;
}
initXM(&xm,&n,&totalPer);
//其他代码无改动
共用体/联合体
概念引入
有时候同一个内存空间存放类型不同,不同类型的变量共享一块空间
结构体元素有各自单独空间,共用体元素共享空间,空间大小由最大类型确定
结构体元素互不影响,共用体赋值会导致覆盖
![](https://i-blog.csdnimg.cn/blog_migrate/15ffa1fd0b6110fcd2942c417e5c043e.png)
注意数据覆盖
![](https://i-blog.csdnimg.cn/blog_migrate/6e5275fc2b3250fa216c4b31c399bb74.png)
应用
![](https://i-blog.csdnimg.cn/blog_migrate/7a419849791852cf016a4532f764fe45.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a8091c432d280d0beb2ae6f308f97113.png)
枚举类型
什么是枚举类型
如果一个变量只有几种可能的值,比如星期几son mon tus wed thu fri sat
怎么定义枚举类型
列表中的名字,可以自己定义,无需像变量一样去申请
C编译器把它当成常量处理,也称枚举常量
枚举变量
只限列表中的集中情况
![](https://i-blog.csdnimg.cn/blog_migrate/d3f7f8eff6aceb483eb136588f4a1a1c.png)
值默认从0开始,枚举元素不能被赋值,虽然瞅着象变量名
![](https://i-blog.csdnimg.cn/blog_migrate/da9c9a7d23bd2eff5542f53a4a7f8785.png)
可以指定列表中枚举数的值
![](https://i-blog.csdnimg.cn/blog_migrate/044e7ca6ba16f4a5a5bc720af69f2671.png)
可以直接忽略枚举类型名,直接定义枚举变量
![](https://i-blog.csdnimg.cn/blog_migrate/d87f497f905583422f6e6b315c67dcc3.png)
例子
![](https://i-blog.csdnimg.cn/blog_migrate/d15587d2fabf6b8161f416430eedc7ea.png)
typedef关键字
给已经有的变量类型起名字
一般配合结构体用,方便嘛,不要每次都要struct开头
![](https://i-blog.csdnimg.cn/blog_migrate/82bd42f652ed85de900ba1ebfbd465a9.png)
案例
![](https://i-blog.csdnimg.cn/blog_migrate/84693cd4fdeec794113855bbe16dd627.png)