1、第七章第七章 数数 组组(The Array)掌握一维数组、二维数组的定义、掌握一维数组、二维数组的定义、初始化和引用。初始化和引用。掌握字符串和字符数组的概念及其掌握字符串和字符数组的概念及其处理函数。处理函数。掌握用数组进行编程的技术。掌握用数组进行编程的技术。先看一个例子:先看一个例子:例:给出给出10个儿童的体重,要求计算平均体重个儿童的体重,要求计算平均体重 并打印出低于平均体重的数值。并打印出低于平均体重的数值。用变量来解决问题:main()int w1,w2,w3,w4,w5,w6,w7,w8,w9,w10;int t;scanf(%d%d%d%d%d%d%d%d%d%d,&w1
2、,&w2,&w3,w4,&w5,&w6,&w7,&w8,&w9,&w10);t=(w1+w2+w3+w4+w5+w6+w7+w8+w9+w10)/10;if(w1 t)printf(%dn,w1);if(w2 t)printf(%dn,w2);if(w3 t)printf(%dn,w3);if(w4 t)printf(%dn,w4);if(w5 t)printf(%dn,w5);if(w6 t)printf(%dn,w6);if(w7 t)printf(%dn,w7);if(w8 t)printf(%dn,w8);if(w9 t)printf(%dn,w9);if(w10 t)printf(%
3、dn,w10);用数组来解决问题:main()int w10;/*定义 1 个整型数组存放体重*/int t,i;for(i=0;i10;i+)scanf(%d,&wi);for(t=0;i=0;i10;i+)t=t+wi;t=t/10;for(i=0;i10;i+)if(wi t)printf(%dn,wi);数组及其相关概念数组及其相关概念 数组数组是一组有序的、类型相同的数据的集合,是一组有序的、类型相同的数据的集合,这些数据被称为这些数据被称为数组的元素数组的元素。数组下标数组下标 每个数组都有一个名字,称之为每个数组都有一个名字,称之为数组名数组名。为标识数组中的每个元素,需要对它们
4、进行编号为标识数组中的每个元素,需要对它们进行编号,称为,称为数组元素的下标数组元素的下标。下标使数组元素在数组中的位置(或排列顺序下标使数组元素在数组中的位置(或排列顺序)被唯一地确定下来;用数组名加上下标可以准)被唯一地确定下来;用数组名加上下标可以准确地访问数组中的某个元素。确地访问数组中的某个元素。如:如:w0代表数组代表数组w中的第一个元素中的第一个元素 w9代表数组代表数组w中的第十个元素中的第十个元素 注意:注意:C语言规定下标从语言规定下标从0开始。开始。说明说明:数组名代表数组的起始地址。数组名代表数组的起始地址。数组元素在内存中是连续存储的。数组元素在内存中是连续存储的。7
5、.1 一维数组的定义和引用(One Dimension Array)一、一维数组的定义一、一维数组的定义定义一维数组的一般方式:定义一维数组的一般方式:类型说明符类型说明符 数组名数组名常量表达式常量表达式;指明数组元素指明数组元素的数据类型的数据类型指明数组所含指明数组所含的元素个数的元素个数例如:例如:int a10;/*定义的整型数组定义的整型数组a含含10个元素个元素*/float b20;/*定义的实型数组定义的实型数组b含含20个元素个元素*/说明:说明:数组名的命名规则同变量名的命名规则一样;数组名的命名规则同变量名的命名规则一样;数组名后用方括号数组名后用方括号,不能用(),不
6、能用();常量表达式必须是常量表达式必须是大于大于0的整型常量表达式的整型常量表达式,不不 能包含变量能包含变量,即其大小不依赖运行过程中变量值即其大小不依赖运行过程中变量值;(4)定义数组时,数组的长度必须是确定的,定义数组时,数组的长度必须是确定的,C语言语言 不允许对数组的大小作动态定义,。不允许对数组的大小作动态定义,。int a(10);例如:例如:int n;int anchar name0;float weight10.3;float array-100;二、一维数组的初始化二、一维数组的初始化1.1.定义时初始化定义时初始化方法:将初值依次写在花括号方法:将初值依次写在花括号
7、内。内。如:如:int a5=2,4,6,8,10;存储形式:存储形式:存储单元说明:说明:如果定义一维数组时给出了全部元素的初值,如果定义一维数组时给出了全部元素的初值,则数组的下标允许省略。此时编译系统自动根据则数组的下标允许省略。此时编译系统自动根据初始化数据的个数来确定数组的长度。初始化数据的个数来确定数组的长度。如:如:int a=2,4,6,8,10;int a;初始化的数据个数初始化的数据个数允许少于数组的长度允许少于数组的长度,但,但不不能多于数组的长度能多于数组的长度。当初始化的数据个数(至。当初始化的数据个数(至少要有一个)少于数组的长度时,未初始化部少要有一个)少于数组的
8、长度时,未初始化部分将被编译系统自动用分将被编译系统自动用 0 赋值。赋值。如:如:int a5=2,4;相当于:相当于:a0=2,a1=4,a2=0,a3=0,a4=0 int a5=1,2,3,4,5,6,7,8;2.2.使用其它方法初始化使用其它方法初始化利用输入语句初始化main()char as26;int i;for(i=0;i26;i+)scanf(%c,&asi);.利用赋值语句初始化main()char as26,ch;for(ch=A;ch=Z;ch+)asch-A=ch;.三、一维数组的引用三、一维数组的引用 数组元素类似于单个变量,可以自由地存取。数组元素类似于单个变量
9、,可以自由地存取。但是,它与一般变量相比,有以下特殊之处:但是,它与一般变量相比,有以下特殊之处:数组元素是通过数组名加上该元素在数组中数组元素是通过数组名加上该元素在数组中的位置(即数组元素的下标)来访问的。的位置(即数组元素的下标)来访问的。表示形式:数组名下标 如:a3 其中,其中,下标可以是整型常量、整型变量或整下标可以是整型常量、整型变量或整型表达式型表达式。如:int a10;float i=3;ai=10;数组元素的下标是从数组元素的下标是从0开始的。开始的。如果定义了如果定义了an,则可使用,则可使用a0、a1、an-1。但是,不能使用。但是,不能使用an。C语言编译系统不检查
10、数组下标越界的错语言编译系统不检查数组下标越界的错误,在编程的时候要注意避免这种错误。误,在编程的时候要注意避免这种错误。如:int a2;scanf(“%d,%d”,&a1,&a2);数组元素的赋值是逐个元素进行的,不允数组元素的赋值是逐个元素进行的,不允许把一个数组作为一个整体赋给另一个数组。许把一个数组作为一个整体赋给另一个数组。除了数组初始化外,也不允许用在花括号中列除了数组初始化外,也不允许用在花括号中列表的方式对数组整体赋值。表的方式对数组整体赋值。例1:int a5=2,4,6,8,10 ,b5;b5=a5;例2:int a5;a5=2,4,6,8,10 ;数组名数组名a代表的是
11、数组代表的是数组a在内存中的首地址,在内存中的首地址,因此,可以用数组名因此,可以用数组名a来代表数组元素来代表数组元素a0的地址。的地址。等价于等价于scanf(“%d”,&a0);scanf(“%d”,a);四、一维数组应用举例四、一维数组应用举例例例1 1:从键盘上输入:从键盘上输入1010个实型数存入数组,然个实型数存入数组,然 后按输入顺序的逆序输出这后按输入顺序的逆序输出这1010个数。个数。main()float a10;int i;for(i=0;i=0;i-)printf(“%10.2f”,ai);例例7.27.2:用数组来处理求斐波纳契数列:用数组来处理求斐波纳契数列:1
12、1,1 1,2 2,3 3,5 5,88的前的前2020个数。个数。main()int f20=1,1;for(i=2;i20;i+)/*f2是数组第3个元素*/fi=fi-2+fi-1;for(i=0;i20;i+)printf(“%10d”,fi);if(i%2=0)printf(“n”);/*每行打印2个数*/数学表示:数学表示:f(0)=f(1)=1,f(n)=f(n-2)+f(n-1)例例7.37.3:用冒泡法对:用冒泡法对n=6n=6个数排序(由小到大)。个数排序(由小到大)。冒泡法的思路是:冒泡法的思路是:将相邻两个数比较,将小的将相邻两个数比较,将小的 调到前头。调到前头。9
13、8 8 8 8 8 8 9 5 5 5 5 5 5 9 4 4 4 4 4 4 9 2 2 2 2 2 2 9 0 0 0 0 0 0 9 第一轮排序,比较了第一轮排序,比较了5次次,获得第一次结果,获得第一次结果。轮数 剩数 比较次数 j=n-j+1 n-11n-1 1 6 5 2 5 4 3 4 3 4 3 2 5 2 1 main()int a7,i,j,t;printf(Input 6 numbers:n);for(i=1;i7;i+)scanf(%d,&ai);printf(n);for(j=1;j=5;j+)/*控制5轮排序 */for(i=1;iai+1)t=ai;ai=ai+1
14、;ai+1=t;for(i=1;i=6;i+)printf(%d,ai);main()int a6,i,j,t;printf(Input 6 numbers:n);for(i=0;i6;i+)scanf(%d,&ai);printf(n);for(j=0;j=4;j+)/*控制5轮排序 */for(i=0;iai+1)t=ai;ai=ai+1;ai+1=t;for(i=0;i=5;i+)printf(%d,ai);7.2 二维数组的定义和引用先看一个例子:先看一个例子:某校近三年招收各专业本科生人数如下:某校近三年招收各专业本科生人数如下:计算机 电子 管理 数学 2019 90 40 80
15、30 2000 100 50 90 40 2019 95 45 100 50 要把这些数据组织起来,可以有两种选择:要把这些数据组织起来,可以有两种选择:按从左到右从上到下的顺序存入一个一维数按从左到右从上到下的顺序存入一个一维数 组中。(查询困难)组中。(查询困难)每年用一个一维数组,把这些数据分别存入每年用一个一维数组,把这些数据分别存入 三个数组中。三个数组中。(增加一年数据困难)(增加一年数据困难)一、二维数组的定义一、二维数组的定义 定义二维数组的一般方式:定义二维数组的一般方式:类型说明符类型说明符 数组名数组名 常量表达式常量表达式11常量表达式常量表达式22;如:int a34
16、;存储形式:存储形式:二维数组在内存中是按行的顺序存放的,即先存放第一行的元素,再存放第二行的元素。说明:说明:二维数组除了维数比一维数组多一维外,二维数组除了维数比一维数组多一维外,其它性质与一维数组是全部类似的。其它性质与一维数组是全部类似的。看看下面写法是否正确?看看下面写法是否正确?int a03;用于定义数组长度的常量表达式的值必须用于定义数组长度的常量表达式的值必须是大于是大于0的正整数。的正整数。int i=3,j=4;int aij;定义数组元素的个数必须使用常量表达式,定义数组元素的个数必须使用常量表达式,而不能使用变量。而不能使用变量。二、二维数组的初始化二、二维数组的初始
17、化 这里主要介绍定义时初始化,其它方法初始化和一维数组类似。定义时初始化有两种方法:分行初始化分行初始化 例如:例如:int a23=1,2,3 ,4,5,6;省略掉内层的花括号省略掉内层的花括号 即按数组元素在内存中排列的顺序赋初值。即按数组元素在内存中排列的顺序赋初值。例如:例如:int a23=1,2,3,4,5,6;说明:说明:对二维数组初始化时,可以只对部分数组元素对二维数组初始化时,可以只对部分数组元素初始化,未被初始化的数组元素将自动赋初始化,未被初始化的数组元素将自动赋 0。int a23=5,6,7,8;int a23=5,6,7,8;如:得到的数组为:5 6 0 7 8 0
18、得到的数组为:5 6 7 8 0 0对二维数组初始化时,如果对全部元素都赋初值,对二维数组初始化时,如果对全部元素都赋初值,或分行赋初值或分行赋初值(每行至少一个数据每行至少一个数据),则可以省略第一,则可以省略第一维数组长度。但是,维数组长度。但是,第二维数组长度不允许省略第二维数组长度不允许省略。如:int a3=1,2,3,4,5,6,7,8,9;int a4=1,2,3,4,5,6,7;系统按3行处理 int a10=1,0;float f2=1.1,2.2;三、二维数组的引用三、二维数组的引用 与引用一维数组元素一样,是用下标法引用二维数组元素的。表示形式:表示形式:数组名行下标列下
19、标 其中,行下标和列下标是整型常量、整型变量或整型表达式。其编号是从0开始的。例如:若有 int a2*53*4,i=15;则使用 a3*30,a1i-5都是合法的。说明:(1)数组名a代表的是a在内存中的首地址,因此可以用数组名a来代表数组元 素a00的地址。例如:若有 int a34,设a的首地址为2000,则aij的地址为2000+i*3+j*4;a00的地址为2000,与a相同。(2)二维乃至多维数组是若干个比其低一维的数组的集合。换句话说,二维乃至多维数组可以化成多个降低维数后的数组使用。例如:若有 int a34,则等价于有了3个一维整型数组a0,a1,a2。四、二维数组应用举例四
20、、二维数组应用举例例1:使用数组保存“九九乘法表”,然后输出。main()int a991010,i,j;for(i=1;i 10;i+)for(j=1;j=i;j+)a99ij=i*j;for(i=1;i10;i+)for(j=1;j=i;j+)printf(%6d,a99ij);printf(n);例例7.4:矩阵的转置。(书中例:矩阵的转置。(书中例7.4)a=1 2 34 5 6b=1 4 2 53 6转换成main()int a23=1,2,3,4,5,6;int b32,i,j;printf(array a:n);for(i=0;i=1;i+)for(j=0;j=2;j+)prin
21、tf(%5d,aij);bji=aij;printf(n);printf(n array b:n);for(i=0;i3;i+)for(j=0;j2;j+)printf(%6d,bij);printf(n);例例7.5:求:求3*4数组中的最大值及其下标。数组中的最大值及其下标。main()int max,row,colum,i,j;int a4=1,2,3,4,9,8,7,6,-10,10,-5,2;max=a00;for(i=0;i3;i+)for(j=0;jmax)max=aij;row=i;colum=j;printf(max=%d,row=%d,colum=%d,max,row,co
22、lum);7.3 字符数组和字符串 (Character Array and Strings)一、字符数组一、字符数组(Character Array)当数组的元素类型为字符型时,被称为当数组的元素类型为字符型时,被称为字符数组字符数组。如:char c10;则c为字符数组。字符数组的定义、初始化和元素的引用与字符数组的定义、初始化和元素的引用与一般的数组相同。一般的数组相同。如:main()char ch5=c,h,i,n,a;for(i=0;i5;i+)printf(“%c”,chi);说明:说明:定义字符数组的类型说明符一般为定义字符数组的类型说明符一般为char,如:如:char c1
23、0;由于字符型与整型的互相通用性,由于字符型与整型的互相通用性,因此,上面定义也可改为:因此,上面定义也可改为:int c10;初始化赋值的字符个数初始化赋值的字符个数允许少于字符数组的允许少于字符数组的长度长度,但,但不能多于字符数组的长度不能多于字符数组的长度。当初始化。当初始化赋值的字符数(至少要有一个)少于字符数组赋值的字符数(至少要有一个)少于字符数组的长度时,未初始化部分将被编译系统自动用的长度时,未初始化部分将被编译系统自动用空字符空字符0 赋值。赋值。如:int c8=H,e,l,l,o;则:c0=H,c1=e,c2=l,c3=l,c4=,o c5=0,c6=0,c7=0二、字
24、符串与字符数组二、字符串与字符数组 字符串常量字符串常量是用双引号括起来的一串字符,由系统自动加上一个字符串结束标志0。它占内存,但不记入字符串长度。如:“china”占内存6个字节,但字符串长度是5 在在C语言中用字符数组来处理字符串,每个语言中用字符数组来处理字符串,每个数组元素存放一个字符型数据。数组元素存放一个字符型数据。字符型数组可用一般数组的初始化方式初始化字符型数组可用一般数组的初始化方式初始化外,还可以使用字符串常量初始化:外,还可以使用字符串常量初始化:如:char message=“Hello”;或 char message=“Hello”;(这时,字符数组长度是6,字符串
25、长度是5。)注意注意:它与一般初始化方式:它与一般初始化方式:char message=H,e,l,l,o;初始化的结果是不同的。初始化的结果是不同的。用一般初始化方式结果:H e l l o用字符串常量初始化:H e l l o 0说明说明:字符数组本身并不要求它的最后一个元素一定是0,例如:char ch2=A,B;是合法的。当定义字符数组用字符串常量赋初值时,最后有一个元素其值为0。为了使处理方法一致,在字符数组中也常常人为地加上一个值为0的元素。如:char message=H,e,l,l,o,0;例7.7 输出一个钻石图形main()char diamond5=,*,*,*,*,*,
26、*,*,*;int i,j;for(i=0;i5;i+)for(j=0;j5;j+)printf(“%c”,diamondij);printf(“n”);*三、字符数组的输入输出三、字符数组的输入输出字符数组的输入输出可以有以下两种方法:逐个字符输入输出逐个字符输入输出 用格式符“%c”输入或输出一个字符。将整个字符串一次输入或输出将整个字符串一次输入或输出 用格式符“%s”输入输出字符串。例如:char c=“Hello”;printf(“%s”,c);注意:注意:输出字符不包括结束符0。用“%s”格式符输出字符串时,printf函数的 输出项是字符数组名,而不是数组元素名。main()ch
27、ar a5;int i=0;while(i0;串串1串串2 则:则:n=n=0;串串1=串串2 n0;串串10)puts(str1);注意:注意:不能写成不能写成 if(str1str2)strcmp(“China”,”Korea”);3.字符串连接字符串连接strcat()函数函数 使用形式使用形式:strcat(字符数组1,字符串2)功能功能:连接两个字符串,把字符串2连接到字符 串1的后面,连接后的字符串放在字符 数组1中。说明:说明:字符数组字符数组1必须足够大以便能够容纳字符串必须足够大以便能够容纳字符串2。连接时只在新串最后保留一个连接时只在新串最后保留一个0。4.字符串复制字符串
28、复制strcpy()函数函数 使用形式使用形式:strcpy(字符数组1,字符串2)功能功能:将字符串2复制到字符数组1中 (其后自动加一个0)。例如:char str120,str210;strcpy(str1,“hello world”);strcpy(str2,str1);其中,字符串2可以是字符串常量或字符数组。Strcpy使用举例:使用举例:#include#includemain()char filewing20=wing.txt”,filehori20=fuselage.txt”,filefuse20=“tail.txt“;cout“请输入飞机部件类型 n;cout1-机翼n;c
29、out2-机身n;cout3-尾翼numpart;switch(numpart)case 1:strcpy(filedes,filewing);cout“正在计算机翼,请稍等.”;break;case 2:strcpy(filedes,filehori);cout正在计算机身,请稍等.;break;case 3:strcpy(filedes,filefus1);cout“正在计算尾翼,请稍等.;break;case 4:default;ifstream in(filedes,ios:in);if(!in)coutcannot open Inputfile n;exit(1);说明:说明:字符数
30、组1必须足够大以便能够容纳被 复制的字符串。不能用赋值语句将一个字符串常量或字符 数组直接赋值给一个字符数组。例如:char str120,str220;str1=“hello”;str2=str1;5.将字符串中大写字母换成小写字母将字符串中大写字母换成小写字母strlwr()函数函数 使用形式使用形式:strlwr(字符串)6.将字符串中小写字母换成大写字母将字符串中小写字母换成大写字母strupr函数函数使用形式使用形式:strupr(字符串)五、字符数组应用举例五、字符数组应用举例例1:(例题7.8)统计字符串中的单词数。#include main()char string81,c;i
31、nt i,num=0,word=0;gets(string);for(i=0;stringi!=0;i+)if(stringi=)word=0;else if(word=0)word=1;num+;printf(“nThere are%d words.”,num);I am a boys0word=0(后面是单词)s=word=0num+word=1(后面不是单词)YYNYNNI am a boy学习数组这一章要注意的几个问题:学习数组这一章要注意的几个问题:1.1.在在C C语言中数组的下标是从语言中数组的下标是从0 0开始;开始;2.C2.C语言不进行下标的越界检查,不论是在编译阶段还是语
32、言不进行下标的越界检查,不论是在编译阶段还是 在运行阶段,这个问题交给程序员。这样就给初学者在运行阶段,这个问题交给程序员。这样就给初学者 带来一定的风险。带来一定的风险。3.3.数组名是地址,这在字符串处理中已经看到,这个我数组名是地址,这在字符串处理中已经看到,这个我 们要先强记,以后在讲指针时再详细讲。们要先强记,以后在讲指针时再详细讲。4.4.字符数组在定义时必须考虑到串结束符的位置,因为字符数组在定义时必须考虑到串结束符的位置,因为 它要占一个字符的位置它要占一个字符的位置.5.5.要注意数组初始化的方法与简单变量的区别,特别是要注意数组初始化的方法与简单变量的区别,特别是 字符数组
33、的初始化方法。字符数组的初始化方法。6.6.字符串的操作有许多专用函数,请注意掌握并运用字符串的操作有许多专用函数,请注意掌握并运用。本章作业:本章作业:1.复习本章内容,将书中例题看懂,会独立编写。复习本章内容,将书中例题看懂,会独立编写。2.编写并上机调试下列习题:编写并上机调试下列习题:1)用冒泡法对任意输入的用冒泡法对任意输入的n个数(个数(n10)排)排序(序(由大到小由大到小)。)。2)矩阵的转置。)矩阵的转置。a=1 2 3 46 7 89 10 11 12b=1 5 92 6 103 7 114 8 12转换成3)对一段英文的文章进行统计,分别计算输出其单)对一段英文的文章进行
34、统计,分别计算输出其单词数、空格数,不考虑标点符号(标点符号与单词词数、空格数,不考虑标点符号(标点符号与单词之间有空格)。之间有空格)。例如:例如:I am a teacher._you are students.4)在字符数组中存一段英文,按书上例)在字符数组中存一段英文,按书上例6.10译成密译成密码,取字符的码,取字符的ASCII码的移动值为码的移动值为4,除英文字符外,除英文字符外,其它符号不译码。按提示一给出一段或数段英文句其它符号不译码。按提示一给出一段或数段英文句子,打开一个数据文件,将译码后的英文输出到该子,打开一个数据文件,将译码后的英文输出到该数据文件。数据文件。5)将提
35、示二给出的几句英文句子翻译成原文。(选)将提示二给出的几句英文句子翻译成原文。(选做)做)FILE*fp;/定义文件指针char parag100=“That may change in the near future.”,“With it,two people are talking can see each other.”;/字符数组赋初值/新建名为parag.txt的数据文件if(fp=fopen(parag.txt,w)=NULL)printf(cannot open this filen);paragki!=0/译码时循环继续的条件/循环将字符数组中的字符输出到上述数据文件for(k
36、=0;k5;k+)fprintf(fp,%sn,pk);fclose(fp);/关闭前面打开的数据文件提示一提示一char parag100=Ytifd ujtuqj hfs zxj ymj umtsj yt yfqp bnym tymjwx fqrtxy fsdbmjwj ts ymj jfwym.,Gzy bmjs dtz zxj ymj umtsj,dtz itsy xjj ymj ujwxts dtz fwj yfqpnsl bnym.,Ymfy rfd hmfslj ns ymj sjfw kzyzwj.,Ytifd xtrj ujtuqj fwj zxnsl f pnsi tk yjqjumtsj hfqqji ymj unhyzwj umtsj tw anxnts umtsj.,Bnym ny,ybt ujtuqj fwj yfqpnsl hfs xjj jfhm tymjw.;提示二提示二