结构体与共用体结构体与共用体结构体
结构体是 一种 构造 数据类型
用途:把 不同类型 的数据组合成一个 整体 -------
自定义 数据类型
– 结构体类型定义
struct [结构体名 ]
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
成员类型可以是基本型或构造型struct是 关键字,不能省略合法标识符可省,无名结构体此处分号 ; 不能少例 struct point
{
double x;
double y;
};
struct point A;
结构体变量的定义
– 常用形式,先定义结构体类型,再定义结构体变量
一般形式,struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
struct 结构体名 变量名表列 ;
说明
结构体类型与结构体变量概念不同
类型,不分配内存 ; 变量,分配内存
类型,不能赋值、存取、运算 ; 变量,可以
结构体可嵌套
结构体成员名与程序中变量名可相同,不会混淆
结构体类型及变量的作用域与生存期 例 struct point{
double x;
double y;
};
struct triangle
{ struct point A;
struct point B;
struct point C;
};
例 struct student
{
int num;
char name[20];
int score[3];
-s1=,1,”Zhang San”,80,90,100-,s2;
2字节
1字节结构体类型定义描述结构的组织形式,不分配内存
nums1
name[0]
2字节
2字节
2字节
score[1]
score[0]
score[2]
…….,……..
name[19]
低地址高地址图 7-1 结构体变量 s1的存储结构结构体变量的引用
– 引用规则
结构体变量 不能整体引用,只能引用变量 成员
可以将一个结 构体变量赋值给另一个结构体变量
结构体嵌套时 逐级引用成员 (分量 )运算符优先级,1
结合性,从左向右引用方式,结构体变量名,成员名例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
Stu2 = stu1; ( )
结构体变量的初始化
– 常用形式,struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
struct 结构体名 结构体变量 ={初始数据 };
例 struct student
{ int num;
char name[20];
int score[3]; };
struct student s1 =,1,“Zhang San”,85,90,100”-;
定义变量时就初始化结构体变量的初始 化以及引用例 /*参考程序 7-1.c*/
#include <stdio.h>
struct student
{ int num;
char name[20];
int score[3];
};
main()
{
sturct student s1;
int i,average;
printf(“Input number:\n”);
scanf(“%d”,&s1.num);
gets(s1.name);
……-
定义变量后,再初始化要给结构体里的变量依次赋值结构体数组
– 结构体数组的定义三种形式:
num
name
sex
age
num
name
sex
age
stu[0]
stu[1]
25B
形式一,
struct student
{ int num;
char name[20];
char sex;
int age;
};
struct student stu[2];
先定义结构体,再定义变量形式三
struct
{ int num;
char name[20];
char sex;
int age;
}stu[2];
定义结构体时同时定义变量形式二,
struct student
{ int num;
char name[20];
char sex;
int age;
}stu[2];
定义结构体时同时定义变量结构 体数组应用举例例 /*参考程序 7-2.c*/
#include <stdio.h>
#define N 3
struct stu
{ int num;
char name[20];
int score[4]; };
main()
{
int i,k,max;
struct stu s[N];
printf(“Input data:\n”);
for(i=0;i<N;i++)
,scanf(“%d%s%d%d%d”,&(s*i+.num),s*i+.name,&(s*i+.score*0+),
&(s[i].score[1]),&(s[i].score[2]));
结构 体数组应用举例
s[i].score[3]=(s[i].score[0]+s[i].score[1]+s[i].score[2])/3;
}
printf(“\nAverage:”);
for(i=0;i<N;i++)
printf(“%d”,s*i+.score*3+);
max =s[0].score[3];
k =0;
for (i=1;i<N;i++)
if(s[i].score[3]>max)
{ k = i;
max = s[i].score[3]; }
printf (“\n The top student,”);
printf (“%d,%s,%d,%d,%d,average:%d\n”,s*k+.name,s*k+.score*0+,
s[k].score[1],s[k].score[2],s[k].score[3]);}
结构体和指针
– 指向结构体变量的指针
定义形式,struct 结构体名 *结构体指针名 ;
例 struct student *p;
使用结构体指针变量引用成员形式存放结构体变量在内存的起始地址指向运算符 ->
优先级,1
结合方向:从左向右结构体指针 ->成员 结构体变量,成员(*结构体指针 ).成员参考源程序 7-3.c
#include <stdio.h>
#define N 3
struct stu
{ int num;
char name[20];
int score[4]; };
main()
{
int i,k,max;
struct stu s[N],*p;
printf(“Input data:\n”);
for (p=s;p<s+N;p++)
,scanf(“%d%s%d%d%d”,&p->num,p->name,&p->score[0],&p-
>score[1],&p->score[2]);
p->score[3]=(p->score[0]+p->score[1]+p->score[2])/3;}
printf(“\nAverage:”);
for(p=s;p<s+N;p++)
printf(“%d”,p->score[3]);
P=s;
max =p->score[3];
k =0;
for (p=s+1;p<s+N;p++)
if(p->score[3]>max)
{
k = p-s;
max = p->score[3];
}
p=s+k;
printf (“\n The top student,”);
printf (“%d,%s,%d,%d,%d,average:%d\n”,p->num,p->name,p-
>score[0],p->score[1],p->score[2]);}
struct data // 定义结构体
{ int a,b,c; };
main()
{ void func(struct data);
struct data arg; // 定义结构体变量,即实参
arg.a = 27; arg.b = 3; arg.c = arg.a+arg.b;
printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c);
printf("Call Func()....\n");
func(arg); // 将实参传给函数 func,传变量名
printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c);
}
void func(struct data parm) // 通过形参 parm能改变实参 arg吗?
{
parm.a = 18; parm.b = 5; parm.c = parm.a*parm.b;
printf("parm.a=%d parm.b=%d parm.c=%d\n",parm.a,parm.b,parm.c);
printf("Return...\n");
}
arga,27
b,3
c,30
(main)
(func)
parm
a,27
b,3
c,30
copy
arg
,
b,3
c,30
(func)
parm
a,18
b,5
c,90
a,27
b,3
c,30
例 用 结构体变量(变量名) 作函数参数
struct data // 定义结构体
{ int a,b,c; };
main()
{ void func(struct data *);
struct data arg; // 定义结构体变量,即实参
arg.a=27; arg.b=3; arg.c=arg.a+arg.b;
printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c);
printf("Call Func()....\n");
func(&arg); // 将实参传给函数 func,传变量的地址
printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c);
}
void func(struct data *parm) // 通过形参 parm能改变实参 arg吗?
{
parm->a=18; parm->b=5; parm->c=parm->a*parm->b;
printf("parm->a=%d parm->b=%d parm->c=%d\n",parm->a,parm->b,parm->c);
printf("Return...\n");
}
arg
a,18
b,5
c,90
(main)
,27
,3
,30
i例 用 结构体指针变量(变量地址) 作函数参数
arga,27
b,3
c,30
( ain)
(func)
parm****
18
b,5
c 9
共用体
构造数据类型,也叫 联合体
用途:使几个不同类型的变量共占一段内存 (相互覆盖 )
– 共用体类型定义定义形式:
union 共用体名
{
类型标识符 成员名;
类型标识符 成员名 ;
…………….
};例 union data
{
int i;
char ch;
float f;
}; f
ch
i 类型定义 不分配内存最终占用 4个字节形式一,
union data
{ int i;
char ch;
float f;
}a,b;
形式二,( 最常用 )
union data
{ int i;
char ch;
float f;
};
union data a,b,c,*p,d[3];
形式三,( 无名 )
union
{ int i;
char ch;
float f;
}a,b,c;
共用体变量的定义
f
ch
i
f
ch
i
a b
共用体 变量定义 分配内存,
长度 = 最长成员 所占字节数共用体 变量任何时刻只有 一个成员 存在
共用体变量引用
引用方式:( 同结构体 )
引用规则
不能引用共用体变量,只能 引用其成员共用体指针名 ->成员名共用体变量名,成员名 (*共用体指针名 ).成员名
共用体变量中起作用的成员是 最后一次存放的成员
不能 在定义共用体变量时 初始化
可以用一个共用体变量为另一个变量赋值例 将一个整数按字节输出
01100001 01000001
低字节高字节
01000001
01100001
ch[0]
ch[1]
运行结果:
i = 24897
Ch0 = A,ch1 = a
main()
{ union int_char
{ int i;
char ch[2];
}x;
x.i = 24897;
printf("i=%d\n",x.i);
printf("ch0=%c,ch1=%c\n",
,x.ch[0],x.ch[1]);
}
枚举 类型
定义,将变量的值一一列举出来,变量的值只限于列举出来的值的范围之内。
枚举类型定义
enum weekday { sun,mon,tue,wed,thu,fri,sat } ;
enum weekday workday,week_end;
枚举变量定义
workday = mon;
week_end = sun;
enum { sun,mon,tue,wed,thu,fri,sat } workday,week_end;
枚举元素
sun = 0; mon = 1; (× )
说明,
1、在 C编译中,对枚举元素按照常量处理
2,枚举元素是有值的,按定义时的顺序使它们为
enum weekday { sun,mon,tue,wed,thu,fri,sat } ;
sun ~ sat 依次为,0,1,2,3,4,5,6
enum weekday { sun,mon = 8,tue,wed,thu = 100,fri,sat } ;
sun ~ sat 依次为,0,8,9,10,100,101,102
3、枚举值可以用来作判断比较。
if( workday == mon )…
4,一个整数不能直接赋给一个枚举变量。
enum weekday i;
i = 100; (× ) i = wed; (√) // 要用枚举元素来赋值原因:常量不能再被赋值参考源程序 7-6.c
#include <stdio.h>
void main()
{
enum mon{Jan=1,Feb,Mar,Apr,May} mon1,mon2,mon3;
enum mon *pm;
pm=&mon3;
mon1=Jan;
printf(“Input mon2:\”);
scanf(“%d”,&mon2);
mon3=mon1+2;
printf(“mon1=%d,mon2= %d,mon3=%d\n”,mon1,mon2,*pm);
}
用 typedef定义类型
功能,用自定义名字为 已有 数据类型命名
类型定义 简单形式,typedef type my_name;
类型定义语句关键字已有数据类型名用户定义的类型名说明,
1.typedef 没有创造 新数据类型
2.typedef 是定义类型,不能定义变量
3.typedef 与 define 不同
define typedef
预编译时处理 编译时处理简单字符置换 为已有类型命名
– typedef定义类型步骤
按定义变量方法先写出定义体 如 int i;
将变量名换成新类型名 如 int INTEGER;
最前面加 typedef 如 typedef int INTEGER;
用新类型名定义变量 如 INTEGER i,j;
类型定义可嵌套例 typedef struct club
{ char name[20];
int size;
int year;
}GROUP;
typedef GROUP *PG;
PG pclub;? GROUP *pclub;? struct club *pclub;
GROUP为结构体类型
PG为指向 GROUP的指针类型单向链表
存放数据元素的结点包括两个域
用途,数据域 (data)和 指针域 或 链域 (next)
– 单向链表表示( ^表示 NULL)
定义:
Struct Ai
{ int a;
struct Ai *next;
}
建立动态链表
– 创建结点,malloc 与 calloc 函数
malloc
函数原型,int *malloc(unsigned int size)
功能:在内存中动态分配 size个连续空间返值:正常,返回 空间地址 ; 出错,为 NULL
callcc
函数原型,int *calloc(unsigned n,unsigned
int size)
功能:在内存分配 N个连续长度为 size的空间返值,正常,返回 空间地址 ; 出错,为 NULL
节点链接到链表新节点链接到链表末尾
a1 a2 an
a1
NULL
NULLnew
pend
Head
② ①
链表的插入插入节点到头节点之前
an+1 NULL
new
NULLa1 a2 anHead
② ①
插入节点到链表中间
an+1 NULL
new
a1 NULLa2 anHead
② ①①
pins
链表的删除
BEGIN
IF (待删除节点为头节点 )
head=head->next;
ELSE
找到目标节点,并让 prev指向待删除节点的前导节点;
if (prve!=NULL)
{pdel=prev->next;
prev->next=pdel->next;
free(pdel);
}
else
print 没有找到要删除的节点;
ENDIF
return(head);
END
链表的删除
/*参考源程序 7-9*/
#include”Ex7-71.c”
#include <stdio.h>
Struct Ai *findprev(struct Ai *head,int a)/*从第 2个开始查找 */
{ struct Ai *prev,*pdel;
prev=head;
pdel=head->next;
while(pdel->a!=a && prev->next!=NULL)
{ prev=pdel;
pdel=pdel->next; }
if (pdel->next!=NULL)
return(prev);
else
return(NULL);}
链表的删除
/*参考源程序 7-9*/
Struct Ai *delete(struct Ai *head,int a)
{struct Ai *prev,*pdel;
if (head->a==a)
{head=head->next;
printf(“The first node is deleted.\n”);-
else
{if ((prev=findprev(head,a))!=NULL)
{pdel->next=pdel->next;
free(p);
printf(“Node(which number is %d)is deleted.\n”,a);-
else
printf(“Node(which number is %d)is not found.\n”,a);-
return(head);}
链表的删除
/*参考源程序 7-9*/
main()
{
struct Ai *head,*new,*p;
int n=0;
int a;
head=create();
printf(“Input data for the node to be deleted:\n”);
scanf(“%d”,&a);
head=delete(head,a);
printf(“Atfer the node is deleted:\n);
output(head);
}