C语言结构体

目录

结构体引入:

定义一个结构体:

编程练习:如何定义一个结构体

编程练习:结构体变量的定义和访问

 编程练习:输入两个学生的名字,学号,成绩等输出成绩高的学生的信息

 结构体数组:

编程练习:结构体数组应用

 编程练习:选票系统

结构体指针:

编程练习:结构体指针的定义及访问

 编程练习:结构体指针的应用01

 编程练习:结构体指针应用02

 编程练习:结构体指针数组函数综合应用改写选票系统

 结构体二级指针:

 编程练习:结构体二级指针

 共用体/联合体引入:

编程练习:共用体定义和使用

 编程练习:共用体开发案例

枚举类型 

编程练习:如何定义枚举类型且使用

 typedef 关键字

编程练习:typedef 使用


 

结构体引入:

为什么要引入结构体?

如果没有结构体的话就只能 int char float 单独去定义,不是一个有机的整体,利用结构体定义数据类型可以将这些数据都融合到一起,就可以模拟实现多一的数据类型。(类比数组,数组是相同的数据类型集合到一起,结构体是不同的数据类型集合到一起)

定义一个结构体:

编程练习:如何定义一个结构体

/*
	如何定义一个结构体
*/

#include <stdio.h>

struct Student	//告知系统是一个结构体,关键字"struct"
{
	int num;
	char name[32];
	char sex[4];
	char address[32];
	int age;
	double score;
};				//分号很重要,不能丢

struct Date
{
	int year;
	int month;
	int day;
	int hour;
	int minute;
	int seconds;
};

int main()
{
	
	return 0;
}

编程练习:结构体变量的定义和访问

/*
	结构体变量的定义和访问
*/

#include <stdio.h>
#include <string.h>

struct Student
{	
	int num;
	char name[32];
	char sex[4];
	char address[32];
	int age;
	double score;
};				

int main()
{
	int a;
	struct Student stu1;	//struct Student就相当于int
	struct Student stu2 = {20140678,"唔西迪兮","女","河北",18,97.5};
	
	stu1.num = 20140656;	//点运算符来访问结构体中的成员变量(域)
	strcpy(stu1.name,"玛卡巴卡");	//给字符串赋值用字符串拷贝
	strcpy(stu1.sex,"男");
	strcpy(stu1.address,"山西");
	stu1.age = 18;
	stu1.score = 98.5;
	
	printf("学号:%d 姓名:%s 性别:%s 地址:%s 年龄:%d 分数:%.1lf\n",
		stu1.num,stu1.name,stu1.sex,stu1.address,stu1.age,stu1.score);
		
	printf("学号:%d 姓名:%s 性别:%s 地址:%s 年龄:%d 分数:%.1lf\n",
		stu2.num,stu2.name,stu2.sex,stu2.address,stu2.age,stu2.score);
	
	return 0;
}

 编程练习:输入两个学生的名字,学号,成绩等输出成绩高的学生的信息

/*
	输入两个学生的名字,学号,成绩等输出成绩高的学生的信息
*/


#include <stdio.h>

struct Student
{
	int num;
	char name[32];
	char sex[4];
	char address[32];
	int age;
	double score;
};

int main()
{
	struct Student stu1;
	struct Student stu2;
	struct Student Better;
	
	printf("请输入学生1的学号、姓名、性别、地址、年龄、分数\n");
	scanf("%d%s%s%s%d%lf",&stu1.num,stu1.name,stu1.sex,stu1.address,&stu1.age,&stu1.score);
	
	printf("请输入学生2的学号、姓名、性别、地址、年龄、分数\n");
	scanf("%d%s%s%s%d%lf",&stu2.num,stu2.name,stu2.sex,stu2.address,&stu2.age,&stu2.score);
	
	printf("学生1的成绩:%.1lf 学生2的成绩:%.1lf\n",stu1.score,stu2.score);
	
	Better = stu1;
	
	if(stu1.score < stu2.score)
	{
		Better = stu2;
	}
	
	puts("成绩较好的是");
	printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
			Better.num,Better.name,Better.sex,Better.address,Better.age,Better.score);
	
	return 0;
}

 结构体数组:

它与前面讲的数值型数组几乎是一模一样的,只不过需要注意的是,结构体数组的每一个元素都是一个结构体类型的变量,都包含结构体中所有的成员项。

定义结构体数组的方法很简单,同定义结构体变量是一样的,只不过将变量改成数组。或者说同前面介绍的普通数组的定义是一模一样的,如:

struct Student stu[10];

这就定义了一个结构体数组,共有 10 个元素,每个元素都是一个结构体变量,都包含所有的结构体成员。

结构体数组的引用与引用一个结构体变量在原理上是一样的。只不过结构体数组中有多个结构体变量,我们只需利用 for 循环来遍历结构体数组中的元素。 

编程练习:结构体数组应用

/*
	结构体数组应用
*/


#include <stdio.h>

struct Student
{
	int num;
	char name[32];
	char sex[4];
	char address[32];
	int age;
	double score;
};

int main()
{
	struct Student stu[3] = {
		{20140656,"玛卡巴卡","男","山西",18,98.5},
		{20140678,"唔西迪兮","女","河北",18,97.5},
		{20140690,"依古比古","男","北京",18,95.5}
		};
		
	int i;
	int len = sizeof(stu)/sizeof(stu[0]);
	
	for(i=0;i<len;i++)
	{
		printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
			stu[i].num,stu[i].name,stu[i].sex,stu[i].address,stu[i].age,stu[i].score);
	}
	
	
	return 0;
}

 编程练习:选票系统

/*
	选票系统
*/

#include <stdio.h>
#include <string.h>

struct Voter
{
	int tickets;
	char name[32];
};

int main()
{
	struct Voter xm[3];
	struct Voter Best;
	
	int i;
	int len = sizeof(xm)/sizeof(xm[0]);
	int total = 6;		//总票数为6
	char tempname[32];	//定义一个临时名字来和选民的名字一一对比,相同的对应的票数加1
	int j;
	int mark = 0;
	int abandon = 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<total;i++)
	{
		mark = 0;
		printf("请问你想投给谁?\n");
		memset(tempname,'\0',sizeof(tempname));	//每次投票时,临时名字都清空成0
		scanf("%s",tempname);
		for(j=0;j<len;j++)
		{
			if(strcmp(tempname,xm[j].name) == 0)	
			{				//将每次的投票和选民的名字进行对比,如果相同,对应的票数加1,如果不一样,则弃票
				xm[j].tickets++;
				mark = 1;
			}
		}
		if(mark == 0)	//如果投票和所有名字都不匹配,弃票加1
			{
				printf("弃票\n");
				abandon++;
			}
	}
	
	//公布环节
	
	for(i=0;i<len;i++)
	{
		printf("name:%s tickets:%d\n",xm[i].name,xm[i].tickets);
	}
	
	putchar('\n');

	Best = xm[0];
	
	for(i=0;i<len;i++)
	{
		if(Best.tickets < xm[i].tickets)
		{
			Best = xm[i];
		}
	}
	printf("经投票,%s以%d票当选,弃票%d票\n",Best.name,Best.tickets,abandon);
	
	return 0;
}

结构体指针:

变量的访问有两种方式:1.变量名访问;2.通过地址来访问,结构体也一样,可以通过变量名和地址来访问结构体变量,因此引入结构体指针。

编程练习:结构体指针的定义及访问

/*
	结构体指针的定义和应用
*/

#include <stdio.h>

struct Test
{
	int indata;
	char cdata;
};

int main()
{
	int idata = 10;
	int *pi = &idata;	//之前定义指针的方法
	
	char cdata = 'R';
	char *pc = &cdata;	//之前定义指针的方法
	
	struct Test T1 = {20,'E'};
	struct Test *pt = &T1;
	
	printf("indata = %d,cdata = %c\n",T1.indata,T1.cdata);	
					//之前学到的用变量名访问结构体变量方法
	
	printf("indata = %d,cdata = %c\n",pt->indata,pt->cdata);	
					//用结构体指针访问结构体变量的方法,用"->"取代点运算符
	return 0;
}

 编程练习:结构体指针的应用01

/*
	用结构体指针来遍历数组
*/

#include <stdio.h>

struct Student
{
	int num;
	char name[32];
	char sex[4];
	char address[32];
	int age;
	double score;
};

int main()
{
	struct Student stu[3] = {
		{20140656,"玛卡巴卡","男","山西",18,98.5},
		{20140678,"唔西迪兮","女","河北",18,97.5},
		{20140690,"依古比古","男","北京",18,95.5}
	};
	struct Student *p;
	p = stu;
	int i;
	int len = sizeof(stu)/sizeof(stu[0]);
	
	for(i=0;i<len;i++)
	{
		printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
				p->num,p->name,p->sex,p->address,p->age,p->score);
		p++;
	}
	
	/*	使用指针遍历数组时,一次遍历指针会移到数组的尾巴,
		所以当要再一次遍历时,要重新指向数组的首地址。
	p = stu;	
	
	for(i=0;i<len;i++)
	{
		printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
				p->num,p->name,p->sex,p->address,p->age,p->score);
		p++;
	}*/
	
	
	
	return 0;
}

 注意:如果使用结构体指针遍历数组后想要再次遍历数组的时候,要把指针再次指向数组首地址!!!要不然就会出现以下等问题:

 编程练习:结构体指针应用02

/*
	用结构体指针改写选票系统
*/


#include <stdio.h>
#include <string.h>

struct Voter
{
	int tickets;
	char name[32];
};

/*
	1.把以前普通的变量名或者下标访问的运算符,改成结构体指针的 "->"
	2.每次遍历数组都会指针都会偏移到数组尾巴,下次遍历之前要重新指向数组首地址
*/

int main()
{
	struct Voter xm[3];
	struct Voter Best;
	struct Voter *p;
	p = xm;
	
	int i;
	int len = sizeof(xm)/sizeof(xm[0]);
	int total = 6;		//总票数为6
	char tempname[32];	//定义一个临时名字来和选民的名字一一对比,相同的对应的票数加1
	int j;
	int mark = 0;
	int abandon = 0;
	
	//初始化环节
	for(i=0;i<len;i++)
	{
		p->tickets = 0;
		printf("请输入第%d位选民的名字\n",i+1);
		scanf("%s",p->name);
		p++;
	}
	//唱票环节
	p = xm;
	for(i=0;i<total;i++)
	{
		mark = 0;
		printf("请问你想投给谁?\n");
		memset(tempname,'\0',sizeof(tempname));	//每次投票时,临时名字都清空成0
		scanf("%s",tempname);
		p = xm;
		for(j=0;j<len;j++)
		{
			if(strcmp(tempname,p->name) == 0)	
			{				//将每次的投票和选民的名字进行对比,如果相同,对应的票数加1,如果不一样,则弃票
				p->tickets++;
				mark = 1;
			}
			p++;
		}
		if(mark == 0)	//如果投票和所有名字都不匹配,弃票加1
			{
				printf("弃票\n");
				abandon++;
			}
	}
	
	//公布环节
	p = xm;
	for(i=0;i<len;i++)
	{
		printf("name:%s tickets:%d\n",p->name,p->tickets);
		p++;
	}
	
	putchar('\n');

	Best = xm[0];
	p = xm;
	for(i=0;i<len;i++)
	{
		if(Best.tickets < p->tickets)
		{
			Best = *p;
		}
		p++;
	}
	printf("经投票,%s以%d票当选,弃票%d票\n",Best.name,Best.tickets,abandon);
	
	return 0;
}

 编程练习:结构体指针数组函数综合应用改写选票系统

/*
	结构体指针数组函数综合应用改写选票系统
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Voter
{
	int tickets;
	char name[32];
};

struct Voter *InitFun(struct Voter *p,int *len)
{
	int i;
	
	if(p == NULL)
	{
		printf("请输入有几个人参选?\n");
		scanf("%d",len);
		p = (struct Voter *)malloc(*len * sizeof(struct Voter));
	}

	for(i=0;i<*len;i++)
	{
		p->tickets = 0;
		printf("请输入第%d位选民的名字\n",i+1);
		scanf("%s",p->name);
		p++;
	}
	return p-*len;
}

void PrintFun(struct Voter *p,int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("name:%s tickets:%d\n",p->name,p->tickets);
		p++;
	}
}

int CallFun(struct Voter *p,int len)
{
	int i;
	int total = 0;
	char tempname[32];
	int j;
	int mark = 0;
	int abandon = 0;
	struct Voter *pback = p;
	
	printf("请问总共有多少人投票?\n");
	scanf("%d",&total);
	
	for(i=0;i<total;i++)
	{
		mark = 0;
		printf("请输入你想投给谁?\n");
		memset(tempname,'\0',sizeof(tempname));
		scanf("%s",tempname);
		p = pback;
		for(j=0;j<len;j++)
		{
			if(strcmp(tempname,p->name) == 0)
			{
				p->tickets++;
				mark = 1;
			}
			p++;
		}
		if(mark == 0)
		{
			printf("弃票\n");
			abandon++;
		}
	}
	return abandon;
}

struct Voter *GetBest(struct Voter *p,int len)
{
	int i;
	struct Voter *Best;
	
	Best = p;
	
	for(i=0;i<len;i++)
	{
		if(Best->tickets < p->tickets)
		{
			Best = p;
		}
	}
	return Best;
}

int main()
{
	struct Voter *xm = NULL;
	int len = 0;
	
	xm = InitFun(xm,&len);
	PrintFun(xm,len);
	
	int abandon = CallFun(xm,len);
	PrintFun(xm,len);
	
	struct Voter *Best = GetBest(xm,len);
	
	printf("%s以%d票当选,弃票%d票\n",Best->name,Best->tickets,abandon);
	
	return 0;
}

 结构体二级指针:

假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:


将这种关系转换为C语言代码:

 
  1. int a =100;
  2. int *p1 = &a;
  3. int **p2 = &p1;

指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级指针,指向一级指针 p1,定义时有两个*。(结构体的二级指针也一样)

 编程练习:结构体二级指针

/*
	结构体二级指针应用
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Voter
{
	int tickets;
	char name[32];
};

struct Voter *InitFun(struct Voter **p,int *len)
{
	int i;
	
	if(*p == NULL)
	{
		printf("请输入有几个人参选?\n");
		scanf("%d",len);
		*p = (struct Voter *)malloc(*len * sizeof(struct Voter));
	}

	for(i=0;i<*len;i++)
	{
		(*p)->tickets = 0;			//当二级指针的"*"和"->"运算符在一起的时候要括起来注意符号优先级问题
		printf("请输入第%d位选民的名字\n",i+1);
		scanf("%s",(*p)->name);
		(*p)++;
	}
	return *p - *len;
}

void PrintFun(struct Voter *p,int len)
{
	int i;
	for(i=0;i<len;i++)
	{
		printf("name:%s tickets:%d\n",p->name,p->tickets);
		p++;
	}
}

int CallFun(struct Voter *p,int len)
{
	int i;
	int total = 0;
	char tempname[32];
	int j;
	int mark = 0;
	int abandon = 0;
	struct Voter *pback = p;
	
	printf("请问总共有多少人投票?\n");
	scanf("%d",&total);
	
	for(i=0;i<total;i++)
	{
		mark = 0;
		printf("请输入你想投给谁?\n");
		memset(tempname,'\0',sizeof(tempname));
		scanf("%s",tempname);
		p = pback;
		for(j=0;j<len;j++)
		{
			if(strcmp(tempname,p->name) == 0)
			{
				p->tickets++;
				mark = 1;
			}
			p++;
		}
		if(mark == 0)
		{
			printf("弃票\n");
			abandon++;
		}
	}
	return abandon;
}

struct Voter *GetBest(struct Voter *p,int len)
{
	int i;
	struct Voter *Best;
	
	Best = p;
	
	for(i=0;i<len;i++)
	{
		if(Best->tickets < p->tickets)
		{
			Best = p;
		}
	}
	return Best;
}

int main()
{
	struct Voter *xm = NULL;
	int len = 0;
	
	xm = InitFun(&xm,&len);
	PrintFun(xm,len);
	
	int abandon = CallFun(xm,len);
	PrintFun(xm,len);
	
	struct Voter *Best = GetBest(xm,len);
	
	printf("%s以%d票当选,弃票%d票\n",Best->name,Best->tickets,abandon);
	
	return 0;
}

 共用体/联合体引入:

共用体和结构体十分相似,是一种构造类型或复杂类型,它也可以包含多个类型不同的成员。

结构体共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

注意:结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉

编程练习:共用体定义和使用

/*
	共用体的定义及其注意事项
*/

#include <stdio.h>

struct TestT
{
	int indata;
	char cdata;
	double ddata;
};

union TestU
{
	int indata;
	char cdata;
};

int main()
{
	struct TestT t1;
	union  TestU u1;
	
	t1.indata = 10;
	t1.cdata  = 'c';
	t1.ddata = 98.5;
	
	u1.indata = 10;
	u1.cdata  = 'd';
	
	printf("结构体大小是sizeof = %d\n",sizeof(t1));		//内存大于或等于所有成员的内存
	printf("共用体大小是sizeof = %d\n",sizeof(u1));		//内存大小由最大成员的内存决定
	
	printf("结构体:\n indata:%p %d\n cdata:%p %d\n ddata:%p %d\n",t1.indata,t1.cdata,t1.ddata);
				//结构体成员的每一个都有单独的地址
	printf("共用体:\n indata:%p %d\n cdata:%p\n ",u1.indata,u1.cdata);
				//共用体所有成员都共用一个地址
				
				
	//因为结构体成员每一个都有独立的内存空间,所以它的每一个成员都可以打印出来。互不干扰;
	//因为共用体成员每一个都是公用同一个内存空间,所以它的值会被之后一个输入的成员覆盖掉。
	return 0;
}

 编程练习:共用体开发案例

/*
	共用体应用
*/


#include <stdio.h>

struct Person
{
	char name[32];
	int num;
	char sex[4];
	char Profession;
	union
	{
		char class[8];
		char subject[4];
	}mes;
};

int main()
{
	struct Person p[2];
	int i;
	int len = sizeof(p)/sizeof(p[0]);
	
	for(i=0;i<len;i++)
	{
		printf("请输入您的职业,t or s\n");
		scanf("%c",&(p[i].Profession));
		if(p[i].Profession == 't')
		{
			printf("请老师输入名字\n");
			scanf("%s",p[i].name);
			printf("请老师输入所教的科目\n");
			scanf("%s",p[i].mes.subject);
		}
		else
		{
			printf("请学生输入名字\n");
			scanf("%s",p[i].name);
			printf("请学生输入所在班级\n");
			scanf("%s",p[i].mes.class);
		}
		getchar();
	}
	
	for(i=0;i<len;i++)
	{
		if(p[i].Profession == 't')
		{
			printf("老师的名字是%s,所教的科目是%s\n",p[i].name,p[i].mes.subject);
		}
		else
		{
			printf("学生的名字是%s,所在班级是%s\n",p[i].name,p[i].mes.class);
		}
	}
	
	return 0;
}

枚举类型 

在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程,这时候就要用到枚举类型

编程练习:如何定义枚举类型且使用

/*
	枚举类型
*/

#include <stdio.h>

enum Month
{
	Jan = 1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec
}m1,m2;

int main()
{
	
	m1 = Feb;
	m2 = Dec;
	
	if(m1 < m2)
	{
		printf("我看你是在为难我玛卡巴卡\n");
	}
	
	printf("m1 = %d m2 = %d\n",m1,m2);
	
	
	return  0;
}

/*
	1.值默认从0开始,枚举元素不能被赋值,虽然瞅着象变量名
	2.可以指定列表中枚举数的值
	3.可以直接忽略枚举类型名,直接定义枚举变量
*/

 typedef 关键字

C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。(方便用户使用)

编程练习:typedef 使用

#include <stdio.h>

typedef struct
{
	int num;
	char name[32];
	char sex;
}S,*p;

void print1(S p)
{
	printf("num:%d name:%s sex:%c\n",p.num,p.name,p.sex);
}

void print2(S *p)
{
	printf("num:%d name:%s sex:%c\n",p->num,p->name,p->sex);
}

int main()
{
	S p1 = {20140656,"玛卡巴卡",'b'};
	S p2 = {20140678,"唔西迪兮",'g'};
	
	print1(p1);
	print1(p2);
	
	S *pp1 = &p1;
	S *pp2 = &p2;
	print2(&p1);
	print2(&p2);
	
	
	return 0;
}

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日落星野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值