第九章 结构、联合、枚举<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
(用户定义数据类型)
一、用户定义数据类型概述
? 用户定义数据类型的特点
类型标识符由用户自行定义
用户定义的数据类型既可以是基本类型的操作数(例:枚举),也可以是包含多个不同类型不同长度数据的集合(例:结构)。
? 用户可定义的数据类型
结构(struct): 构造类型
联合(union) : 构造类型
枚举(enum) : 基本类型
第一节 结构类型
一、结构类型的定义
? 定义格式
struct 类型名 ←类型标识符
{ 数据类型 成员名; ←成员的类型及名字
。。。
}; ←必须有分号
只定义了一种数据类型,不占用存储空间
例:
struct st 类型标识符是struct st
{ long id; \*学号*\
char name[10];
char sex[2]; \*m:男,f:女 *\
float mark[3]; \*成绩*\
};
(1) 类型名、成员名应遵守标识符命名规则
(2) 同一结构中不允许出现同名的成员
(3) 成员的数据类型可以是任何已定义的数据类型(基本类型、构造类型、指针类型)
(4) 当成员是指针型变量或数组时,数据类型可以是正在定义的结构类型自身。例:
struct st
{ long id;
char name[10];
char sex[2];
float mark[3];
struct st *next ;
};
(5) 成员没有存储类型,不能使用auto,register,
extern,static ( C++中可以使用static )
(6) 数据类型的定义在源程序中的位置决定了所定义的数据类型标识符的作用域
函数外:作用域为定义位置至文件结束
函数内:作用域为定义所在函数
(7) 大型程序通常将大量结构类型的定义放在头文件中。
(8) 编译系统的头文件中包含了一些结构类型定义
二、结构型变量的声明和初始化
? 先定义数据类型后声明变量
(1) 变量声明格式
存储类型 struct 类型名 变量名={初始值};
存储类型可缺省。
初始值可缺省。全局变量和静态局部变量无初始值时系统为全部成员置初值0。
例:
struct st s1, s2={1,”Tom”,”m”,70, 80};
变量s1所有成员初值不确定,s2的成员mark[2]为0
static struct st s3;
变量s3所有成员初值为0
说明:
(1) 变量名可以与该结构中某个成员同名
(2) 变量声明位置决定了结构变量的作用域
函数外:全局结构变量
函数内:局部结构变量
? 在定义数据类型的同时声明变量
(1) 方式一
struct st
{ long id;
char name[10], sex[2];
float mark[3];
}s1={1,”Tom”,”m”,70,80,90} , s2;
特点:
s1,s2的存储属性只能是缺省类型(全局变量为extern,局部变量为auto)。
s1,s2的作用域由其定义和声明位置确定
(2) 方式二
struct
{ long id;
char name[10];
char sex[2];
float mark[3];
} s1={1,”Tom”,”m”,70,80,90} , s2;
特点:
没有定义类型标识符,不能再声明新变量。
s1,s2的存储属性只能是缺省类。
s1,s2的作用域由其定义和声明位置确定
三、结构型变量的存储结构
一个结构变量的所有成员按出现顺序占用一片连续存储区域的不同单元。
struct
{ long id;
char name[10];
char sex[2];
float mark[3];
} s1={1,”Tom”,”m”,70,80,90} , s2;
变量s1占用的存储单元
=4 (id) +10 (name) + 2 (sex)+12 (mark) = 28 bytes
四、结构型变量的赋值与引用
? 类型相同时可直接引用结构型变量做赋值运算
例:
struct st s1, s2 ={1, ”Tom”,”m”};
FILE s3={0};
int s4=0;
s1=s2; (正确)
s1=s3; (错误)
Illegal structure operation in function main
s1=s4; (错误)
Illegal structure operation in function main
? 不能引用结构型变量做算术、关系、逻辑运算
struct st s1={1,”Tom”,”m”}, s2={0}, s3;
s1+s2 , s1++ , s1==s2 , s1 && s2 (错误)
? sizeof 运算可以得到一个结构变量的存储字节数
int y;
struct st s1;
y=sizeof(s1); 或 y= sizeof(struct st);
五、结构型变量成员的引用
? 引用格式
结构变量名.成员名
“.”为成员引用运算符,优先级最高。
例:
s2.id=s1.id; (正确)
s2.name = s1.name (错误)
strcpy ( s2.name , s1.name); (正确)
s2.name[0] = s1.name[0]; (正确)
判断s1是否等于s2的语句:
t =s1.id==s2.id&& strcmp(s1.name,s2.name)==0&&strcmp(s1.sex,s2.sex)==0&&s1.mark[0]==s2.mark[0] && s1.mark[1]==s2.mark[1]&&s1.mark[2]==s2.mark[2] ;
if (t)
{ 语句 }
六、结构型变量的输入输出
struct st s1;
scanf(“%ld%s%s%f%f%f”, &s1 );
(只有s1的第1个成员获得输入的数据)
scanf(“%d%s%s”, &s1.id, s1.name, s1.sex); (正确)
for(j=0;j<3;j++)
scanf(“%f”, &s1.mark[j]); (正确)
七、嵌套结构类型
? 嵌套结构类型的定义( 方式一)
struct date
{ int year,minth,day; };
struct st
{ long id;
char name[10], sex[2];
struct date birthday,registerday;
float mark[3];
};
? 嵌套结构类型的定义( 方式二)
struct st
{ long id;
char name[10];
char sex[2];
struct date
{ int year, minth, day;} birthday, registerday;
float mark[3];
};
? 嵌套结构型变量的声明、引用与输入输出
struct st s1={1,”Tom”,”f ”, {1980,2,12}, 70, 80, 90 };
static struct st s2;
s2.birthday={1982,2,12}; (错误)
s2.birthday.year =1982; (正确)
s2.birthday.month = 2; (正确)
s2.birthday.day = 12; (正确)
scanf(“%d”, &s2.birthday.year); (正确)
printf(“%d”, s2.birthday.year); (正确)
八、将局部结构型变量的值传给另一函数
struct comp { double x , y; };
struct comp cadd(struct comp c1, struct comp c2)
{ struct comp c;
c.x=c1.x+c2.x;
c.y=c1.y+c2.y;
return c;
}
main()
{ struct comp a1={1.2 , 2.3}, a2={2.3 , 3.4}, a3;
a3=capp(a1,a2);
printf(“%f,%f ”, a3.x, a3.y ) ;
}
九、结构型数组
? 结构型数组的声明和初始化
例1:
struct st s1[100]={{1,”Tom”,”m”}, {2,”Mary”,”f”}};
struct st s2[10][10];
例2:
struct st
{ long id;
char name[10], sex[2];
float mark[3];
}s1[100]= {{1,”Tom”,”m”}}, s2[10][10];
? 结构型数组元素的赋值和引用
(1) 直接引用数组元素(仅限于赋值操作)
例: for(i=0;i<100;i++)
s2=s1;
只有当两个数组的数据类型完全相同时才是合法的
(2) 直接引用数组元素的成员
例: for(i=0;i<100;i++)
{ s2.id=s1.id;
for(j=0;j<3;j++)
s2.mark[j]=s1.mark[j];
}
? 结构型数组的输入输出
例:
for(i=0;i<100;i++)
{ scanf(“%d%s”, &s2.id, s2.name);
for(j=0;j<3;j++) scanf(“%f”, &s2.mark[j]);
}
输出函数调用类似
? Tc2.0系统的特殊处理
struct
{ long id;
float sum;
}s[100];
for(i=0;i<100;i++)
{ scanf("%f ", &s.sum); }
以上程序段运行时若显示如下信息并终止程序运行:
scanf : floating point formats not linked
Abnormal program termination
解决方法:
float y;
for(i=0;i<100;i++)
{ scanf("%f",&y); s.sum=y; }
? 将局部结构型数组的指针传给另一函数
void f (struct st x[ ] , int n)
形式参数声明struct st x[ ] 等同于 struct st *x
{ int i,j;
for(i=0;i<n;i++)
{ scanf(“%ld%s%s”, &x.id, x.name, x.sex);
for(j=0;j<3;j++) scanf(“%f”, &x.mark[j]);
}
}
键盘输入:1 mary f 88 77 90 . . .
main()
{ struct st s1[10], s2[100];
f (s1,10); 或 f (&s1[0],10);
f (s2+10 , 90 ); 或 f( &s2[10] , 90);
}
? 嵌套的结构型数组
例:
struct date{ int year,month,day;};
struct st
{ long id;
char name[10], sex[2];
struct date date[2]; /*入学日期,毕业日期*/
}s[100];
for(i=0;i<100;i++)
{ s.date[0].year=2003; s.date[1].year=2007; }
第二节 联合类型
一、联合类型与结构类型的不同点
定义数据类型时使用的类型说明符不同
变量的存储结构不同
声明变量时初始值的个数不同
二、联合类型的定义
? 定义格式
union 类型名
{ 数据类型 成员名;
。。。
} ;
例:
union data
{ int i;
char ch[2];
float f;
};
二、联合型变量的声明和初始化
? 声明格式
存储类型 union 类型名 变量名=初始值;
可缺省:存储类型,初始值
若有初始值,只能有一个初值,该值的类型应与该联合类型中某个成员的类型相同。
例:
union data u1, u2 =32767;
static union data u3, u4[100];
三、联合型变量的存储结构
一个联合型变量的所有成员共用一块存储区域,该存储区域的字节数等于占用存储单元最多的成员所需要的字节数。
union data
{ int i;
char ch[2];
float f;
}u={32767};
四、联合型变量成员的赋值与引用
? 引用格式(与结构变量相同)
变量名.成员名
例:
u.i=0x4241;
printf(“%c,%c”, u.ch[0], u.ch[1]);
输出:A , B
五、嵌入在结构中的联合型变量
struct date
{ int year,month,day; };
union employeedate
{ long worked_days;
struct date last_day;
};
struct employee
{ long id;
char name[10];
union empdate date;
} staff [100];
staff[0].id=1;
strcmp(staff[0].name,”Tom”);
staff[0].date.worked_days=1000; 在职雇员
staff[1].id=2;
strcmp(staff[1].name,”Mary”);
staff[1].date.last_day.year=2004; 离职雇员
staff[1].date.last_day.month=4;
staff[1].date.last_day.day=4;
第四节 枚举类型
一、枚举类型的特点
? 类型的值是整数
(整数型:int, char, 枚举)
? 与int/char的不同之处
int /char: 没有限定可用值的范围,只有可表示值的范围。
枚举:限定了可用值的范围。
? 枚举类型可用值范围的每个整数均以符号常量形式定义。
二 、枚举类型的定义
? 定义格式
enum 类型名
{ 枚举常量表 };
例:
enum color { RED, GREEN, BLUE };
类型标识符 枚举常量表
枚举常量表中出现的常量等同于符号常量的作用
? 定义枚举常量所代表的整数值的几种方式
(1) 所有枚举常量使用缺省值
enum color{ RED, GREEN, BLUE };
RED 代表0,GREEN 代表1,BLUE 代表2
(2) 为所有枚举常量指定特定的值
enum color { RED=2,GREEN=1, BLUE=0 };
(3) 部分枚举常量指定特定的值其它使用缺省值
enum weekday
{ SUN=7, MON=1,TUE,WED,THU, FRI, SAT } ;
TUE代表2,WED代表3,。。。SAT代表6
(4) 允许为多个枚举常量指定相同的值
enum color { RED=1, GREEN=1, BLUE };
三、声明和引用枚举变量
? 变量声明的三种形式
enum color c1, c[10];
enum color{RED,GREEN,BLUE } c1, c[10];
enum{RED,GREEN,BLUE } c1, c[10];
? 枚举变量赋值
用枚举常量表中给出的枚举常量给该类型枚举变量赋值
例:c1=RED; c[0]=BLUE; (正确)
c1=0; c[0]=3; (错误)
四、枚举变量输入输出
例:
scanf (“%d”, &c1 );
printf (“%d”, c1 );
直接输入输出的是枚举常量所代表的整型数,而不是枚举常量名。
五、使用枚举常量
通过定义枚举类型而定义一组符号常量。
例:在graphics.h中定义了代表16个颜色的符号常量
enum COLORS {
BLACK, /* dark colors */
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY, /* light colors */
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
调用设置前景颜色函数: setcolor(BLUE); 等同于 setcolor(1);
第五节 typedef
? typedef的功能
为已定义的数据类型定义一个新的类型说明符。
例1:
定义类型说明符:
typedef unsigned long int ULINT ;
typedef struct
{ long id; char name[10], sex[2]; } PERSON;
typedef enum { TRUE=1, FALSE=0 } BOOL;
应用类型说明符:
ULINT k,j;
PERSON S[100];
BOOL t;
例2:
定义类型说明符:
typedef int IARR1[10]; int [10]代表一维数组类型
typedef int IARR2[3][4]; int [3][4]代表二维数组类型
typedef int * IP; int * 代表指向int数据的指针类型
应用类型说明符:
IARR1 a,b; 声明 a,b为一维数组
IARR2 c,d; 声明c,d为二维数组
IP p1,p2; 声明p1,p2为指向int数据的指针变量
关闭
站长推荐
/2
文章评论(0条评论)
登录后参与讨论