版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
结构体、共同体与位运算第一节结构体类型概述第二节结构体数组概述第三节共用体第四节位运算第五节项目任务:利用结构体类型改写输入输出子模块第一节结构体类型概述在前面几章中,我们已经介绍了基本类型的变量,如整型、实型、字符型变量等,也介绍了一种构造类型的数据----数组,它的特点是数组中各元素的类型和长度都必须一致,以便于系统处理。但是只有这些数据类型是不够的。有时需要将不同类型的数据组合成一个有机的整体,以便于引用。这些组合在一个整体中的数据是相互联系的。例如,一个学生的姓名、性别、籍贯、学号、成绩等项目,这些项目都与一个学生相联系。但它们的数据类型却各不相同,如姓名、性别、籍贯、学号的数据类型可以为字符型数据,成绩为实型数据,如果将它们分别定义为互相独立的简单变量,难以反映它们之间的内在联系。应当把它们组织成一个组合项,在一个组合项中包含若干个类型不同的数据项,在C语言中就引入了一种数据类型----结构体类型。这种类型的变量可以拥有不同数据类型的成员。一、结构体类型的定义定义结构体类型的格式为:struct
<结构体类型名>{<成员类型1><成员名1>;<成员类型2><成员名2>;…<成员类型n><成员名n>;
};说明:(1)struct是定义结构体类型的关键字,不能省略。(2)结构体类型名由用户命名,命名规则与标识符命名规则相同。(3)花括号{}内的部分称为结构体。结构体是由若干结构成员组成的。每个结构成员有自己的名称和数据类型,<成员名>是用户自己定义的标识符,<成员类型>既可以是基本数据类型,也可以是已定义过的某种数据类型(如:数组类型、结构体类型等)。若几个结构成员具有相同的数据类型,可将它们定义在同一种成员类型之后,各成员名之间用逗号隔开。(4)结构体类型的定义应视为一个完整的语句,用一对花括号{}括起来。例如:定义一个学生信息的结构体类型,包括:学生学号、姓名、性别、年龄、地址和学生成绩。structstudent//定义学生信息结构体类型{intnum;;/*学生学号*/charname[20];/*姓名*/charsex;/*性别*/intage;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/};说明:(1)structstudent是用户自己定义的一个结构体类型,它和系统已经定义了的标准类型如int,char等一样可以用来作为定义变量的类型;(2)定义一个结构体类型并不分配内存,只有定义这个结构体类型的变量时,才分配内存。二、结构体类型变量的定义结构体类型定义之后只是说明了一个构造型数据类型,系统并不为其分配内存,也就无法存储数据,只有在程序中定义了结构体类型变量之后才能存储数据。说明结构体变量有以下几种方法:1、先定义结构体类型,再说明结构体变量。
例如:
struct
student/*定义学生信息结构体类型*/{intnum;;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/};
struct
student
student1;/*定义了1个结构体变量
student1*/2、在定义结构体类型的同时定义结构体变量。例如:
struct
student/*定义学生信息结构体类型*/{intnum;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}student1,student2;/*定义2个结构体变量student1,student2*/3、说明一个无名结构体类型,直接说明结构体变量。例如:
struct
/*定义学生信息结构体类型*/{intnum;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}student1,student2;/*定义2个结构体变量student1,student2*/
由于这种定义方法不定义结构体类型名,无法记录该结构体类型,所以只能用来声明结构体变量,而且以后也不能用它声明变量或函数等。三、结构体类型变量的初始化和引用(一)、结构体类型变量的初始化
所谓结构体变量的初始化是指在定义结构体变量的同时给结构体变量赋初值。其初始化的方式有两种:1、是用花括号{}括起来的若干成员值对结构体变量初始化;二是用同类型的变量对结构体变量初始化。例如:
struct
student/*定义学生信息结构体类型*/{intnum;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}
struct
student
student1={001","LiYan","female",18,”cd”,90.5};2、是用同类型的变量对结构体变量初始化。例如:struct
student
student2=student1;
上述语句是用同类型的变量student1对student2初始化,这种方式是将变量student1拷贝到student2中。(二)、结构体类型变量的引用
在定义了结构体变量以后,当然可以应用这个变量,但应遵循以下规则:对结构体变量的引用不能整体应用,只能应用结构体成员。可以使用结构成员操作符“.”(或称为点操作符)对其成员进行访问。使用结构体成员的格式为:<结构体变量>.<成员名>成员运算符的作用是引用结构体变量中的某个成员。点运算符的的优先级与下标运算符的优先级相同,是C语言中所有运算符优先级中最高的。例如:对于如下结构体:
struct
date/*定义日期信息结构体类型*/{int
year;int
month;int
day;}date1;要给结构体变量中的year赋值10,其引用的方式为:date1.year=10;【案例7-1】结构体类型变量的引用。分析:定义一个教师结构体类型,教师的数据包括职工号,姓名、性别和年龄。从键盘上输入每个教师的信息,然后输出结构体成员的数据。voidmain(){structteacher/*定义教师信息结构体类型*/{charnumber[12];charname[10];charsex[6];intage;}teacher1;printf("\n请输入职工号:");scanf("%s",teacher1.number);printf("请输入姓名:");scanf("%s",);printf("请输入性别:");scanf("%s",teacher1.sex);printf("请输入年龄:");scanf("%d",&teacher1.age);printf("\n职工号是:%s",teacher1.number);printf("\n姓名是:%s",);printf("\n性别是:%s",teacher1.sex);printf("\n年龄是:%d",teacher1.age);}【注意】不能将结构体变量作为一个整体进行输入和输出,只能通过引用其成员依次将数据进行输入和输出。第二节结构体数组概述一、结构体数组的定义一个结构体变量中可以存放一组数据(如一个学生的学号、姓名,成绩的),如果有20个学生的数据需要参与运算,显然应该使用数组,这就是结构体数组。结构体数组与以前介绍过的数值型数组的不同之处在于每个数组元素都是一个结构体类型的数据。结构体数组的使用与普通数组的使用一样,也是通过下标来访问数组元素的。结构体数组的定义方式和定义结构体变量相似,只需说明其为数组即可。例如:
struct
/*先定义学生信息结构体类型,再定义结构型数组*/{intnum;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}structstudentstu[3];以上代码定义了一个结构体数组stu,其元素为structstudent类型数据,数组有3个元素。也可以采取以下的方式来定义:
struct
/*先定义学生信息结构体类型,再定义结构型数组*/{intnum;/*学生学号*/char
name[20];/*姓名*/char
sex;/*性别*/int
age;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}stu[3];二、结构体数组的初始化(一)、结构体数组的初始化与其他类型的数组一样,在定义数组的同时,对其中的每一个元素进行初始化。
例如:structstudent{intnum;;/*学生学号*/charname[20];/*姓名*/charsex;/*性别*/intage;/*年龄*/charaddress[30];/*地址*/floatscore;/*分数*/}stu[2]
={{10000,"LiHua","female",21,”BJ”,88.6},{10002,"WenMing","male",22,”CD”,76.8};/*对结构体数组进行初始化*/(二)、结构体数组的使用结构体数组的使用即数组元素的使用,是通过下标变量实现的。对于结构体数组需要用下标变量引用结构体成员。引用方式:结构体数组名[下标].成员名。下面通过两个例子说明结构体数组的使用。【案例7-2】有3个候选人,每次输入一个得票的候选人的名字,对他们的得票结果进行统计,并将这些信息显示在屏幕上。分析:在主函数中定义一个字符数组,它代表被选人的姓名。在10次循环中每次先输入一个候选人的名字,然后把它与3个候选人人姓名相比,然后将相符合的候选人的票数加1,在输入和统计结束之后,将3人的名字和得票数输出。#include<stdio.h>#include<string.h>structperson/*定义候选人信息结构体类型*/{charname[10];intcount;}person1[3]={"YangLin",0,"ZhangHua",0,"LiPin",0};voidmain(){inti,j;charpersonname[10];for(i=0;i<6;i++){printf("\n请输入第%d个候选人姓名:\n",i+1);scanf("%s",personname);for(j=0;j<3;j++)if(strcmp(personname,person1[j].name)==0)/*将选票上的姓名与候选人的姓名进行比较*/person1[j].count++;/*将候选人的得票数加1*/}printf("------------统计结果--------------");printf("\n");for(i=0;i<3;i++)printf("%s:%d\n",person1[i].name,person1[i].count);}第三节共用体共用体类型也是用来描述类型不相同的数据,但与结构体类型不同,共用体数据成员存储时采用覆盖技术,共享(部分)存储空间。因此,共用体变量所占的存储空间不是各成员所需存储空间字节数的总和,而是共用体成员中需要空间最大的哪个成员所需的字节数。一、共用体类型的定义定义一个共用体的语法形式为:union共用体类型名{<成员类型1>
<成员名1>;<成员类型2>
<成员名2>;…<成员类型2>
<成员名n>;};其中union为系统的关键字,其作用是通知系统,目前定义了一个为名为“共用体类型名”的共用体。成员变量可以是任何类型的变量。例如:unionstudent{char
number[10];char
name[10];char
sex[8];int
age;};二、共用体变量的定义共用体变量的定义方式与结构体变量相同,也有三种方式,下面介绍常用的两种。1、先定义共用体类型,再定义共用体变量。例如:uniondata{inti;char
ch;floatf;};uniondataa,b,c;2、在定义共用体的同时定义变量。例如:uniondata{intI;char
ch;floatf;}a,b,c;共用体和结构体的比较:1、结构体变量所占内存长度是各成员所占的内存长度之和,每个成员分别占有其自己的内存单元。2、共用体变量所占的内存长度等于最长的成员所占的内存长度。例如:上面定义的共用体变量a,b,c占用4个字节,而不是各占2+1+4=7个字节。三、共用体变量的引用对共用体变量的赋值、使用都只能是对变量的成员进行。共用体变量的成员表示为:共用体变量名.成员名【案例7-3】利用共用体的特点分别取出int变量中高字节和低字节中的两个数。#include<stdio.h>main(){unionic{inti;charch[2];}x;x.i=24897;printf("i=%o\n",x.i);/*用8进制形式输出x.i*/printf("ch0=%o,ch1=%o\nch0=%c,ch1=%c\n",x.ch[0],x.ch[1],x.ch[0],x.ch[1]);}/*用8进制形式输出ch[0],ch[1],用字符形式输出ch[0],ch[1];*/【说明】本例程序中的共用体类型变量x中有两个成员,一个是整型变量n,一个是字符串ch,它们在内存中共占用2个字节。ch[0]存放的是整数的低字节01000001,ch[1]存放的是整数的高字节01100001。第四节位运算C语言兼具高级语言与低级语言的特性,因此适合编写系统软件,C语言具备低级语言的特性就在于它能直接对硬件进行操作,即位运算。所谓位运算是指按二进制位进行的运算。一、位逻辑运算(一)、按位与按位与的运算符“&”是双目运算符,参加运算的两个数据,按各对应的二进位进行“与”运算。运算规则:0&0=0;0&1=0;1&0=0;1&1=1;例如:有两个整数i=7,j=3,求i&j运算过程示意如下:i=0000000000000111j=0000000000000011i&j=0000000000000011因此,i&j的值得3(注意不是10)。用途:可以判断一个数据的某一位是否是1;可以保留一个数据中的某些位,屏蔽掉其它位。(二)、按位或按位或运算符为“|”,参加运算的两个对象,按相应的二进位中进行“或”运算。运算规则0|0=0;0|1=1;1|0=1;1|1=1。例如:有两个整数i=3,=5,求i|j运算过程示意如下:i=0000000000000011j=0000000000000101i&j=0000000000000111因此,i&j的值得7用途:可以将一个数据的某些位置为1,其它位不变。(三)、按位异或按位异或的运算符“∧”也称XOR运算符。运算规则:0∧0=0;0∧1=1;1∧0=1;1∧1=0;例如:有两个整数i=47,j=32,求i∧j运算过程示意如下:i=0000000000101101j=0000000000100101i&j=0000000000001101因此,i&j的值得13用途:(1)对某些位取反在异或运算中,使用1与某一位进行异或可以达到取反的功能。(2)保留某些位在异或运算中,使用0与某一位进行异或可以保持该位不变。(3)交换两个值,不用临时变量。假如a=3,b=4。想将a和b的值互换,可以用以下赋值语句实现:a=a∧b;b=b∧a;a=a∧b;(四)、按位取反按位取反的运算符为“~”。“~”是一个单目(元)运算符,用来对一个二进制数按位取反。运算规则:将0变1,1变0。例如:~9的结果为-10。运算过程示意如下:
i=0000000000001001~j=1111111111110110因此,~i的值得-10。二、移位运算(一)、左移位左移运算符为“<<”。用来将一个数的各二进位全部左移若干位,左边的二进制丢弃,右边补0。例如:a=a<<2;(左移二位)若a=15,a的二进制数为00001111,a左移2位后为00111100,其值为60。从上面我们可以看出左移1位相当于该数乘以2,左移2位相当于该数乘以4,但此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。左移比乘法运算速度快得多,因此,有些C编译程序自动将乘2的运算用左移一位来实现,将乘2n的幂运算处理为左移n位。(二)、右移位右移运算符为“>>”。用来将一个数的各二进位全部右移若干位,从右边移出去的低位部分被丢弃。对无符号数来讲,高位部分补0,对有符号数来讲,正数(符号位为0),则右移时左端补0,负数(符号位为1),则右移时左端是补0还是补1,取决于所用的计算机系统。例如:a=a>>2;(右移2位)。若a=016,a的二进制数为00001110,a右移2位为00000011由上述运算结果可以看出,在进行“右移运算时,如果移出去的低位部分不包含1,则右移1位相当于除以2,右移2位相当于除以4,右移3位相当于除以8,依次类推,因此,在实际应用中,经常利用”右移“运算来进行除以2的方幂的操作。【案例7-4】采用位运算中的移位运算,输出一个整数的二进制形式。分析:输出的整数num一般为2个字节的16位整型数据,那么可以把num中16个位的每一位看成是一个整数bit,其值当然只能为0或者为1。从高位开始,逐位判断num的每一位是0还是1,然后把该位的值赋给bit,并输出bit的值。此判断输出要循环16次。程序如下:/*输出一个整数的二进制形式*/#include<stdio.h>main(){intnum,bit,i;unsignedtest=0x8000;/*test用二进制表示是1000000000000000*/printf("请输入一个任意整数:");scanf("%d",&num);printf("%d整数的十六进制形式是:0x%x,二进制形式是:",num);for(i=1;i<=16;i++){bit=((num&test)==0)?0:1;/*逐位判断num的每一位是0还是1*/printf("%d",bit);test>>=1;/*将test右移1位*/}}第五节项目任务:利用结构体类型改写输入输出子模块【项目案例】利用结构体类型改写输入输出子模块分析:在本次项目任务中,我们将学生信息、成绩等数据存储在结构体类型变量中,并对它们进行处理。#defineN30#include<stdio.h>structscore/*定义包含学生信息的结构体类型
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论