740 likes | 892 Views
第七章 数组. 信息管理系. 第七章 数组. 1 、概述. 2 、一维数组的定义和引用. 3 、二维数组的定义和引用. 4 、字符数组. 引 言. 前面我们学习了 C 语言中的基本类型: 整型: int long unsigned int 实型: float double 字符型: char 这些基本类型可以用来存储处理一些单个的数据。如一个整数可以定义一个整型变量来存储。.
E N D
第七章 数组 信息管理系
第七章 数组 1、概述 2、一维数组的定义和引用 3、二维数组的定义和引用 4、字符数组
引 言 前面我们学习了C语言中的基本类型: 整型:int long unsigned int 实型:float double 字符型:char 这些基本类型可以用来存储处理一些单个的数据。如一个整数可以定义一个整型变量来存储。 除基本类型之外,C语言还提供了构造类型的数据,它们有:数组类型、结构体类型、共用体类型。构造类型数据是由基本类型数据按一定规则组成的,因此也可以称之为“导出类型”。
引 言 • 在日常生活中,往往需要对一组相同类型的数据进行处理,这时,需要很多相同类型的变量来存放这一组数据,为了方便起见,C语言引入了数组来实现这种问题。 • 数组实际上是多个相同类型变量的有序排列。为了便于描述和处理,多个变量采用相同的名称,不同的下标来表示,并且用下标的个数来表示数组的维数。 • 数组中的数据称为元素,用统一的数组名和下标来唯一地确定数组中的元素。
一维数组的定义(1) 一、定义方式: 类型说明符数组名 [ 常量表达式]; 例如: inta [ 10 ]; 则定义了一个名为a的数组,可以存放10个整数。定义了数组后,程序运行时,系统自动为数组开辟10个连续的大小为两个字节的存储空间,每个空间可存放一个整数。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 二、说明: (1)数组名定名规则和变量名相同,遵循标识符定名规则。 (2)数组名后是用方括弧括起来的常量表达式,不能用圆括 弧。 下面的用法是错误的: int a(10);
一维数组的定义(2) (3)常量表达式表示元素的个数,即数组长度。 例如: 在a[10]中,10表示a数组中有10个元素, 下标从0开始,这10个元素是:a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9] 注意:不能使用数组元素a[10]; (4)常量表达式可以包括常量和符号常量,不能包含变量。C不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。 更准确的说是 整型常量表达式 例如:下面这样定义数组是不行的: int n; scanf(“%d”,&n); int a[n];
一维数组元素的引用(1) 一、规则: (1)数组必须先定义,后使用。 (2)数组元素的使用形式为: 数组名 [ 下标] 下标可以是整型常量或整型表达式, 例如: a[0]=a[5]+a[1+3]-a[2*3]; 注意: C语言规定只能逐个引用数组元素, 不能一次引用整个数组.
一维数组元素的引用举例 例7.1 数组元素的引用 main() { int i ,a[10]; for( i =0; i<=9; i ++) a[ i ]= i ; for(i=0;i<=9;i++) printf(“%d,”,a[i]) ; } 程序使a[0]到a[9]的值为0~9, 然后按顺序输出 for(i=9;i>=0;i--) printf(“%d”,a[i]); 如果按逆序输出 运行结果: 0, 1, 2, 3, 4, 5, 6,7,8,9, 运行结果: 9,8,7,6,5,4,3,2,1,0,
一维数组的初始化(1) 1、在定义数组时对数组元素赋以初值。 例如:int a[10]={ 0,1,2,3,4,5,6,7,8,9 }; 初始化之后:a[0]=0,a[1]=1,……a[8]=8,a[9]=9。 2、可以只给一部分元素赋值. 例如:int a[10]={0,1,2,3,4}; 只给前五个元素赋值,后五个元素为0。 初始化之后:a[0]=0,a[1]=1,a[2]=2,a[3]=3,a[4]=4, a[5]=0,……,a[8]=0,a[9]=0。 3、如果想使一个数组中全部元素值为0, 可以写成 int a[10]={0}; 与 int a[10]={0*10};不同
一维数组的初始化(2) 4、对全部数组元素赋初值时,可以不指定数组长度。 例如:int a[]={1,2,3,4,5}; 上面的写法中,{ }中只有五个数,系统会据此自动定义数组的长度为5。 初始化之后:a[0]=1,a[1]=2,a[2]=3,a[4]=4,a[5]=5。 如果被定义的数组长度与提供初值的个数不同,则数组长度不能省略。 例如:想定义数组长度为10,就不能省略数组长度的定义。 而必须写成 int a[10]={ 1,2,3,4,5}; 只初始化前面5个元素,后5个元素为0。 不能写成 int a[ ]={1,2,3,4,5}; 也就是说,对部分元素赋初值时,长度不能省。
一维数组的初始化(3) 5、数组定义的长度不能小于初值的个数,否则作语法错误处理。 如:int a[3]={1,2,3,4,5}; 在编译时会出现语法错误!
一维数组的程序举例(1) 例1:输入一组数据,按相反的顺序输出。如输入1 2 3 4 5,输出5 4 3 2 1。 例2:输入5个学生的成绩,计算平均分。 例3:将10个字符放到数组中,求数组中大写字母的个数。 例4:已知有一组字符共10个,查看这些字符中是否含有字符a,如果有,找出它在这个字符组中的位置,如果没有,输出提示信息。
一维数组的程序举例(2) 例5:将一组数放到数组a中,在指定位置插入一个数。 4 4 5 7 9 11 例6:将一组数放到数组a中,删除指定位置的数。 7 9 11 13
一维数组的程序举例(2) 例7:将数据中的数据倒置存放。如:
一维数组的应用练习(1) 1、已有一个数组中的数据按由大到存小放,输入一个数,将它插入到数组合适的位置中,使数组中数据仍有序。 2、统计一个字符数组中数字字符、英文字母的个数。
用数组来处理Fibonacci数列问题 (见教材124页) 1 1 2 3 5 8 13 21 34 55 89
一维数组的程序举例(3) 例 7.2 用数组来处理Fibonacci数列问题。(见教材124页) 运行结果: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 程序如下: main( ) { int i; int f[20]={1,1}; for(i=2,i<20;i++) f [ i ]=f [ i -1]+f [ i -2]; for(i=0,i<20;i++) { if( i %5= =0) printf(“\n”);/*控制换行,每行输出五个数*/ printf(“%12d”,f [ i ]); } }
例(2) 输入10个数并从中找出最大者. main( ) { int a[10] ,i , j , max ; printf( “ input 10 numbers: \n ” ) ; for( i = 0 ; i < 10 ; i + + ) scanf( “ %d ” , & a [ i ] ) ; printf( “ \n ” ) ; max = a [ 0 ] ; for(i = 1 ; i < 10 ; i + + ) { if ( max < a [ i ] ) max = a [ i ] ; } printf(“\nmax=%d”,max); }
一维数组的程序举例(3.1) 例 7.3 用起泡法对n个数排序(由小到大)。(教材124页) 起泡法的思路是:将相邻两个数比较,将小的调到前头。 具体参见课本: 例如:对一个这样的序列排序:9,8,5,4,2,0(一共有6个数) (1) 98 5 4 2 0 /*9>8,交换*/ (2) 8 9 5 4 2 0 /*9>5,交换*/ (3) 85 9 4 2 0 /*9>4,交换*/ (4) 8 5 4 9 2 0 /*9>2,交换*/ (5) 85 4 2 9 0/*9>0,交换*/ 8 5 4 2 0 9 /*第一轮结束*/ 那么第一轮进行了 n-1=6-1=5 次比较即循环了5次
一维数组的程序举例(3.2) 第二轮交换: (1) 85 4 2 0 9/*8>5,交换*/ (2) 5 8 4 2 0 9/*8>4,交换*/ (3) 54 8 2 0 9/*8>2交换*/ (4) 5 4 2 8 09/*8>0,交换*/ 54 2 0 89 /*第二轮结束*/ 那么第二轮进行了 n-2=6-2=4 次比较即循环了4次 总结:第 i 轮进行了n- i次比较即循环了n- i 次. 一共要n-1轮比较即外围循环n-1次
一维数组的程序举例(3.3) 算法的N-S结构流程图如下: 源程序如下: main(){int a[10], i,j,t; 输入n个数给a[0]到a[n-1] for(i=0;i<10;i++) scanf(“%d”,&a[i]); for j=1 to n-1 for(j=1;j<10;j++) for(i=0;i<10-j;j++) if(a[i]>a[i+1]) {t=a[i]; a[i]=a[i+1]; a[i+1]=t;} for i =0 to n-j-1 假 a[ i]>a[ i+1] 真 t=a[i]; a[ i]=a[i+1]; a[i+1]=t; for(i=0;i<10;i++) printf(“%d”,a[i]); } 输出a[0]到a[n]
【实验八】 实验名称:一维数组的应用 实验目的: 1、掌握一维数组的定义、赋值和输入输出的方法。 2、掌握一维数组的基本操作:运算、插入、删除、逆置、排序和查找等。 3、掌握与一维数组有关的算法(特别是排序算法)。 实验要求: 编写程序并上机调试运行。 1、有一组已按由小到大的顺序排好序的整数,编写程序,从键盘输入一个数,将这个数插入到这组数合适的位置,使这组数仍然有序。 2、编写程序,删除一组数中所有值为x的元素。 3、用选择法对10个整数排序。10个整数用scanf函数输入。
1、统计各年龄段的人数。20个年龄通过键盘输入到age数组中,要求把0至9岁年龄段的人数放在d[0]中,把10至19岁年龄段的人数放在d[1]中,把20至29岁年龄段的人数放在d[2]中,其余依此类推,把100岁(含100)以上年龄的人数都放在d[10]中。1、统计各年龄段的人数。20个年龄通过键盘输入到age数组中,要求把0至9岁年龄段的人数放在d[0]中,把10至19岁年龄段的人数放在d[1]中,把20至29岁年龄段的人数放在d[2]中,其余依此类推,把100岁(含100)以上年龄的人数都放在d[10]中。 2、删去一维数组中所有相同的数,使之只剩一个。数组中的数已按由小到大的顺序排列。 例如,一维数组中的数据是: 2 2 2 3 4 4 5 6 6 6 6 7 7 8 9 9 10 10 10。删除后数组中的内容应该是:2 3 4 5 6 7 8 9 10。 3、移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p(含p,p小于等于n-1)的数组元素平移到数组的最后。 4、将数组中下标为奇数、同时值也为奇数的元素删除。
二维数组的定义(1) 1、一般形式: 类型说明符数组名[常量表达式][常量表达式] 例如:int a[3][4]; 包含:a[0][0],a[0][1],a[0][2],a[0][3] a[1][0],a[1][1],a[1][2],a[1][3] a[2][0],a[2][1],a[2][2],a[2][3] 定义了一个3*4(3行4列)的数组. 注意: 不能写成 int a[3,4];
二维数组的定义(2) 可以把二维数组看作是 一种特殊的一维数组:它的元素又是一个一维数组. 例如:int a[3][4];/*定义了一个3*4(3行4列)的数组. */ 我们可以将a看成一个一维数组:a[0]、 a[1]、 a[2], 每个元素又是包含4个元素的一维数组。 a[0]---------a[0][0] a[0][1] a[0][2] a[0][3] a a[1]---------a[1][0] a[1][1] a[1][2] a[1][3] a[2]---------a[2][0] a[2][1] a[2][2] a[2][3]
二维数组的存放 2、存放顺序:按行存放,即在内存中先顺序存放第一行的元素,再存放第二行的元素。 int a[3][4]; a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]
二维数组的引用 1、数组元素的表示形式: 数组名[下标][下标] 例如:a[3][4] 区分在定义数组时用的a[3][4]和引用元素a[3][4] 下标可以是整型表达式 例如:a[2-1][2*2-1] 数组元素可以出现在表达式中,也可以被赋值。 例如:b[1][2]=a[2][3]/2; 2、注意:使用数组元素时,下标值应该在定义的数组大小的范围内。 不要出现这样的错误: 例如:int a[3][4]; a[3][4]=3;
二维数组的初始化(1) 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 1、分行给二维数组赋初值。 例如:int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 2、可以将所有数据写在一个花括弧内,按数组排列的顺 序对各元素赋初值。 例如:int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
二维数组的初始化(2) 1 0 0 0 5 0 0 0 9 0 0 0 1 0 0 0 0 6 0 0 0 0 11 0 1 0 0 0 5 6 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 11 0 3、可以对部分数据赋初值。 例如: int a[3][4]={{1},{5,6}}; 例如: int a[3][4]={{1},{5},{9}}; 例如: int a[3][4]={{1},{},{0,0,11}}; 例如: int a[3][4]={{1},{0,6},{0,0,11}};
二维数组的初始化(3) 1 2 3 4 5 6 7 8 9 10 11 12 0 0 3 0 0 0 0 0 0 10 0 0 4、如果对全部元素赋初值(即提供全部初始数据), 则定义数组时对第一维的长度可以不指定, 但第二维的长度不能省。 例如:int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; 等价于:int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12}; 如果定义时也可以只对部分元素赋初值而省略第一维的长度,但应该分行赋初值: 例如:int a[][4]={{0,0,3},{},{0,10}};
二维数组元素的应用举例(1) 1、已知有4个学生,每个学生有3门课的成绩,求每门课的平均成绩和每个学生的平均成绩。 2、求一个33整型矩阵的对角线元素之和。 3、求一个4 3整型矩阵中非0元素的个数。
1 2 3 0 • 4 5 6 0 • 7 8 9 0 4、已给如下矩阵: 编程实现:第四列的值为相应行上各元素的和,并输出该矩阵。 5、将一个二维数组的行、列互换,存到另一个二维数组中。如: 1 2 3 1 4 4 5 6 B= 2 5 3 6 A= 二维数组元素的应用练习(2)
【实验九】 实验名称:二维数组的应用 实验目的: 1、掌握二维数组的定义、赋值和输入输出的方法。 2、掌握二维数组的基本操作:运算、转置、取特殊元素等。 实验要求: 编写程序并上机调试运行。 1、求一个3阶方阵A和其转置矩阵的和。 2、求一个4阶方阵的周边元素的和 3、输出一个3行4列的矩阵的最大值及其所在的行号和列号。
例 7.4 有一个3*4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号. (见教材129页) max=a[0][0] main() { int i,j,row=0,colum=0,max; int a[3][4]={{1,2,3,4},{9,8,7,6}, {-10,10,-5,2}}; max=a[0][0]; for(i=0;i<=2;i++) for(j=0;j<=2;j++) if(a[i][j]>max) {max=a[i][j];row=i;colum=j;} printf(“%d,%d,%d”,max,row, colum); } for i=0 to 2 for j =0 to 3 假 a[i][j]>max 真 max=a[ i][j]; row=i; colum=j; 输出:max,row,colum
数 组 知 识 回 顾 为什么要引入数组? 数组如何定义? 如何对数组进行初始化? 如何引用数组元素? 引用数组元素时要注意哪些问题? 如何输入、输出一个数组? 如何在一维数组中插入、删除一个(一些)元素? 如何取出二维数组中的某些特殊元素?
数 组 的 定 义 一维数组: 类型 数组名[数组大小] 二维数组:类型 数组名[数组行数][数组列数] 若有:#define m 3 #define n 4 int i, j; 下列能够正确定义一维数组的语句是: int a[10]; int a[i]; int a[2.5]; int a[2*5]; int a[2+5]; int a[m]; int a[n]; 下列能够正确定义二维数组的是: int a[3][4]; int a[i][j]; int a[m][n]; int a[3*4]; int a[3+4]; int a[3,4]; 以下各组选项中,均能正确定义二维实型数组a的选项是( )。 A)float a[3][4]; float a[][4]; float a[3][]={{1},{0}}; C)float a[3][4]; float a[][4]={{0},{0}}; float a[][4]={{0},{0},{0}}; B)float a(3,4); float a[3][4]; float a[][]={{0};{0}}; D)float a[3][4]; float a[3][]; float a[][4]
数 组 的 初 始 化 一维数组:int a[5]={1,2,3,4,5}; int a[5]={1,2}; 二维数组:int a[2][3]={1,2,3,4,5,6}; int a[2][3]={{1,2,3},{4,5,6}}; 若有说明:int a[][4]={0,0};则下面正确的叙述是( )。 A)数组a的每个元素都可得到初值0 B)二维数组a的第一维大小为2 C) 数组a的第二维大小为2 D)只有元素a[0][0]和a[0][1]可得到初值0,其余元素均得不到初值0
数 组 元 素 的 引 用 引用数组元素: 数组名[下标] 数组名[行下标][列下标] • 17.若有说明:int a[3][4];则对a数组元素的非法引用是( )。 • A)a[0][2*1] • B)a[1][3] • C)a[4-2][0] • D)a[0][4] • int i=0,j=2; a[i][j] • 注意: • 1、引用数组元素与定义数组的区别: • 2、引用数组元素不要超出数组的范围。
1.若有以下定义: double w[10]; 则w数组元素下标的上限为______,下限为______。 2.在C语言中,二维数组元素在内存中的存放顺序是______。 3.若有定义:int a[3][4]={{1,2},{0},{4,6,8,10}}; 则初始化后,a[1][2]得到的初值是______,a[2][1]得到的初值是______。
数 组 的 基 本 操 作 数组的基本操作绝大部分都是由循环完成的。 例如:数组的输入和输出操作:一维数组用一重循环; 二维数组用二重循环实现。 熟悉其他操作: 如:一维数组中元素的插入、删除等操作; 二维数组的转置、算术运算、如何筛选出特殊元素等。 4.统计一个一维字符数组中26个大写字母的个数。(要求A的个数放在d[0]中,B的个数放在d[1]中,依次类推。) 5.统计一个二维字符数组中所有大写字母的个数。
字符数组定义(1) 用来存放字符数据的是字符数组. 字符数组中的一个元素存放一个字符. 1、定义方式:字符数组的定义方法与前面介绍的数值数 组相同。 例如: (1)char c[5]={‘c’,’h’,’i’,’n’,’a'}; c[0]=‘c’;c[1]=‘h‘;c[2]=‘i’;c[3]=‘n’;c[4]=‘a’; c[] c[] (2)char c[6]={“china”}; 或 char c[6]=“china” c[0]=‘c’;c[1]=‘h‘;c[2]=‘i’;c[3]=‘n’;c[4]=‘a’; c[5]=‘\0’; c[] 当数组中的全部初始化,定义时数组的长度可以省略, 注意不同的初始化方式会导致数组长度的不同
字符数组定义(2) 2.说明: (1)由于字符型和整型通用,也可以定义为int c[10]。 但这时每个数组元素占2个字节的内存单元。 char c[10];占1个字节 int c[10];占两个字节
字符数组定义(3) I a \0 \0 d \0 \0 \0 \0 \0 \0 I a \0 \0 d \0 \0 \0 \0 \0 \0 (2)字符数组也可以是二维或多维数组。 例如:char c[5][10];即为二维字符数组。 char a[3][4]={“Ia”,” d”}; char a[3][4]={{‘I’,’a’},{‘ ’,’d’}}; 当数组中各个串的内容被初始化, 定义时可以省略数组的第一维大小
字符数组的初始化(1) 1、字符数组允许在类型说明时作初始化赋值,逐个对 数组元素进行初始化。 例如: char c[10]= {’I’ , ’’,’a’,’m’,’’,’h’,’a’,’p’,’p’,’y’}; (1)初值个数等于数组元素长度时,依次赋值。 (2)初值个数大于数组元素长度时,做语法错误处理。 例如: char c[10]= {‘I’,’’,’a’,’m’,’’,’h’,’a’,’p’,’p’,’y’,’!’};
字符数组的初始化(2) (3)初值个数小于数组元素长度时,则后面的元素自动置 为空字符(也就是‘\0’)。 例如: char c[10]={`w`,` h `,`o`,` `, `a`, `m`, ` `,`I`}; 赋值后各元素的值为: 其中c[8] 、c[9]未赋值,由系统自动赋予\0值。 (4)当对全体元素赋初值时也可以省去长度说明。 例如: char c[ ]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`}; 这时C数组的长度自动定为9。
字符数组的引用(1) 1、输出一个字符串 例: 写出下面程序的运行结果。 main( ) { int i,j; char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}}; for(i=0;i<=1;i++) { for(j=0;j<=4;j++) printf("%c",a[i][j]); printf("\n"); } } 输出结果: BASIC dBASE
字符数组的引用(2) 2、输出一个钻石图形 例: 写出下面程序的运行结果。 main( ) { int i,j; char diamond[][5]={{’’,’’,’*’}, {’’,’*’, ’’,’*’}, {’*’,’’,’’,’*’}, {’*’,’*’,’’,’*’}, {’’,’’,’*’}}; for(i=0;i<5;i++) { for(j=0;j<5;j++) printf("%c",diamond[i][j]); printf("\n"); } } * * * * * * * *
字符串和字符串结束标志(1): 1.总领: (1)在C语言中没有专门的字符串变量,通常用一个 字符数组来存放一个字符串。 字符串总是以‘\0’作为串的结束符。 因此当把一个字符串存入一个数组时, 也把结束符‘\0’ 存入数组,并以此作为该字符串是否结束的标志。 有了‘\0’标志后,就不必再用字符数组的长度来判断字符 串的长度了。
字符串和字符串结束标志(1): (2)`\0`代表ASCII码为0的字符,从ASCII码表中可以到,ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不干。 用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。
字符串和字符串结束标志(2): C[0] C[1] C[2] C[3] C[4] C[5] C[6] C[7] C[8] C[9] C P r g r a m \0 2、字符数组的初始化: C语言允许用字符串的方式对数组作初始化赋值。 例如:char c[]={'c', ' ','p','r','o','g','r','a','m'}; 可写为: char c[]={"C program"}; 或去掉{ }写为:char c[]="C program"; 说明: (1)用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'\0'。 上面的数组c在内存中的实际存放情况为:C program\0。 ‘\0'是由C编译系统自动加上的。