结构体
目录:
- 结构体的概念
- 结构体类型的定义
- 结构体类型的嵌套定义
- 结构体类型变量
- 结构体类型变量的定义
- 结构体类型变量的初始化
- 结构体类型变量的引用
- 注意事项1
- 注意事项2
- 注意事项3
- 注意事项4
- 相关说明
- 结构体数组
- 结构体数组的定义
- 结构体数组的初始化
- 分行初始化
- 顺序初始化
- 结构体数组的访问
- 结构体数组应用举例
- 结构体与指针
- 指向结构体类型数据的指针
- 指向结构体变量的指针
- 指向结构体数组的指针
- 结构体变量和指向结构体的指针做函数参数
- 结构体变量做参数(值传递)
- 结构体数组做函数参数
- 函数返回值是结构体类型
1.结构体的概念
结构体是一种构造数据类型
数组也是一种构造数据类型(由多个数组合在一起),结构体可以组合不同类型的数
用途:把不同类型的数据组合成一个整体————自定义数据类型。
2.结构体类型的定义
结构体先定义类型,再定义变量
语法格式与实例
- 关键字struct代表定义的是结构体类型。
- 注意最后的分号。
- 在之后定义变量时要使用类型名,注意类型名,在实例中,类型名不是”student”而是”struct student”!!!
- 结构体中的成员可以是普通类型,也可以是构造类型(如数组)。因此数组可以作为成员名。
结构体类型的嵌套定义
之后结构体类型的定义可以利用之前所定义过的结构体类型
嵌套定义的例子
3. 结构体类型变量
1. 结构体类型变量的定义
方法一:使用已经定义好的结构体类型定义变量
方法二:在定义结构体类型的同时定义变量
方法三:直接定义结构体变量
在这三种中,通常采用第一种。
方法一实例:struct student为定义好的结构体类型,在其之后定义了fresher,junior两个变量
方法二实例,前方为结构体类型的定义,之后所接的即为变量,之后若想继续定义变量,则需要用方法一
方法三实例,没有定义结构体的类型,直接定义了变量。用这种方式,之后无法继续使用此类型定义变量,只能在这一行添加。
2. 结构体类型变量的初始化
与结构体类型变量的定义相对应,其有三种情形:
先定义结构体类型,然后定义结构体变量,然后写上了一些内容(初始化)
定义结构体类型的同时定义变量,并且对它进行初始化
不定义结构体类型,直接定义结构体类型的变量,并且对它们初始化
情形一,注意不能整体赋值!
- 结构体变量不允许整体赋值
- 初始化时各成员初值要与数据类型一致!
情形二,同理,不能对结构体变量做整体的赋值运算
情形三实例,不定义结构体类型,直接定义变量并初始化
3. 结构体类型变量的引用
一般形式: 结构体变量名.成员名
注意事项:
不能将结构体变量作为一个整体进行输入和输出
不能将两个结构体变量进行整体比较
可以将一个结构体变量整体赋值给另一个结构体变量
结构体嵌套时逐级引用
引用实例:
赋值运算,自加运算,判断
注意事项1:
结构体变量不能整体输入和输出和赋值!
需要一一对应地输出
不能整体输入,注意要加取地址符号,但是数组(char类型)的名字就是地址(首地址)
结构体变量不能整体赋值。注意第二行,作为数组名,不能出现在赋值等于号的左边(因为它是常量),因此字符串的拷贝用strcpy,第六行的地址同理
注意事项2:
不能对结构体变量做是否相等的运算。
需要比较时,则将里面的每一个字段一一比较以确认相等。
通常此内容对应到数据库知识。注意第二行,对两个字符串进行比较时使用strcmp
注意事项3(可以):
可以把一个结构体变量整体赋值给另一个!
可以将stu1的所有信息赋值给stu2
注意事项4
结构体嵌套时逐级引用!
结构体类型嵌套定义,若想引用该结构体中所嵌套的另一个结构体类型的成员,中的信息,要逐级引用。
如:变量名.成员名.嵌套的结构体的成员名
有几层便要用几层的引用。
相关说明:
注意:结构体类型与结构体变量不可混淆!
结构体成员名与程序中变量名可相同,互不影响!
结构体可复合!
关于结构体复合:
在结构体类型的定义内再定义另一个结构体类型
与嵌套的不同之处:它真的把结构体嵌进去了!
结构体的复合
4. 结构体数组
结构体与数组的联系:
在结构体的成员中有数组(如char name[10])
把数组放在外面,把结构体放在里面,便生成结构体数组。
结构体数组的定义
类似于结构体变量定义的三种方法,结构体数组的定义有三种方法:
一、使用已经定义好的结构体类型定义数组
例子:
1 2 3 4 5 6 7 8
| struct student { int num; char name[20]; char sex; int age; }; struct student stu[2];
|
结构体数组的分配空间
二、在定义结构体类型的同时定义数组
1 2 3 4 5 6 7
| struct student { int num; char name[20]; char sex; int age; }stu[2];
|
三、直接定义结构体数组
1 2 3 4 5 6 7
| struct { int num; char name[20]; char sex; int age; }stu[2];
|
2. 结构体数组的初始化
分行初始化
所谓分行,不是局限于行数,而是初始化时,使用了多组大括号。
只要每个初始化信息外有大括号,就是分行初始化。
例子:
1 2 3 4 5 6 7 8 9 10
| struct student { int num; char name[20]; char sex; int age; }; struct student stu[]={{100,"Wang Lin",'M',20}, {101,"Li Gang",'M',19}, {110,"Liu Yan",'F',19}};
|
全部初始化时维数(第八号方括号内的数)可省
顺序初始化
例子:
1 2 3 4 5 6 7 8
| struct student { int num; char name[20] char sex; int age; }; struct student stu[]={100,"Wang Lin",'M',20,101,"Lin Gang",'M',19,110,"liu Yan",'F',19};
|
与分行初始化的区别:每个人的信息都用逗号隔开,外面没有大括号了。
结构体数组元素的访问
语法格式: 结构体数组名[下标].成员名
例:
让一号同学的年龄加一:
让零号学生姓名为ZhaoDa
1
| strcpy(stu[0].name,"ZhaoDa");
|
作为数组(常量),因此不能用赋值运算,使用strcpy,把字符串拷贝到数组中
结构体数组应用举例:
选举:十三人中,三人为候选人,十人为选举人,选举三人中的一人。每个人那一张纸条,上面写上”Li”或”Wang”或”Zhang”投票。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include<stdio.h> #include<string.h> struct person { char name[20]; int count; }leader[3]={"Li",0,"Zhang",0,"Wang",0}; void main() { int i,j; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } printf("\n"); for(i=0;i<3;i++) printf("%5s:%d\n",leader[i].name,leader[i].count); }
|
5.指向结构体类型数据的指针
1.指向结构体变量的指针
2.指向结构体数组的指针
3.结构体变量和指向结构体的指针做函数参数
指向结构体变量的指针
引例
1 2 3 4
| int i; int *p=&i; i=10;
|
由此引出:
1 2 3 4
| struct student stu1; struct student *q=&stu1; stu1.age=18;
|
注:点号为单目运算符,结合性为自右向左,即可能出现忽略左侧星号*的情况。所以要带上小括号。
由于写的时候容易有歧义、或者要带括号,较为麻烦,
因此可以用一种新的写法:
尤其当之后学了链表后,都是用这种方法,基本上不再用前者。
定义 struct 结构体名 *指针变量;
赋初值 指针变量名=&结构体变量;
访问成员 设p为指向结构体变量的指针:
访问方式一:(*p).成员名
访问方式二:p->成员名
指向结构体数组的指针
定义一个数组,定义一个指针指向数组的第一个地址,指针P就可以通过自加运算访问第一、二、三······个。
例:有3个学生的信息,放在结构体数组中,输出全部学生的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <string.h>
struct student { int num; char name[20]; char sex; int age; }stu[3]={{10101,"Li Lin",'M',18},{10102,"Zhang Fun",'M',19},{10104,"Wang Min",'F',20}}; void main() { struct student *p; for(p=stu;p<stu+3;p++) printf ("%d%s%c%d\n",p->num,p->name,p->sex,p->age); }
|
结构体变量和指向结构体的指针作函数参数
1. *结构体变量作参数(值传递)
例:定义一个复数类型的结构体,通过函数调用,求两个复数的和。
复数包括实部、虚部,结构体变量可以带多个成员。因此可以定义一个复数的结构体类型,带三个成员:实部、虚部和模。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<stdio.h> #include<math.h> struct complex_t { double real; double imag; double modular; }; void add(struct complex_t,struct complex_t); int main() { struct complex_t c1.c2; scanf("%lf %lf",&c1.real,&c1.imag); scanf("%lf %lf",&c2.real,&c2.imag); add(c1,c2); return 0; } void add(struct comples_t c1,struct complex_t c2) { struct comples_t c; c.real=c1.real+c2.real; c.imag=c1.imag+c2.imag; c.modular=sqrt(c.real*c.real+c.imag*c.imag); printf("%lf,%lf,%lf\n",c.real,c.imag,c.modular); }
|
结构体数组作为函数参数
(例题:学生的记录由学号和成绩组成,N名学生的数据已在主函数中放入结构体数组s中,请编写函数fun,其功能是:把分数最低的学生数据放在h所指的数组中。注意:分数最低的学生可能不止一个,函数返回分数最低的学生的人数。)
通过结构体数组作为参数的形式实现排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void SortData(struct student *pstu,int n) { int i,j; struct student temp; for(i=0;i<n-1;i++) for(j=0;j<n-1-i;j++) if(pstu[j].sum<pstu[j+1].sum) { temp=pstu[j]; pstu[j]=pstu[j+1]; pstu[j+1]=temp; } }
|
函数的返回值是结构体类型
1 2 3 4 5 6 7 8
| struct complex_t add(struct complex_t c1,struct complex_t c2) { struct complex_t c; c.real=c1.real+c2.real; c.imag=c1.imag+c2.imag; c.modular=sqrt(c.real*c.real+c.imag*c.imag); return c; }
|
主函数的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <math.h> struct complex_t { double real; double imag; double modular; }; struct complex_t add(struct complex_t,struct complex_t); int main() { struct complex_t c,c1,c2; scanf("%lf %lf",&c1.real,&c1.imag); scanf("%lf %lf",&c2.real,&c2.imag); c=add(c1,c2); printf("%lf,%lf,%lf\n",c.real,c.imag,c.moudlar); return 0; }
|
例:
设一个班级有三十个人,学生信息包括姓名、学号外、三科成绩。利用函数的返回值找出总分最高分和最低的学生的信息。
函数只能返回一个回来,如何解决这个问题——可以用指针带回来一些值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include<stdio.h> #define N 30 struct student { char name[20]; long num; float score[3]; float sum; }; struct student max(struct student [],struct student *,int); void inputdata(struct student stu[],int); void inputdata(struct student stu[],int n) { int i,j; for(i=0;i<n;i++) { scanf("%s %ld %f %f %f",stu[i].name,&stu[i].num,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]); stu[i].sum=(stu[i].score[0]+stu[i].scpre[1]+stu[i].scpre[2]); } } struct student max(struct student stu[],struct student *s,int n) { struct student t; int i; float m,p; m=p=stu[0].sum; for(i=0;i<n;i++) { if(m<=stu[i].sum) { m=stu[i].sum; t=stu[i]; } if(p>=stu[i].sum) { p=stu[i].sum *s=stu[i]; } } return t; } int main() { struct student st[N],maxst,minst; inputdata(st,N); maxst=max(st,&minst,N); printf("最高分学生信息:\n"); printf("%s %ld %.2f %.2f %.2f %.2f\n",maxst.name,maxst.num,maxst.score[0],maxst.score[1],maxst.scpre[2],maxst.sum); printf("最低分学生信息:\n"); printf("%s %ld %.2f %.2f %.2f %.2f\n",minst.name,minst.num,minst.score[0],minst.score[1],minst.score[2],minst.sum); return 0; }
|