第七章 结构体、共同体和枚举类型
7.1 结构体定义及应用 7.2 共同体定义及应用 7.3 枚举类型定义及应用
7.1结构体的定义及应用 当需要将不同类型数据组合在一起为一个整体来处理,构成新的数据类型时,C++提供了结构体类型。 7.1.1 结构体类型的定义 关键字struct 定义结构体类型 struct <结构体类型名> { <类型名> <变量名1> 《<类型名> <变量名2>…》 };
结构体类型定义 可由如下方法定义以上结构体类型: Struct student { char num[9]; char name[10]; char sex[3]; int age; float score; }; 结构体名 结构体类型名 成员列表 成员类型 成员名 ;不能忘
注意: 编译程序不为任何数据类型分配存储空间,只有定义了结构体类型的变量时,系统才为这种变量分配存储空间 定义结构体的成员时,不能指定成员的存储类型为auto,register,xetern
结构体类型变量定义 结构体是由用户自定义的数据类型,定义后,系统将其与int,char,float等基本数据类型同等看待。可以用这种类型定义变量。 结构体变量与其他类型变量一样,必需先定义后使用。 《存储类型》<结构体类型名><变量1>《<变量2>…》 《存储类型》struct <结构体类型名><变量1>《<变量2>…》
结构体的变量定义 1、先定义类型,然后定义变量: struct student { int id; char name[20]; char sex; int age; float Engl,Phys; }; struct student s1,s2; student ss[30]; 2、也可以在定义结构体类型的同时定义其变量: struct book { char name[80]; int code; char author[20]; }bk1,bks[50];
结构体的变量定义 3、省略结构体类型名,直接定义其变量: struct { int year; int month; int day; }d1,d2,d3; 这种定义方式只能在定义结构体类型时定义变量,在程序其他地方不能再定义该结构体类型变量。
嵌套定义 结构体可以嵌套定义,即一个结构体可以包含结构体变量成员 struct date { int year; int month; }; struct student { char num[8]; char name[10]; char sex; struct date birthday; float score; } student1,student2; student num name sex birthday score year month
结构体变量初始化 可以在定义结构体变量的同时对其初始化: book b1={“C++程序设计”,1700,”张江”}; studen s1={ 101,”Linli”,’M’,{1980,06,22},87,90,70,97}; 初始化数据必需注意类型与排列顺序与结构体类型定义的类型一致。结构体成员初始化数据合成一组。 编译器为每个结构体变量分配存储空间,大小为所有成员占用空间之和。
结构体变量的存放 例7.1 结构体的各成员在内存为依次连续存放 struct date { int year; int month; }; struct student int id; char name[10]; struct date birthday; char sex; } stu; 4字节 stu stu.id stu.name stu. sex 10字节 stu.birthday.year stu.birthday.month 1字节 例7.1
结构体变量及其成员的使用 对于结构体类型,必需通过其变量来使用。不能直接引用结构体变量,只能引用其成员。通过成员运算符 “.” 来引用。 结构体变量名.成员名 各成员与其同类型的普通变量用法相同 例如: cout<< b1.name<<b1.code<<b1.author<<”\n”; 同类型结构体变量可以相互赋值,结果相当于对应成员对应赋值; book b1={“C++程序设计”,1700,”谭浩强”},b2,b3; b2=b1; // 相当于: { strcpy(b2.name,b1.name); b2.code=b1.code; strcpy(b2.author,b1.author);}
使用 结构体变量不能整体输入输出,也不能整体赋值。只能根据其成员数据类型,对各成员分别输入输出或赋值。 book bk; bk={“C++程序设计”,1700,”谭浩强”};//错误,不能整体赋值 结构体类型变量可以作函数参数或返回值类型。形参为结构体类型时,函数调用仍属值调用,被调函数中对结构体变量的修改不能影响实参状态。 P122 例7.2
7.1.4 结构体数组 当数组元素是结构体类型时,数组称为结构体数组。结构体数组定义及使用与普通数组类似,可以在定义同时初始化,每个元素的初始化数据是一组数据。 例p123_extend 例3, 例4
void main(){ Person temp; for(int i=0;i<6;i++){ for(int j=0;j<6-i-1;j++) if(allone[j].salary>allone[j+1].salary) { temp = allone[j]; allone[j] = allone[j+1]; allone[j+1]=temp; } for( i=0 ;i<6;i++) // cout<< allone[i].name<<” “ << allone[i].id <<”“ <<allone[i].salary<<’\n’; #include <iostream.h> struct person{ char name[20]; unsigned long id; float salary; }; Person allone[6] = {{“jone”,12345,339.0}, {“david”,13916,449.0}, {“marit”,27519,311.0}, {“jasen”,42876,623.0} {“peter”,23987,400.0}, {“yoke”,12335,511.0}
结构体类型的静态成员 struct stu{ static int id; int eng; }; 当结构体类型中定义了静态成员时,则无论这种类型结构体定义了多少变量,编译器只为成员分配一个存储空间,所有变量共同使用该成员的空间。 struct stu{ static int id; int eng; }; int stu::id=50;//静态变量一定要有 //定义性说明和初始化 stu =s1;
void main() { s s2; cout<<”s1.id=”<<s1.id<<’\t’<< ”s2.id=”<<s2.id<<’\n’; s2.id = 200; cout<<”s1.id=”<<s1.id<<’\t’<< ”s2.id=”<<s2.id<<’\n’; return; }
共同体定义及应用 7.2.1 共同体的概念 有时需将几种不同类型变量存放到同一段内存单元中,都从同一起始地址开始存放,这就需要使用覆盖技术,几个变量互相覆盖。 使几个不同变量共占同一段内存的结构称为“共同体”类型的结构。 定义形式: union 共同体名 {成员表列: }变量表列; 定义形式与结构体类似,关键字用union。
union data {int i; char ch; float f; }a,b,c; 共同体变量定义和存储 或 union { int i; char ch; float f; }a,b,c; 或 union data { int i; char ch; float f; }; union data a,b,c; 结构体变量所占内存长度是各成员占的内存之和,若上面union为struct,则占4+1+4=9字节。共用体变量所占内存长度是最长的成员长度。上例中,float最长,故为4个字节。 用sizeof(union data)得到最长成员长度
1000地址 1000地址 整型 i 字符型ch 实型 f
共同体变量的引用 遵循先定义后引用原则,只有定义了共同体变量才能引用它。 不能引用共同体变量,只能引用变量中的成员。 对于上节定义的变量,可以是 a.i,b.ch, c.f 。 不能引用a cout<<a; 错 cout<< a.i; 对 cout<< a.f; 对
共同体变量类型数据的特点 1.虽然几种不同类型成员存放在同一段内存中,但某一时刻只能存放其中之一,不是同时存放几种,每一时刻只有一个成员起作用(不是同时起作用),互相覆盖。 2.某一时刻变量中起作用的成员是最后一次存放的成员,覆盖了先前存放的成员。如:a.i=1;a.ch=’a’;a.f=5.1;只有a.f有效,a.i,a.ch已无效。引用时应注意当前有效的是哪个成员。 3.共同体变量及其各个成员的地址是同一地址, &a=&a.i=&a.ch=&a.f
4.下列对共同体变量的操作是非法的: 变量名赋值, 定义变量时初始化 通过引用变量名取得成员值 共同体变量作函数参数 函数返回共同体类型值 a=1; 错 m=a; 错 union {int i ; char ch; }a={1,’a’}; 错,不能初始化。
union … struct … {……struct … ……}; union { …… int a[5]; }a,b; 5.共同体和结构体可以互相嵌套定义,数组可以是共用体成员,也可以定义共用体数组。 union … {……struct … ……}; union { …… int a[5]; }a,b; struct … {…… union }; }; {…… }a[4];
例 union entry {struct book {char author[20]; char title[40]; }book; 定义一个有关记录书籍、杂志文章方面信息的共用体 union entry {struct book {char author[20]; char title[40]; }book; struct article char journal[40]; }artic; }info;
共同体变量的用途 写系统软件时,处理符号表。如,某个单元内放一个常量,该常量根据不同情况可能是整型、实、字符或单、双精度等。 可以设置类型标志,依此标志决定按什么类型处理。
struct {…… union { int i; char ch; float f; double d; }data; int type; switch(a.type) {case 0: cout<<a.data.i ; break; case 1: cout<< a.data.ch; break; case 2: cout<< a.data.f; break; case 3: cout<< a.data.d; break; }
枚举类型定义及应用 如果一个变量只有几种可能的值,可以定义为枚举类型,定义时将值一一列出,变量的值只限于列举的范围,以关键字enum开头,例: enum weekday{ sun,mon,tue,wed,thu,fri,sat}; 上面定义了weekday 枚举类型,可用于定义变量, enum {sun,mon,tue,wed,thu,fri,sat} workday,weekend; { }中元素称为枚举元素或枚举常量,是由用户定义的标识符。
说明 说明: 1、C++编译时,枚举元素按常量处理,称枚举常量,不能对其赋值。 2、枚举元素作为常量是有值的,编译器按定义时顺序使它们值为0、1,2等 如有 workday=mon,则workday值为1,可以整数形式输出。 也可以由程序员在定义时指定枚举元素的值 enum weekday {sun=7,mon=1,tue,wed,thur,fri,sat};
3、枚举值可用来作判断比较 if(workday==mon)…… if(workday>sun)…… 按定义时的顺序比较 4、 一个整数不能直接赋给枚举变量,它们是不同类型,要进行强制类型转换 workday=(enum weekday)2; workday=tue; 整型表达式也可以转换类型后赋给枚举变量 workday=(enum weekday)(5-3)
枚举类型的优点 枚举类型的优点: 虽然可以用常数代表各枚举元素,但是用枚举元素更直观,便于理解。枚举变量的值限制于定义时列举的几个元素范围内,赋予另外的值会有错误信息,便于查错。 P132例7.6, 7.7