《第8章常用数据表达.ppt》由会员分享,可在线阅读,更多相关《第8章常用数据表达.ppt(46页珍藏版)》请在三一办公上搜索。
1、1,第8章 常用数据表达,本章重点:常用的数据类型 宏的定义与应用 数组的定义和使用 指针的定义和使用 结构体的定义,枚举与定义类型 指针和数组 返回值为指针的函数 指向函数的指针,2,基本数据类型,构造类型数据是由基本类型数据按一定规则组成的,所以它们又被称为“导出类型”。,3,为什么要有数组这么一个数据类型?数组与其他基本的数据类型有什么区别?,8.1 数组,4,举例:一个班有30个学生,求这30个学生的总成绩和平均成绩。分析:如果按照我们以前的知识,涉及到30个学生的成绩,那么我们要定义30个变量来存储成绩信息。那么如果100个学生呢?是不是要定义100个变量?若有2万在校生,那么学籍管
2、理系统中是不是要定义2万个变量?-不可能!如何表示这么多学生的相关信息(例如成绩),就要引入数组的概念,数组是有序数据的集合。数组中的每一个元素都属于同一个数据类型。可以用一个统一的数组名和下标来惟一的确定数组中的元素,利用循环来统一完成各个元素的各种操作。,5,数组具有如下主要特点:(1)每个数组中的元素类型必须一致。(2)用不同的下标来区分数组的元素。(3)数组在内存中占有连续的存储单元,数组名表示数组在内存中的首地址。(4)数组和指针有着极密切的联系,可以通过指针移动来对数组元素进行操作。,6,#includeint main()int i,a10=1,2,3,4,5,6,7,8,9,1
3、0;/*定义一个整型数组,数组名为a,并给数组初始化*/for(i=0;i10;i+)printf(a%d=%-2d,i,ai);/*ai为数组的第i个元素*/printf(n);return 0;,例8.1 数组及数组元素的表示方法。,7,一、一维数组定义 1.定义形式:数据类型 数组名元素个数;如:int a5;不能写成int a(5);,8.1.1 一维数组,2.注意:数组名由用户定义,规则与变量名相同,元素个数为常量表达式而不能是变量表达式。如:int n=5;int an;数组的下标从0开始。如:a10下标是从09,而不是1-10。下标可以是整型常量或整型常量表达式 和其他变量一样,
4、数组也必须先定义后使用。,8,二、一维数组的引用、初始化与赋值C语言规定不能一次引用整个数组,引用时只能对逐个元素进行引用。(1)一维数组引用:引用形式:数组名下标注意:对下标的使用不要超过下标的最大值。尽管超过最大值时不出现编译错误。但是运行的时候会出现杂乱的结果。例如:a0=8;a2=0;a3=2*a2;,9,(2)一维数组赋值如何给一维数组赋值呢?可以有三种方法:数组的初始化 程序中赋值 键盘中读入数组的初始化 在定义数组时对数组元素可赋以初值。例如:static int a10=0,1,2,3,4,5,6,7,8,9;初始化时可以只对一部分元素赋初值。例如:int a10=0,1,2,
5、3,4;如果想使一个数组的元素值全部为0.例如:static int a10=0;在对全部数组元素赋初值时,可以不指定数组长度。例如:int a=1,0,3,5,7;,10,程序中给数组的元素赋值。例8.2 程序中给数组的元素赋值,并输出数组元素的值。#include int main()int s10=1,2,3,4,5,6,7,8,9,10;/*定义数组s,并初始化*/int i=2,a3;/*定义数组a*/a0=si;/*为数组元素a0赋值*/a1=s2+i;a2=s2*i+3;printf(a0=%d a1=%d a2=%dn,a0,a1,a2);return 0;,程序执行结果:,1
6、1,程序运行时从键盘输入,例8.3程序运行时从键盘输入,给数组的元素赋值,最后输出数组元素的值。#includevoid main()int i,a10;printf(请输入10个整型数,以空格隔开n);for(i=0;i10;i+)/*输入10个数,分别赋予10个元素*/scanf(%d,12,C语言本身没有字符串类型,字符串的存储完全依赖于字符数组,但字符数组又不等于字符串。虽然C语言中没有字符串数据类型,但却允许使用字符串常量。在C语言中,字符串是借助于字符型一维数组来存放的,以字符0作为字符串结束标志,它的ASCII代码值为0,0占用存储空间、不输出,也不计入串的实际长度。用字符数租存
7、放字符串。,8.1.2 字符数组,13,char c10;c0=I;c1=;c2=a;c3=m;c4=;c5=h;6=a;c7=p;c8=p;c9=y;,字符数组的定义字符数组的定义方法与普通的数组的定义方法类似。,a0 a1 a2 a3 a4 a5 a6 a7 a8 a9,14,字符数组的输入输出,有下列方法:(1)逐个字符输入输出。用格式符%c 输入或输出一个字符。(2)将整个字符串一次输入或输出。用格式符“%s”,对字符串进行输入输出。(3)用gets()输入字符串,用puts()输出字符串。,15,例8.4 利用字符数组,在终端中输出字符串“I Love China!”。分析:初始化数
8、组string,在初始化时直接用字符串常量,给字符数组string赋值。,#includeint main()char string=“I Love China!”;/*定义数组并初始化*/printf(“%sn”,string);/*字符串输出*/return 0;,程序执行结果:,16,例8.5 输入一行字符,统计其中字母、数字、空格和其它字符的个数,并输出结果。,分析:用函数gets()输入字符串,字符个数小于等于80(因为数组长度为80)。用gets()函数输入字符,可以输入空格,若用scanf()函数输入字符,遇到空格时系统认为字符串结束。设整型变量letter,digit,spac
9、e,other分别存放字母、数字、空格和其他字符的个数,其初始值均为0。在循环中判断数组中的每个字符是字母(则letter+)?还是数字(则digit+)?还是空格(则space+)?还是其他字符(则other+)?,17,#includevoid main()char str80;int letter=0,digit=0,space=0,other=0,i,length=0;gets(str);/*输入若干字符*/for(i=0;stri!=0;i+)/*判断字符是什么*/if(stri=a,18,8.1.3 二维数组,在C语言中,可以把二维数组看作是一种特殊的一维数组。二维数组中元素的排列
10、顺序是:先按行存放,再按列存放,即在内存中先顺序存放第一行的元素,再存放第二行的元素。,19,一、二维数组的定义 定义格式:类型 数组名行数列数;(1)如:int a23;(2)在内存中,是按行存放的。(3)因为数组的存储是顺序的,所以,各个元素的存储顺序为:a00 a01 a02 a10 a11 a12,0行:a00 a01 a02,1行:a10 a11 a12,20,三、二维数组元素的初始化,1.按行给二维数组赋初值。如:int aa23=0,0,1,1,0,0;2.也可以把数值写在一块:int aa23=0,0,1,1,0,0则aa00=0 aa01=0 aa02=1aa10=1 aa1
11、1=0 aa12=0,二、二维数组元素的引用行号和列号都是从0开始的,并注意行号和列号不要超过数组定义的范围。,21,3.如果初始化值比数组元素少,则后面的元素值为0,如:int a45=1,2,0,1,3则各值为:1 2 0 0 0 0 0 0 0 0 0 1 3 0 0 0 0 0 0 0 4.可以对单个元素进行赋值:aa34=5;,22,5.如果对二维数组的所有元素都赋值,则数组的第一维可以省略。如:int m3=1,2,3,4,5,6,7,8,9;则默认的第一维的值是3 又如int m3=1,2,3,4,5,6,7;则默认的第一维的值也是3;其中m21=m22=0;,23,例8.6 二
12、维数组输入、输出的例子。,#includeint main()int i,j,a43;printf(请输入12个整型数,以空格隔开n);for(i=0;i4;i+)for(j=0;j3;j+)scanf(%d,24,例8.7 二维数组程序举例,对以下矩阵进行转置:2 3 4 1 5 9 135 6 7 8 2 6 7 1410 11 12 3 7 11 1513 14 15 16 4 8 12 16 说明:该矩阵是对称矩阵,主对角线上下元素可以直接交换。若是非对称矩阵,可以利用两个二维数组进行存储原矩阵和转置矩阵。,25,#includevoid main()int i,j,t;int a44
13、=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16;printf(矩阵转置前:n);for(i=0;i4;i+)/*输出矩阵*/for(j=0;j4;j+)printf(%3d,aij);printf(n);printf(n矩阵转置后:nn);for(i=0;i4;i+)/*矩阵转置*/for(j=0;j4;j+)if(i=j)t=aij;aij=aji;aji=t;/*交换元素*/for(i=0;i4;i+)/*输出矩阵*/for(j=0;j4;j+)printf(%3d,aij);printf(n);,26,8.3 指针,指针C语言的特色,指针用来存放内存地址,
14、也称为指针变量。利用指针可以存放变量的地址、数组的地址、函数的起始地址等,利用指针可以很方便地处理数组、字符串。计算机的内存是以字节为单位的连续存储空间,每一字节单元都有一个编号,该编号被称为地址,这个地址就像房间号一样。在程序中定义的变量,在内存中都代表某一地址。,27,8.3.1 指针变量的定义与赋值,(一)指针变量的定义一般形式:类型名*指针变量名;例如:int x,*p1,*p2;,标志,命名规则同变量名,(二)指针变量的赋值 可以初始化:类型名*指针变量名=初值表达式;例如:int*px=,28,#includeint main()int x;int*p;/*定义一个指针变量p*/p
15、=,例8.8 从键盘输入一个数,赋给一个普通变量,利用指针变量,输出普通变量的值。,指针运算符,29,例8.9 指针变量的定义与相关运算示例。#includevoid main()int n=12,*pn;/*定义一个指向int型数据的指针变量pn*/float f=3.14,*pf;/*定义一个指向float型数据的指针变量pf*/char ch=p,*pc;/*定义一个指向char型数据的指针变量pc*/pi=,程序运行结果:n=12,*pn=12f=3.14,*pf=3.14ch=p,*pc=p,30,存取变量x值的方式有两种:(1)直接访问直接利用变量的地址进行存取 scanf(“%d
16、”,/*输出*/,31,8.3.2 指针变量的运算,1.取地址运算()取地址运算的格式:变量注意:指针变量只能存放指针(地址),且只能是相同类型变量的地址。2.指针运算符(*)也称间接访问运算符。用“*”可以访问指针变量所指向的变量的值。例如:printf(“n=%d,*pi=%dn”,n,*pi);注意:指针标识符和指针运算符的区别。在定义指针变量时出现的指针变量名前的“*”是一个标志,而在其余场合出现的“*”是运算符。,32,例8.10 使用指针变量输入2个整数,按升序(从小到大排序)输出。#includevoid main()int n1,n2;int*p1=,程序执行结果:输入第一个数
17、:8输入第二个数:2 min=2,max=8,33,4.指针运算(1)赋值运算 例如:int n,*p1,*p2;p1=是指p1指向下一个整型变量(3)在一定条件下,两个指针可以相减 当两个指针指向同一数组时,两个指针变量值之差是指两个指针之间的元素个数。(4)在一定条件下,两个指针可以比较 当两个指针指向同一数组时,可以进行比较。指向前面元素的指针小于指向后面元素的指针。若两指针不指向同一数组,则两指针相减或比较均无意义。,将一变量的地址赋予指针变量,将一指针变量的值赋予另一指针变量,34,案例8.11 指针运算的实例。分析程序输出的结果。#includeint a=4,2,7,9,3,5;
18、/*定义全局数组a*/main()int*pa1,*pa2;pa1=,/*定义指针变量*/,/*指针变量赋值,使之指向数组*/,/*指针变量pa1加3并与pa2 比较是否相等*/,/*指针pa2-pa1*/,/*指针变量加1,指向后面一个元素*/,/*指针变量减1,指向前面一个元素*/,35,8.3.3 数组与指针,(一)指向数组的指针,数组的指针数组在内存中的起始地址数组元素的指针数组元素在内存中的起始地址。,1.指向数组的指针变量的定义 指向数组的指针变量的定义,与指向普通变量的指针变量的定义方法一样。例如:int array10,*pointer;pointerarray;/*或者poi
19、nter*/注意:数组名代表数组在内存中的起始地址(与第1个元素的地址相同),所以可以用数组名给指针变量赋值。,36,2.数组元素的引用 数组元素的引用,既可用下标法,也可用指针法。使用下标法,直观;而使用指针法,能使目标程序占用内存少、运行速度快。,int array10,*pointer=array;则:(1)pointer+i和array+i都是数组元素arrayi的地址。(2)*(pointer+i)和*(array+i)就是数组元素arrayi。(3)指向数组的指针变量,也可将其看作是数组名,因而可按下标法来使用。例如,pointeri 等价于*(pointer+i)注意:point
20、er+1指向数组的下一个元素,而不是简单地使指针变量pointer的值+1。,37,例8.12 使用指向数组的指针变量来引用数组元素。#includevoid main()int array10,*pointer,i;pointer=array;printf(Input 10 numbers:n);for(i=0;i10;i+)scanf(%d,pointer+i);/*用指针变量来输入数组元素的值*/printf(array:);for(i=0;i10;i+)printf(%d,*(pointer+i);/*用指针变量输出数组元素的值*/printf(n);,38,例8.13 改写例8.12
21、用指针输入输出数据。分析下列程序,判断是否有错,若有错,请找出错误原因,并改正。#includevoid main()int*p,i,a10;p=a;/*指针变量p指向数组a*/printf(Input 10 numbers:);for(i=0;i10;i+)scanf(%d,p+);printf(n);for(i=0;i10;i+,p+)printf(%d,*p);printf(n);,39,字符串在内存中的起始地址称为字符串的指针,可以定义一个字符指针变量指向一个字符串。(一)字符串的表示与引用 在语言中,既可以用字符数组存放字符串,也可用字符指针变量来指向字符串;引用时,既可以逐个字符引
22、用,也可以整体引用。,8.3.4 字符串与指针,40,1.逐个引用例8.14 使用字符指针变量指向和引用字符串。#includevoid main()char*string=I love Beijing.;for(;*string!=0;string+)printf(%c,*string);printf(n);,2.整体引用#includevoid main()char*string=I love Beijing.;printf(%sn,string);,41,3.字符指针变量与字符数组之比较 虽然用字符指针变量和字符数组都能实现字符串的存储和处理,但二者是有区别的,不能混为一谈。(1)存储内
23、容不同 字符指针变量中存储的是字符串的首地址,而字符数组中存储的是字符串本身(数组的每个元素存放一个字符)。(2)赋值方式不同 对字符指针变量,可采用下面的赋值语句赋值:char*pointer;pointer=“This is a example.”;/*合法用法*/而字符数组,虽然可以在定义时初始化,但不能用赋值语句整体赋值。下面的用法是非法的:char array20;array=“This is a example.”;/*非法用法*/(3)指针变量的值是可以改变的,字符指针变量也不例外;而数组名代表数组的起始地址,是常量,而常量不能被改变。,42,1.概念 数组的每个元素都是一个指针
24、数据。指针数组比较适合用于指向多个字符串,使字符串处理更加方便、灵活。2.定义格式 数据类型*数组名指针元素个数;例如:int*p5;char*str7;,8.3.5 指针数组,43,#includeint main()char*name=Liu,Fang,Zhang;int i;for(i=0;i3;i+)if(namei0=Z)printf(%sn,namei);return 0;,例8.15 利用指针数组,根据代表姓名单词的首字母,输出这个姓名.,指针数组定义并初始化,44,8.3.6 数组指针,数组指针用于指向二维数组。数组指针变量定义的一般形式为:类型说明符(*指针变量名)下标;例如
25、:int a23,(*p)3;p=a;用*(pi+j)、*(*(p+i)+j)表示数组元素aij,45,例8.16 利用数组指针,输出一个二维数组。,#includeint main()int a35=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;int i,j,(*p)5;p=a;for(i=0;i3;i+)for(j=0;j5;j+)printf(%dt,*(*(p+i)+j);printf(n);return 0;,46,作业与实验任务,教材P122:一(先完成其中数组的题目,指针的题目以后再做)二(1,2,3)上机完成实验指导书P76:1,2,P85:4 了解并掌握一维数组 P89:五(1),(2),(3),