投影4 省二级C等级考试基础考点3构造类型数据.docx
《投影4 省二级C等级考试基础考点3构造类型数据.docx》由会员分享,可在线阅读,更多相关《投影4 省二级C等级考试基础考点3构造类型数据.docx(17页珍藏版)》请在冰豆网上搜索。
投影4省二级C等级考试基础考点3构造类型数据
构造类型数据
“导出类型”
由基本类型按照一定规则组成:
数组、结构体、联合体
数组
数组是用得最多的构造类型数据,也是考得最多的数据类型。
数组是同类数据的有序集合,数组中的每一个元素都属于同一个数据类型,用一个统一的数组名和不同的下标来表示。
1.数组的命名、声明及初始化(*****)
1)数组的命名(****)
为一组相同类型的变量定义一个共同的名称,该名称即为数组名
数组名采用用户自定义的合法标识符
2)数组的声明(*****)
数组有一维数组和多维数组,一维数组带一个下标,二维数组带两个下标。
数组的声明也叫数组的定义,如同变量的定义一样,需要说明数组的类型及数组元素的个数。
(1)一维数组
一维数组的声明格式:
数据类型数组名[常量表达式];
1数据类型:
基本数据类型,如int、float、char、long、double等。
2数组名:
用户自定义标识符,与定义变量名一样。
数组名表示内存起始地址,是一个地址常量,其值不能改变。
3方括号[]:
为下标运算符,与数组名及常量表达式连为一体,不能缺省。
4常量表达式:
表示元素个数,也就是数组的长度
其值必须确定,不能为变量或不确定的值。
5分号“;”:
必须有,不能缺省。
例如:
inta[6];
(2)二维数组
二维数组的声明格式:
数据类型数组名[常量表达式][常量表达式];
1数据类型、数组名、方括号、分号的含义与一维数组相同。
2第一个常量表达式表示行数,第二个常量表达式表示列数,该数组共有行数×列数个元素。
例如:
floatb[3][4];
3)数组的初始化(*****)
在数组声明的同时对数组元素赋初值,称为数组的初始化。
(1)一维数组的初始化
①所有元素初始化
例如:
inta[5]={1,2,3,4,5};
1数组元素赋初值将值放在一对花括号中,值与值之间用逗号隔开。
2数组元素的初值是一个确定的值,不能为变量。
3只能给元素逐个赋值,不能给数组整体赋值。
4若为全部元素赋初值,可以不指定数组长度。
inta[]={1,2,3,4,5};
②部分元素初始化
例如:
inta[5]={1,2,3};
1数组的长度为5,数组有5个元素,只给数组的前3个赋了初值,其余的后2个没赋初值的元素值自动赋值为0。
2数组不初始化,其元素值为随机数。
(2)二维数组的初始化
二维数组的初始化方式有以下三种形式:
①所有元素初始化
按行分段赋值,例如:
inta[2][3]={{1,2,3},{4,5,6}};
按行连续赋值,例如:
inta[2][3]={1,2,3,4,5,6};
1上述两种初始化方式的结果是相同,初始化的6个元素值分别为:
a[0][0]=1、a[0][1]=2、a[0][2]=3、a[1][0]=4、a[1][1]=5、a[1][2]=6
2二维数组初始化时,按行分段赋值,一行放在一个花括号内,外面再加一个花括号,直观、清楚。
3二维数组是按行存储的,若缺省里面的花括号,按行连续赋值,系统会按照数组元素排列的顺序对各元素赋初值。
②分行进行部分元素初始化
例如:
inta[2][3]={{1,2},{3}};
1数组的长度为6,只初始化了3个元素,分别为第一行的前2个元素和第2行的1个元素,其余没有初始化的元素的值为0。
2此种初始化形式中内部的花括号不能缺省
若缺省为inta[2][3]={1,2,3};则初始化了二维数组的第一行的3个元素,第二行的3个元素没有初始化,值为0。
③缺省第一维行数的值进行初始化。
例如:
inta[][3]={1,2,3,4,5};
系统会根据数据总个数分配存储空间,一共5个数据,每行3个,可确定为两行,所以有6个元素,最后一个元素没有初始化,值为0。
inta[][3]={{1},{4,5}};
采用分行的方式进行初始化,系统根据花括号判断数组有2行,第一行的值为1,0,0,第二行的值为4,5,0。
1二维数组赋初值,可缺省第一维的长度,但是第二维的长度不能缺省。
2二维数组赋初值,内部的花括号是否可以缺省要根据情况决定,无把握时最好加上花括号。
2.数组的存储结构(***)
数组元素的下标是从0开始的,数组各元素在内存中是连续存放的。
对于二维数组,是按行存储的,就是说先存放第一行的元素,再存放第二行的元素,以此类推。
例如:
intb[2][3];
这是一个2行3列的二维数组,数组b的6个元素在内存中的存放顺序依次为:
b[0][0]、b[0][1]、b[0][2]、b[1][0]、b[1][1]、b[1][2]。
3.数组元素的引用(*****)
数组必须先定义,后使用。
1)一维数组元素的引用(*****)
访问某个一维数组元素的形式:
数组名[下标]
例如,若有声明inta[5];则数组a的5个元素分别为:
a[0]、a[1]、a[2]、a[3]、a[4]。
下标表示该元素在数组中的顺序号,对数组元素的使用与普通变量相同。
需要特别注意的是,不存在a[5]元素。
若使用了a[5],则发生数组下标越界错误,但系统并不提示出错,所以一定要小心。
1数组名为已经定义过的数组,下标可以是整型常量或整型变量或整型表达式,若为小数,系统自动取整。
2C语言中,数组下标从0开始。
3数组下标可以为表达式。
4每一个数组元素都可以作为一个普通变量来使用。
5C语言中,对数组的使用只能通过逐个使用下标变量完成,不能一次引用整个数组。
6数组名后面的方括号里的表达式在数组定义时表示数组的长度,在使用时表示数组元素的下标。
7数组的输入输出需要采用循环语句实现。
例如:
inta[5],i;
for(i=0;i<5;i++)scanf("%d",&a[i]);
for(i=0;i<5;i++)printf("%3d",a[i]);
2)二维数组元素的引用(*****)
访问每个二维数组元素的形式:
数组名[行下标][列下标]
例如,若有声明intb[2][3];则数组b的6个元素分别为:
b[0][0]、b[0][1]、b[0][2]、b[1][0]、b[1][1]、b[1][2]
二维数组的输入输出需要采用双重循环实现
外循环表示数组行下标的递增,内循环表示数组列下标的递增。
例如:
inta[3][4],i,j;
for(i=0;i<3;i++)
for(j=0;i<4;i++)
scanf("%d",&a[i][j]);
for(i=0;i<3;i++)
{for(j=0;i<4;i++)
printf("%3d",a[i][j]);
printf("\n");
}
外循环控制行号,内循环控制列号。
内循环每执行一次,输出一个元素
外循环每执行一次,输出一行元素。
输完一行换行,形成矩阵形式。
1二维数组元素有2个下标:
行下标和列下标,都是从0开始的。
2与一维数组一样,要注意下标越界的问题。
若有声明inta[3][4],则行下标最大为2,列下标最大为3,不存在a[3][4]这样的元素。
4.字符数组的使用(字符串的存储及基本操作)(*****)
C语言中无字符串变量,用字符数组处理字符串。
字符数组用来存放字符数据,字符数组中一个元素存放一个字符。
字符串和字符数组是等级考试必考的内容。
1)字符数组的声明(*****)
一维字符数组的声明与一维普通数组相同,只是数据类型为char,一般形式如下:
char数组名[常量表达式];
例如:
charc[10];
二维字符数组的声明形式如下:
char数组名[常量表达式][常量表达式];
例如:
charc[3][10];
2)字符数组的初始化(****)
字符数组的初始化方式有两种:
逐个字符赋初值
用字符串常量赋初值
(1)逐个字符赋初值
赋初值时将字符放在一对单引号中。
1一维字符数组的初始化
给数组元素全部赋初值:
charch[5]={'H','e','l','l','o'};
缺省数组的长度:
charch[]={'H','e','l','l','o'};
给数组元素部分赋初值:
charch[5]={'B','o','y'};
没有赋初值的元素的值为'\0',其对应的ASCII码值为0。
2二维字符数组初始化
chard[][5]={{'x','y','z'},{'a','b','c','d'},
{'A','B','C','D','E'},{'a','b','c','d'},{'x','y','z'}};
(2)用字符串常量赋初值
赋初值时将字符串放在一对双引号中。
1一维字符数组的初始化
给数组元素全部赋初值:
charch[6]={"Hello"};
自动添加结束标志'\0'
缺省数组长度:
charch[]={"Hello"};
数组长度为?
?
?
缺省花括号:
charch[5]="Boy";
'B','o','y','\0','\0'
2二维字符数组初始化
charfruit[][10]={"Apple","Orange","Grape","Pear","Peach"};
字符串数组。
3)字符数组的使用(*****)
字符数组的使用与普通字符数组相同。
字符数组的输入输出可以与普通字符相同,使用循环来实现单个元素的输入输出,也可以使用字符串专用的输入输出函数。
(1)逐个字符输入输出:
用循环和%c格式
main()
{charstr[5];inti;
for(i=0;i<5;i++)scanf("%c",&str[i]);
for(i=0;i<5;i++)printf("%c",str[i]);
}
(2)整个字符串输入输出:
用%s格式
main()
{charstr[20];
scanf("%s",str);
printf("%s",str);
}
1scanf函数用字符数组名,不要加“&”,因为数组名本身就表示地址。
2输入的字符串长度<数组长度,否则产生溢出。
3scanf函数输入时遇空格或回车结束,系统自动在字符串末尾加结束标志'\0'。
4printf函数用“%s”输出时遇结束标志'\0'结束输出。
若数组中有多个‘\0’时,遇第一个结束。
(3)字符串专用的输入输出函数
main()
{charstring[80];
gets(string);
puts(string);
}
1输入的字符串长度<数组长度,否则产生溢出。
2gets能输入空格,遇回车结束,系统自动在字符串末尾加结束标志'\0'。
3puts遇结束标志'\0'结束输出。
4)字符串处理函数(*****)
对字符串进行有关的操作需要使用专门的字符串处理函数进行。
如字符串复制函数、字符串连接函数、字符串比较函数、字符串长度函数等。
结构体变量和结构体数组
结构体与数组都是构造数据类型,不同的是:
数组将相同类型的数据集合在一起;
结构体是将不同类型的数据组合成一个整体。
1.结构体数据类型的定义(****)
结构体的定义分结构体类型定义和结构体变量定义。
因为结构体是自定义类型,首先要定义结构体类型,然后才能定义结构体变量。
1)结构体类型的定义
结构体类型的定义格式如下:
struct[结构体类型名]
{类型标识符1成员名1;
类型标识符2成员名2;
……
};
例如:
structstudent
{intnum;
charname[20];
charsex;
floatscore;
};
此处student是类型名,不是变量名。
该结构由4个成员组成,凡说明为此结构体类型的变量都由上述4个成员组成。
1struct是关键字,不能省略。
2结构体类型名为合法标识符,可缺省,缺省情况为无名结构体。
3成员类型可以是基本型或构造型。
4注意最后的大括号外有分号“;”号。
5结构体类型定义描述结构的组织形式,不分配内存,结构体类型名不能赋值、运算等操作。
而结构体变量在定义的时候分配内存,可以进行赋值、运算等操作。
2)用typedef定义类型(***)
typedef尽管在大纲中没有列出,但是在等级考试的试卷中经常有出现,应该看得懂。
typedef的功能:
用自定义名字为已有数据类型命名,相当于给已有的类型取别名。
类型定义简单形式:
typedeftypename;
typedef为类型定义语句关键字
type为已有数据类型名
name用户定义的类型名
最后加上分号。
例如:
typedefintINTEGER;
如果有类型说明:
INTEGERa,b,c;等价于inta,b,c;
1typedef没有创造新数据类型。
2typedef只是定义类型,不能定义变量。
3typedef与define不同
define在预编译时处理,进行简单字符置换,末尾没有分号。
typedef在编译时处理,为已有类型命名,末尾有分号。
2.结构体变量和结构体数组的声明(****)
结构体变量的声明就是结构体变量的定义。
结构体变量的定义有三种方式:
1)先定义结构体类型,再定义结构体变量(****)
结构体变量在结构体类型定义完了以后才能定义。
假设结构体类型名已定义,结构体变量的定义形式与普通变量的定义形式类似:
struct结构体类型名变量名表列;
例如,若有上面的类型定义,则可以采用如下的形式定义结构体变量和结构体数组:
structstudentpers,stu[3];
2)在定义结构体类型的同时定义结构体变量(****)
struct[结构体类型名]
{类型标识符1成员名1;
类型标识符2成员名2;
……
}变量名表列;
例如:
structstudent
{intnum;
charname[20];
charsex;
floatscore;
}pers,stu[3];
1student为结构体类型名,pers为结构体变量名,stu[3]为结构体数组名。
2将上例中的结构体类型名student省略,就是无名结构体。
如果定义的是无名结构体,则只能采用在定义结构体类型的同时定义结构体变量。
无名结构体只能定义变量一次,不提倡采用这种形式。
3结构体成员名与程序中变量名可相同,不会混淆。
4结构体可嵌套定义。
例如:
structdate
{intmonth;intday;intyear;};
structstudent
{intnum;
charname[20];
structdatebirthday;
}stu;
3)用typedef说明结构体类型(***)
因为结构体类型定义后其类型比较长,我们可以用关键字typedef来说明结构体类型。
structstudent
{intnum;
charname[20];
charsex;
floatscore;
};
typedefstructstudentSTU;
STUpers,stu[3];
此时,structstudent和STU是等价的,STU是structstudent类型的别名,使用更方便。
也可以直接用typedef说明结构体的新类型名。
以下的声明方式与上面的声明方式其含义是完全相同的:
typedefstructstudent
{intnum;
charname[20];
charsex;
floatscore;
}STU;
STUpers,stu[3];
还可以用符号常量来表示一个结构体类型:
#defineSTUstructstudent
在程序中,凡是“structstudent”的地方都可以写成“STU”。
3.结构体变量的初始化(****)
结构体变量的初始化有3种情况:
1)定义时赋初值(****)
structstudent
{intnum;
charname[20];
charsex;
floatscore;
}stu={112,"WangLin",'M',90.0};
如果是数组的话也可用同样的方法:
structstudent
{intnum;
charname[20];
}stu[3]={{110,"WangLin"},{111,"LiPing"},{112,"ZhangSan"}};
2)相同结构体变量之间整体赋值(***)
structstudent
{charname[20];
charsex;
intage;
}stu1={"WangLin",‘M’,19},sru2;
stu2=stu1;
对于结构体而言,若两个变量类型相同允许整体赋值,而数组是不允许的。
3)对结构体成员单个赋值(***)
结构体中的成员,可以作为普通变量使用,可以象普通变量一样给结构体中的成员逐个赋值。
4.结构体变量的引用
结构体变量是通过运算符“.”来引用的。
运算符“.”的优先级和结合性如下:
优先级:
1级,最高
结合方向:
自左向右。
结构体变量的引用规则:
不能整体引用,只能引用变量成员。
结构体变量的引用方式:
结构体变量名.成员名,例如:
stu1.score=85.5;
stu1.age++;
结构体数组的引用方式:
结构体数组名[下标].成员名,例如:
stu[1].age++;
结构体嵌套时逐级引用:
stu1.birthday.month=12;
结构数组的输入是否正确?
?
for(i=0;i<3;i++)
scanf("%d,%s,%f",&students[i].id,&students[i].name,&students[i].score);
联合体数据类型(*)
联合体也叫共用体,主要用途是使几个不同类型的变量共占一段内存。
联合体数据类型的定义与结构体相同,只是将结构体的关键字struct改为union。
例如:
uniondata
{inti;
charch;
floatf;
};
联合体变量声明的形式也与结构体相同。
联合体与结构体的最大区别就是它们的存储方式不同:
联合体变量中的各成员是共用一块存储空间,几个成员是相互覆盖的,任何时刻都只有一个成员起作用;
结构体变量中每个成员都占用自己的内存空间,变量的各成员是同时存在的。
一个联合体变量在内存中占用的空间为所有成员中占用内存最长的成员所占的字节数。
若有上面联合体类型定义,现在定义变量a属于该类型的联合体:
uniondataa;
则变量a在内存中占用的字节数为?
?
?
1不能引用共用体变量,只能引用其成员。
2共用体变量中起作用的成员是最后一次存放的成员。
3不能在定义共用体变量时初始化。
4可以用一个共用体变量为另一个变量赋值。
5结构体与联合体可相互嵌套,结构体中嵌套联合体,联合体中嵌套结构体。
以下程序的运行结果是______________。
#include
main()
{union{longa;
intb;
charc;
}m;
printf("%d\n",sizeof(m));
}
A)2B)4C)6D)8