结构体初识
1.结构体是什么?
1.1 是一种新的数据类型——自定义类型
数组 是 相同数据类型的集合
结构体是不同数据类型的集合
1.2 为什么要有结构体——
加入在程序中需要使用“商品”这样一个类型,一般的商品具有产品名称、形状、颜色、功能、价格和产地等特点,那么“商品”这种类型并不能使用之前学习过的任何一种类型表示,这时就要自己定义一种新的类型,像这种自己指定的结构称为结构体。
1.3 完整定义结构体的语法
/*
struct 标识符
{
基本数据类型;
}
*/
struct MM //struct MM 就是类型
{
char name[20];
int age;
int num;
}
2.如何定义结构体变量——类型+变量名
/*
int num;
struct 结构体名 变量名;
int *p;
struct 结构体名* 指针名;
int array[4];
struct 结构体名 数组名[数组长度]
*/
struct MM //struct MM 就是类型
{
char name[20];
int age;
int num;
}
struct MM myMM;
struct MM *pMM;
struct MM mtMM[20];
3.如何访问结构体成员
3.1 用变量访问:变量.成员
3.2 指针访问 :结构体指针—>成员
(*结构体指针) . 成员
#include<stdio.h>
#include<stdio.h>
struct MM //struct MM 就是类型
{
char name[20];
int age;
int num;
};
struct MM g_MM={"g_MM",19,24};//也可定义全局的结构体变量
int main()
{
printf("请输入姓名,年龄,编号:");
//3.1 结构体变量的访问
scanf("%s%d%d",myMM.name,&myMM.age,&myMM.num);
printf("%s\t%d\t%d\n",myMM.name,myMM.age,myMM.num);
//定义变量的时候初始化
struct MM yourMM={"Baby",18,22};
//<2.>没有结构体名的结构体
struct
{
char name[20];
int age;
int num;
}role={"g_role",20,1001};//该结构体只有一个结构体变量
role.name="GG_role";//可以修改。
struct boy
{
char name[20];
int age;
int num;
}bRole;
//bRole : struct boy bRole;
struct boy bRole2;
struct boy bRole3;
return 0;
}
结构体数组
什么时候采用结构体数组:
多次使用多种不同的数据的时候,采用结构体封装
struct 结构体名 数组名[数组长度]
//封装一个打字母游戏的结构体数组
struct Tar
{
int x; //横坐标
int y; //纵坐标
char target;//砖块上的字母
int speed; //下落的速度
};
struct Tar array[10];
打印学生多种不同的信息:
#include<stdio.h>
#include<string.h>
struct student
{
char name[20];
int age;
int score;
};
int main()
{
struct student stu[3];
printf("请输入三个学生信息:\n");
for(int i=0;i<3;i++)
{
printf("请输入第%d位的信息:",i+1);
scanf("%s%d%d",stu[i].name,&stu[i].age,&stu[i].score);
}
printf("姓名\t年龄\t编号\n");
for(int i=0;i<3;i++)
{
printf("%s\t%d\t%d\n",stu[i].name,stu[i].age,stu[i].score);
}
return 0;
}
结构体指针
指针要充当变量使用:
1.指向变量
2.动态内存申请
#include<stdio.h>
#include<string.h>
struct MM
{
char name[20];
int age;
int num;
};
int main()
{
struct MM* p=NULL;
//指向变量
struct MM myMM;
p=&myMM;
strcpy(p->name,"ILoveYou");
p->age=19;
p->num=1001;
//对结构体数据进行访问
printf("%s\t%d\t%d\n",myMM.name,myMM.age,myMM.num);
printf("%s\t%d\t%d\n",p->name,p->age,p->num);
//*+指针名变成变量,因此
printf("%s\t%d\t%d\n",(*p).name,(*p).age,(*p).num);
//2.动态内存申请的指针
struct MM* pMM=(struct MM*)malloc(sizeof(struct MM));
strcpy(pMM->name,"MM");
pMM->age=19;
pMM->num=1004;
//动态内存申请的结构体数组
struct MM* pArray=(struct MM*)malloc(sizeof(struct MM)*3);
return 0;
}
typedef与结构体的定义
//同时为结构体变量,结构体指针,结构体数组 起别名
typedef struct student_score_info
{
char name[20];
int age;
int num;
}SSI,*LPSSI,SARRY[2];
#include<stdio.h>
#include<string.h>
typedef struct student_score_info
{
char name[20];
int age;
int num;
}SSI,*LPSSI,SARRY[2];
struct MM
{
char name[20];
int age;
int num;
};
typedef struct MM MMTYPE;
typedef struct MM* LPMM;
int main()
{
//正常写法
struct student_score_info mm;
SSI t_mm;
struct student_score_info* pMM=&mm;
LPSSI p=&mm;
struct student_score_info array[2];
SARRY myarray;
return 0;
}
结构体中的指针
结构体用到指针,需要先申请内存,在进行操作!
#include<stdio.h>
#include<string.h>
struct Gril
{
char name[20];
int age;
int score;
};
struct Boy
{
char* name;//是指针不能直接赋值
int age;
int score;
};
int main()
{
struct Girl xy;
strcpy(xy.name,"LXY");//字符串拷贝操作进行赋值
struct Boy yourBoy;
char inputname[20];
printf("inputName:");
scanf("%s",inputName);
yourBoy.name=(char* )malloc(strlen(inputName)+1);
strcpy(yourBoy.name,inputName);
yourBoy.age = 10;
yourBoy.num = 1001;
free(yourBoy.name);
yourBoy.name=NULL;
return 0;
}
内存对齐问题
内存问题分为
1.不对齐
不对齐的内存就是所有内存之和
2.对齐
按照最大的数据类型占用的内存的倍数
节省内存的写法:
字符型当作一个字节处理;
从小到大写
#include<stdio.h>
#include<string.h>
struct MM
{
char name[3]; //3
int age; //4
double num; //8
}
int main()
{
//占用内存的多少只跟内存申请有关系
struct MM* pMM=(struct MM*)malloc(sizeof(struct MM));
printf("%d\n",sizeof(struct MM));
//多打印便可找到规律
return 0;
}
联合体和枚举类型
联合体就是共用体,与结构体最大不同在于——
——1.所有变量共用最长的内存
——2.struct关键字改为union
联合的成员name和age是无法同时使用的
union MM
{
char name[30];//共用这段最大的内存
int age;
int num;
}
int main()
{
union MM myMM={"10"};
strcpy(myMM.name,"1001");//对一元素赋值相当于操作整个内存
printf("%s\n",&myMM.age);
myMM.age=99;
printf("%d\n",myMM.age);
printf("%s\n",myMM.name);
printf("%d\n"myMM.num);
return 0;
}
枚举类型:整型常量
项目中一些具有代表性的常量的符号替换
//项目一些具有代表性的常量的符号替换
enum direction {UP=72,DOWN=80,LEFT=75,RIGHT=77};
//默认的值:0,1,2,3..
//局部的默认:是前者的+1
enum Color{red=1,black,yellow=9,blue};
int main()
{
while(1)
{
char userKey=_getch();
switch(userKey)
{
case Up:
printf("%d\t",red);
break;
case DOWN:
printf("%d\t",black);
break;
case LEFT:
printf("%d\t",yellow);
break;
case RIGHT:
printf("%d\t",blue);
break;
}
}
return 0;
}
结构体嵌套
1,以另一个结构体变量为数据成员
2,以另一个结构体指针为数据成员
//首先,以结构体变量为成员的结构体
//最不常见的一种
struct A
{
int num;
struct B
{
int age;
};
};
int main()
{
struct A aBug={11,23};//可以直接赋值
//无需嵌套,直接就可以访问到结构体A中的结构体B变量
printf("%d\t%d\n",aBug.age,aBug.num);//输出:23,11
//改成用指针访问
struct A* pA=&aBug;
printf("%d\t%d\n",pA->age,pA->num);
return 0;
}
//稍微常见的一种
struct MM
{
int num;
struct GG
{
int age;
}boy;
}
int main()
{
struct MM mmObject={121,135};//初始化和第一种一样
printf("%d\t%d\n",mmObject.num,mmObject.boy.age);//嵌套访问
return 0;
}
//2.常见的写法
struct score
{
int math;
int chinese;
}
struct student
{
struct score stuScore;//将上面的结构体作为数据成员
char name[20];
int num;
}
int main()
{
struct student Li={123,111,"张三",1001};//初始化
struct student Liu={{109,99},"李四",1002};//第二种初始化
printf("%d\t%d\t%d\t%d\n",Liu.stuScore.math,liu.stuScore.chinses,liu.name,liu.num);//剥洋葱式的访问
return 0;
}
//指针的嵌套
struct studentInfo
{
struct score* pScore;
int name[20];
int age;
}
int main()
{
//剥洋葱式为指针申请内存第一层
struct studentInfo* p=(struct studentInfo*)malloc(sizeof(struct studentInfo));
//第二层
p->pScore=(struct score*)malloc(sizeof(struct score));
//用指针赋值
p->pScore->chinese=14;
p->pScore->matr=100;
printf("%d\t%d\n",p->pScore->chinese,p->pScore->math);
return 0;
}