结构体及应用
参考文章链接:https://blog.csdn.net/zw1996/article/details/53844585
结构体的声明
结构体的初始化
注意如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了。
/这样是可以的,在定义变量的时候就初始化了;
struct book s1={//对结构体初始化
"guojiajiaoyun",//author为字符数组
"yuwen",//title为字符串
22.5
};
/这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了;
struct book s1;
s1={
"guojiajiaoyun",//author为字符数组
"yuwen",//title为字符串
22.5
};//这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值;
只能;
s1.title = "yuwen";........//单个赋值;
应用练习
/*
用结构体做一个选票系统,输入选民和唱票过程,输出票数和当选人
*/
#include
#include
struct XuanMin
{
char name[32];
int tickets;
};
int main()
{
int i;
int j;
int len;
int mark;
int quit = 0;
char tmp_name[32];
struct XuanMin xm[3];
struct XuanMin max;
len = sizeof(xm)/sizeof(xm[0]);
for(i = 0;i < len;i++){//初始化 选民的名字和票数
xm[i].tickets = 0;
printf("请输入第%d个选民的名字:\n",i+1);
scanf("%s",xm[i].name);
}
//唱票过程
for(i=0;i<5;i++){//总共有5票
mark = 0;
printf("请输入你要投给谁:\n");
memset(tmp_name,'\0',sizeof(tmp_name));
scanf("%s",tmp_name);
for(j = 0;j < len;j++){//判断是否和输入的三个选民名字相同
if(strcmp(tmp_name,xm[j].name) == 0){
xm[j].tickets++;
mark = 1;
}
}
if(mark == 0){
quit++;
printf("查无此人,弃票\n");
}
}
max = xm[0];
for(i = 1;i<len;i++){
if(max.tickets < xm[i].tickets){
max = xm[i];
}
}
for(i = 0;i < len;i++){
printf("选民:%s的票数为:%d\n",xm[i].name,xm[i].tickets);
}
printf("弃票数:%d\n",quit);
printf("%s以%d票当选,%d人弃票\n",max.name,max.tickets,quit);
return 0;
}
结构体指针及应用
指针就是地址,指针变量就是存放地址的变量,结构体也是变量。变量的访问有两种方式:1.变量名;2.地址。之前的结构体都是用变量名访问。
通过结构体变量地址来访问该结构体需要一个变量来存放这个地址:和之前的指针是一样的,只是指针类型是结构体。
int a;
int *p;
p = &a;
struct Test t1;
struct Test *p;
p = &t1;
访问
#include
struct Test
{
int idata;
char cdata;
};
int main()
{
struct Test t1 = {10,'X'};
struct Test *p;
p = &t1;
printf("idata:%d\n",t1.idata);//变量名访问 用点符号
printf("idata:%d\n",p->idata);//指针访问 用箭头符号
return 0;
}
结构体指针+函数的练习
/*
函数创建结构体,函数初始化结构体
函数实现唱票过程
*/
#include
#include
#include
struct XuanMin
{
char name[32];
int tickets;
};
//结构体初始化
struct XuanMin* init_xm(struct XuanMin *p,int *plen)//返回值是结构体指针
{
int i;
//为指针开辟空间
if(p == NULL){
printf("请输入选民个数:\n");
scanf("%d",plen);
p = (struct XuanMin*)malloc(*plen*sizeof(struct XuanMin));
}
for(i=0;i<*plen;i++){
p->tickets = 0;
printf("请输入第%d个选民的名字:",i+1);
scanf("%s",p->name);
p++;
}
return p-*plen;
}
//打印结构体
void printf_struct(struct XuanMin *p,int len)
{
int i;
for(i=0;i<len;i++){
printf("选民:%s的票数为:%d\n",p->name,p->tickets);
p++;
}
}
//唱票过程
int do_vote(struct XuanMin* p,int len,int num)
{
int i;
int j;
int mark;
int quit = 0;
char tmp_name[32];
struct XuanMin* pbak = p;
for(i=0;i<num;i++){//总共有num票
p = pbak;
mark = 0;
printf("第%d个人投给:",i+1);
memset(tmp_name,'\0',sizeof(tmp_name));//清空
scanf("%s",tmp_name);
for(j = 0;j < len;j++){//判断是否和输入的三个选民名字相同
if(strcmp(tmp_name,p->name) == 0){
p->tickets++;
mark = 1;
}
p++;
}
if(mark == 0){
quit++;
printf("查无此人,弃票\n");
}
}
return quit;
}
//找出票数最高的
struct XuanMin* getmax(struct XuanMin* p,int len)
{
int i;
struct XuanMin* max;
max = p;
for(i = 0;i<len;i++){
if(max->tickets < p->tickets){
max = p;
}
p++;
}
return max;
}
int main()
{
struct XuanMin *xm = NULL;
struct XuanMin* max ;
int len;
int quit;
int num;
xm = init_xm(xm,&len);
printf("请输入投票次数:\n");
scanf("%d",&num);
quit = do_vote(xm,len,num);
printf("弃票数为:%d\n",quit);
printf_struct(xm,len);
max = getmax(xm,len);
printf("%s以%d票当选,%d人弃票\n",max->name,max->tickets,quit);
return 0;
}
二级指针的练习
void init_xm(struct XuanMin** pxm,int* plen)
{
//初始化结构体
int i;
if(*pxm == NULL){
printf("请输入选民的个数:\n");
scanf("%d",plen);
*pxm = (struct XuanMin*)malloc(*plen * sizeof(struct XuanMin));
}
for(i=0;i<*plen;i++){
(*pxm)->tickets = 0;
printf("请输入第%d个选民的名字:\n",i+1);
scanf("%s",(*pxm)->name);
(*pxm)++;
}
*pxm = *pxm - *plen;
}
int main()
{
struct XuanMin *xm;
int len;
int *plen = &len;
struct XuanMin** pxm = &xm;//定义指向指针的变量为二级指针
init_xm(&xm,&len);
}
联合体union
结构体struct
各成员各自拥有自己的内存,各自使用互不干涉,同时存在的,遵循内存对齐原则。一个struct变量的总长度等于所有成员的长度之和。
联合体/共用体union
各成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权(对该内存的读写),各变量共用一个内存首地址。因而,联合体比结构体更节约内存。一个union变量的总长度至少能容纳最大的成员变量,而且要满足是所有成员变量类型大小的整数倍。不允许对联合体变量名U2直接赋值或其他操作。
共同体每次只能存放共同体变量中的的一种!!
共同体变量中起作用的成员是最后一次存放的成员,在存入新的成员后原有的成员失去了作用!
看大小
看地址
联合体应用小练习
#include
/*
有若干人员的数据,其中有学生和教师,学生的数据中包括:姓名、号码、
性别、职业、班级,教师数据包括:姓名、号码、性别、职业、职务,
要求用同一个结构体来处理。
*/
struct Person
{
char name[16];
int num;
char sex[16];
char zhiye;
union {
int class;
char kemu[16];
}msg;
};
int main()
{
int i;
struct Person school[2];
//初始化结构体
for(i=0;i<2;i++){
printf("请输入这个人的职业:'s'代表学生,'t'代表老师。\n");
scanf("%c",&(school[i].zhiye));
if(school[i].zhiye == 's'){
printf("请输入学生的名字:");
scanf("%s",&(school[i].name));
printf("请输入学生的号码:");
scanf("%d",&(school[i].num));
printf("请输入学生的性别:");
scanf("%s",&(school[i].sex));
printf("请输入学生的班级:");
scanf("%d",&(school[i].msg.class));
}if(school[i].zhiye == 't'){
printf("请输入老师的名字:");
scanf("%s",&(school[i].name));
printf("请输入老师的号码:");
scanf("%d",&(school[i].num));
printf("请输入老师的性别:");
scanf("%s",&(school[i].sex));
printf("请输入老师的科目:");
scanf("%s",&(school[i].msg.kemu));
}
getchar();
}
//打印结构体数据
for(i=0;i<2;i++){
if(school[i].zhiye == 's'){
printf("学生个人资料:\n");
printf("姓名:%s,号码:%d,性别:%s,班级:%d\n",
school[i].name,school[i].num,school[i].sex,school[i].msg.class);
}
if(school[i].zhiye == 't'){
printf("老师个人资料:\n");
printf("姓名:%s,号码:%d,性别:%s,科目:%s\n",
school[i].name,school[i].num,school[i].sex,school[i].msg.kemu);
}
}
return 0;
}
枚举类型enum
如果一个变量只有几种可能的值,比如星期几:Mon、Tues、Wed、Thurs、Fri、Sat、Sun。
怎么定义枚举类型:列表中的名字,可以自己定义,无需像变量一样去申请。
C编译器把它当成常量处理,也称枚举变量。
enum Week {Mon,Tues,Wed,Thurs,Fri,Sat,Sun};
enum Week {Mon = 1,Tues = 2,Wed,Thurs,Fri,Sat,Sun};
enum {Mon,Tues,Wed,Thurs,Fri,Sat,Sun}w1,w2;
typedef关键字
typedef是在C和C++编程语言中的一个关键字。作用是为现有的数据类型(int、float、char……)创建一个新的名字,目的是为了使代码方便阅读和理解。
typedef 原类型 新类型名;
//整型
typedef int DATATYPE;
DATATYPE a;
//结构体
typedef struct stu STU;
STU stu1;
//结构体
typedef struct{
int data;
int data2;
}T2;
T2 t2;
//数组
typedef char ARRAY20[20];
//表示ARRAY20是类型char[20]的别名,它是一个长度为20的字符数组类型,接着可以用ARRAY20定义数组:
ARRAY20 a1,a2,a3,a4;
//指针
typedef int *STRING;
STRING a;
//数组指针
typedef int (*PTR_TO_ARR)[4];
//表示 PTR_TO_ARR 是类型int (*) [4]的别名,它是一个一维数组指针类型。接着可以使用 PTR_TO_ARR 定义一维数组指针:
PTR_TO_ARR p1, p2;
typedef与#define的区别
Typedef是起别名,define是替换。
例如:
typedef int *PTR; //要加 ";"
PTR a,b;
此时a,b都是指针变量。
#define PTR int* //不用 ";"
PTR a,b;
此时等同于
int *a,b;
只有a为指针变量,而b为整型变量。