1、第七章 数 组,C语言中除了基本类型的数据之外,还有构造类型的数据(如:数组类型、结构体类型、共用体类型等)。构造型数据 : 由基本类型数据按一定的规则组成的数据。最简单的构造类型是数组。,第七章 数组,数组定义 : 同一种数据类型的元素的有序集合。一个数组用一个统一的名称-数组名。数组中的每一个元素由数组名和下标唯一地确定。数组有一维数组、二维数组等.,定义方式: 类型说明符 数组名常量表达式; 例如 : int a10;,7.1 一维数组的定义和引用,表示数组名为 a 有10个整型元素,系统为数组a分配 一块连续的空间。 下标 i 唯一地确定 每一个元素.,i 0 1 2 3 4 . .9
2、,a a0 a1 a2 a3 a4 . .a9,7.1.1 一维数组的定义,以下是不合法的:int n ;scanf(“%d” , /* n 是变量 */,1. 数组名的命名方式与标识符相同。2. 数组名后面是 “ ”, 不是( )。3. 常量表达式表示元素的个数,即数组长度,数组的下标从 0 开始4. 常量表达式可以是常量或符号常量,但不能是变量。#define M 100int aM ; /* M为符号常量 */,注 意,数组必须先定义后使用。C语言中规定只能逐个引用数组元素而不能一次引用整个数组数组元素的表示形式 : 数组名下标,例如:int a10 ;a0=a5+a7+a2*3 ;,可
3、以是整型常量 或整型表达式,整型常量,整型表达式,注意表达式值 不能超过 9,7.1.2 一维数组元素的引用,#include void main( ) int i , a10 ;for(i=0 ; i=0; i- -) /* 倒序输出数组元素值 */printf(“%d“, ai ) ; ,数组元素的引用。,运行结果:9 8 7 6 5 4 3 2 1 0,例 7.1,可以用赋值语句或输入函数使数组中的元素得到值;也可以在程序运行之前对数 组进行初始化,即 对数组元素赋初值。数组元素的初始化方法:1. 在定义数组的同时可以对数组元素赋初值。例如: int a10=0,1,2,3,4,5,6,
4、7,8,9;相当于:a0=0 , a1=1 ,a9=9,7.1.3 一维数组的初始化,2. 可以只给一部分元素赋值例如: int a10=0,1,2,3,4;表示只对前面 5 个元素赋初值,后5个元素初值为0。,3. 如果一个数组中全部元素赋同一个初值,也必须逐个写出。例如: int a10=0,0,0,0,0,0,0,0,0,0 ;4. 对全部数组元素赋初值时可以不指定数组长度。例如: int a =1,2,3,4,5; 系统自动将 a 的长度定义为 5。但是,当数组长度与初值个数不相同时,必须写出数组长度。,#include void main() int i;int f20=1,1; /
5、* 处理前20项,并对第一、第二项赋初值1 */for (i=2;i20;i+) /* i=2 表示从第三项开始 */fi=fi-2+fi-1;for(i=0;i20;i+) if (i%5=0)printf(“n“); /* 控制输出换行,每行为5个元素 */printf(“%12d“,fi);,7.1.4 一维数组程序举例,用数组来处理 Fibonacci 数列问题。,F1=1 , F2=1 , Fn=Fn-2 + Fn-1 (n2),例 7.2,用冒泡法对10个数排序(从小到大)。冒泡发的基本思路: 将相邻两个数比较,将小的调到前面。第一次从第一个数开始相互比较直到最后一个数,则小的数已
6、经上浮, 而最大数已经下沉到底;第二次从第一个数开始相互比较直到倒数第二个数,则小的数又上浮, 而第二大的数已经下沉到倒数第二位,9 8 8 8 8 8 8 9 5 5 5 55 5 9 4 4 4 4 4 4 9 2 2 2 2 2 2 9 0 0 0 0 0 0 9,8 5 5 5 5 5 8 4 4 4 4 4 8 2 2 2 2 2 8 0 0 0 0 0 8,5 4 4 4 4 5 2 2 2 2 5 0 0 0 0 5,4 2 2 2 4 0 0 0 4,2 0 0 2,0,分析:1. 当对6个数排序,则 每次作两两比较的对数为:5,4,3,2,12. 比较趟数为5趟;3. 参加比
7、较的个数为:6, 5, 4, 3, 2,例如:,例 7.3,for (j=0;jai+1) t=ai;ai=ai+1;ai+1=t;,#include void main( ) int a10 , i , j ,t ;printf(“Input 10 numbers:n“) ;for(i=0 ;iai+1) t=ai; ai=ai+1 ; ai+1=t ; printf(“ The sorted number : n“) ;for(i=0 ;i10 ;i+) /* 输出已排序的数 */printf(“%d “, ai) ; ,当排序个数为 n:,运行如下: Input 10 numbers:
8、1 0 4 8 12 65 -76 100 -45 123 The sorted numbers: -76 -45 0 1 4 8 12 65 100 123,#define M 10void main( ) int j , n , change , aM ;for(j=0 ; j0 ,0 0 0 0 0 01 1 1 1 1 12 2 2 2 2 29 8 8 8 7 78 9 7 7 8 87 7 9,程序二:设change=1时表示上一趟比较有交换,例如:,注意判断的条件,若上一趟没有交换,则跳出 循环。这个算法速度快。,若 用历遍法对数据排序(如从小到大) 历遍法排序的思路: 第一次从
9、第一个开始找出最小的一个 作为第一个元素,第二次从第二个开始找出第二小的元素。,9 0 0 0 0 0 8 9 2 2 2 25 8 9 4 4 44 5 8 9 5 52 4 5 8 9 80 2 4 5 8 9,例如:,void main( ) int a10 , i , j ,t ;printf(“Input 10 numbers:n“) ;for(i=0 ;iai) t=aj; aj=ai ; ai=t ; printf(“The sorted number : n“) ;for(i=0 ;i10 ;i+) /* 输出已排序的数 */printf(“%d “, ai) ; ,当排序个数
10、为 n:,for (j=0 ; jai) t=aj; aj=ai; ai=t; ,二维数组定义的一般形式: 行下标 列下标类型说明符 数组名常量表达式常量表达式例如:float a34; -定义 a 为 3 行 4 列的数组int b510 ;-定义 b 为 5 行 10 列的数组不能写为:float a3,4 ; int b5,10 ; float a(3,4) ; int b(5,10) ;,7.2 二维数组的定义和引用,7.2.1 二维数组的定义,一个二维数组可以看作一种特殊的一维数组, 它的元素 又是一个一维数组。 例如:int a34 ; 其中:a0a00 , a01 , a02 ,
11、 a03a1a10 , a11 , a12 , a13a2a20 , a21 , a22 , a23 即:a0 是第一行的首地址;a1 是第二行的首地址;a2 是第三行的首地址;,C语言中的二维数组元素排列顺序是: 按行存放a00 , a01 , a02 , a03 ,a10 , a11 , a12 , a13 , a20 , a21 , a22 , a23 ,a00,a03,. .,a10,a13,. .,a20,a23,. .,C语言允许多维数组,例如:float a234 ;,二维数组的元素表示形式: 数组名下标下标1. 下标可以是整型常量或整型表达式2. 数组元素可以出现在表达式中,也
12、可以被赋值例如: a24=35 ; a12=a01+a02 ;,7.2.2 二维数组元素的引用,注意 : 数组下标的值必须在数组定义时的大小范围内例如 :int a23 ;a23=35 ; /* 出错 */强调一下:定义数组 a23 中的2和3表示行数和列数, 而引用数组元素 a12 时1和2 表示第2行第3个元素。 下标从0开始。,7.2.3 二维数组的初始化1. 分行给二维数组赋初值 ( 即按行赋初值 )。例如: int a34= 1,2,3,4,5,6,7,8,9,10,11,12 ;将第一个“ “内的数据赋给第一行的元素,.2. 可以将所有数据写在一个“ ”内,系统自动按数组元素的排列
13、顺序赋初值(不直观,容易出错)。例如: int a34=1,2,3,4,5,6,7,8,9,10,11,12 ;,3. 可以对部分元素赋初值,其余元素值自动为0。例如: int a34= 1,5,9 ;1 0 0 05 0 0 09 0 0 0,int a34=1, ,9;1 0 0 00 0 0 09 0 0 0,例如: int a34=1,0,6,0,0,11,1 0 0 0 0 6 0 0 0 0 11 0,4. 如果对全部元素赋值,则定义数组时对第一维的长度可以不指定,但第二维的长度不能省略,系统按数据总个数和每行的列数确定出行数。例如: int a 4=1,2,3,4,5,6,7,8
14、,9,10,11,12 ;或每一行都清楚地表出了初始化,也可以省行下标:int a 4=0,0,3, ,0,9;,0 0 3 0 0 0 0 0 0 9 0 0,将一个二维数组行和列互换,存到另一个数组中。1 2 3 1 44 5 6 2 53 6,a00b00 a10b01 a01b10 a11b11 a02b20 a12b21,a23 b32,行 列,a 的行下标为 b 的列下标,a 的列下标为 b 的行下标,例 7.4,7.2.4 二维数组的程序举例,#include void main( ) int a23=1,2,3,4,5,6 ;int b32 , i , j ;printf(“a
15、rray a:n“) ;for(i=0 ; i2 ;i+) for(j=0 ; j3 ; j+) printf(“%5d“, aij) ; bji=aij ; printf(“n“) ;printf(“array b:n“) ;for(i=0 ; i3 ; i+) for(j=0 ; j2 ; j+) printf(“%5d“, bij) ;printf(“n“) ; ,求一个 3x4 矩阵中值最大的元素及其所在的行和列。 思路: 假设第一个元素为最大,将该最大值与矩阵中的所有元素逐个比较, 如果有大的,则该元素作为最大值,并记下该元素的行和列。,#include void main( ) i
16、nt i,j,row,col,max;int a34=1,2,3,4,7,8,9,10,-5,25,4,10;max=a00; row=0; col=0;for (i=0;imax) max=aij; row=i; col=j; printf(“max=%d,row=%d,col=%dn“,max,row,col); ,例 7.5,#include void main()int m,n,i,j,row,col,max,a1010;printf(“input rows ,如果只已知矩阵的范围,运行时要求从键盘输入矩阵的 大小及各个元素值。,注意: m10,n10,字符数组-用来存放字符数据的数组
17、。字符数组中的每一个元素存放一个字符(即相应的ASCII码)。7.3.1 字符数组的定义char 数组名常量表达式 ;由于字符型与整型相通,因此也可以定义为整型int 数组名常量表达式 ;,7.3 字符数组,例如:char c10;c0=I; c1= ; c2=a; c3=m; c4= ; c5=h; c6=a; c7=p; c8=p; c9=y;,Ia mh a p p y,C10,内存存放的形式,分配10个字节,逐个将字符赋给数组中的元素。例如: char c5=C,h,i,n,a;如果字符个数小于数组长度时,将这些字符赋给数组中前面那些元素, 其余的元素自动定义为空格。如果初值个数与数组
18、长度相同,定义时可省略数组长度。char c =C,h,i,n,a;二维字符数组的定义与赋初值也与其它类型的数组相同。,7.3.3 字符数组的引用可以引用字符数组中的一个元素,得到一个字符。,7.3.2 字符数组的初始化,输出一个字符串。,#include void main( ) char c10=I, , a, m, , a, b, o, y;int i ;for(i=0 ; i10 ; i+)printf(“%c“, ci) ;printf(“n“) ; ),运行结果:I am a boy,例 7.6,输出一个钻石图形。,#include void main( ) char diamon
19、d 5= , ,*, ,*, ,*,*, , , ,*, ,*, , *, , ,*;int i , j ;for(i=0 ; i5 ; i+) for(j=0 ; j5 ; j+)printf(“%c“,diamondij) ;printf(“n“) ; ,* * * * *,运行结果:,例 7.7,1. C语言中将字符串用字符数组来处理。2. 由于字符串的实际长度可能与定义的字符数组长度不同,因此为了测定字符串的实际长度,在C语言中规定了一个“字符串结束标志”,以字符0代表。,系统给这个字符串常量分配11个字节,I a m a b o y 0,7.3.4 字符串和字符串结束标志,3.0代表
20、ASCII码为0的字符,即“空操作符”,因此用0来作为字符串结束标志不会产生附加的动作。,4. 对于字符串常量,系统自动加上一个0作为结束符,例如:“I am a boy“,5. 有了0,对于存放字符串的字符数组的长度就显得不太重要了,只要保证数组长度大于字符串长度即可。6. 有了处理字符串的方法,就可以用字符串常量来对字符数组初始化。例如: char c =“I am happy“;也可省去“ ”,直接写成 char c =“I am happy“;,1. 用字符串常量作为初值时,字符数组的长度是字符串的长度再加上结束符。例如:,再强调几点:,char c =“I am happy“;,相当
21、于: char c =I, ,a,m, ,h,a,p,p,y,0;,数组 c 的长度是 11,char c =I, ,a,m, ,h,a,p,p,y ;数组 c 的长度是 10。,1. 用格式符“%c”逐个输入或逐个输出,一次输入或输出一个字符。 例如: int i;char c5;for (i=0;i5;i+) /* 逐个输入 */scanf(“%c“,2. 字符数组并不一定要求最后一个字符为0。,7.3.5 字符数组的输入输出,1. 输出时不包括0。2. 用“%s”格式输出时,printf函数中的输出项是字符数组的数组名。 例如 :char c =“China“;printf(“%s“,
22、c ); 下面写法是不正确的: printf(“%s”, c0) ;,输出字符串 China,用数组名 c,2. 用格式符“%s”将整个字符串一次输入或输出。输出时遇到结束符0就停止。,C0是数组元素,使用时特别要注意以下几点:,3. 当数组长度大于字符串的实际长度时,也只输出到0结束。char c10 =“China“ ;printf(“%s“, c) ;,5. 用 scanf 函数“%s”格式输入一个字符串时,函数中输入项用数组名,并且该数组已定义,而且输入字符串的长度应小于数组长度。例如: char c10;scanf(“%s“, c);,用数组名,而且不要加地址符 &, 因为数组名代表
23、了该数组的起始地址,数组长度为 10,最多只能输入9个字符,4. 如果一个字符数组中包含多个0时,遇到第一个0时结束输出。,6. 用scanf函数输入多个字符串时,每个字符串之间用空格分隔例如: char str15, str25, str35;scanf(“%s%s%s“,str1,str2,str3);输入: How are you?则: +0 - str3+0 - str2+0 - str1,如果改为: char str13;scanf(“%s“,str); 输入: How are you?只将第一个空格前的字符How送到str中,并加上0。 scanf( ) 遇到空格时,作为输入串结束
24、。,注 意,7.3.6 字符串处理函数在C语言的函数库中提供了一些用来处理字符串的函数。1. 字符串输入输出函数(1) 字符串输出函数 puts(字符数组) -将一个字符串输出到终端。,以0结束,可包含转义字符,例如: char str10= “ China“ ;puts(str) ;,输出: China,(2) 字符串输入函数 gets(字符数组) -输入一个字符串到字符数组函数值是字符数组的起始地址。例如 :char str10 ;gets(str) ;键盘输入:Computer , 数组 str 接收,换行字符n 改为结束符 0 。,puts 函数和gets 函数一次只能输出或输入一个字
25、符串 头上要加 # include ,注意:,2. 字符串连接函数 strcat(字符数组1,字符数组2)功能:将字符数组2中的字符串连接到字符数组1中的字符串的后面, 连接后的结果放在字符数组1中。连接时将自动取消第一个字符串后面的结束标志0注意: 字符数组1必须足够大例如: char str130=“Peoples Republic of “ ;char str2 =“China“ ;printf(“%s“,strcat(str1 , str2) ;执行后在str1 中的字符串为:Peoples Republic of China,3. 字符串拷贝函数 strcpy(字符数组1,字符串2)
26、功能:将字符串2拷贝到字符数组1中 ( 包括字符串结束标志0 )例如: char str110 , str2 =“China“ ;strcpy(str1, str2) ;printf(“%s“,str1) ;其中: 字符数组1必须是字符数组名的形式字符串2可以是字符数组名或字符串常量例如: char str10 ; strcpy(str1 , “China“) ;,(1) 字符数组1必须足够大;(2) 不能用赋值语句直接将一个字符串赋给一个字符数组,只能用 strcpy函数,例如以下是不合法的:char str110 , str2 =“China“ ; str1=str2 ;,如果需要拷贝字符
27、串2中前面的若干个字符,则可指出需要拷贝的字符数。strcpy(字符数组1,字符串2,字符数)例如: strcpy(str1, str2, 2) ;把 str2 中头上二个字符复制到 str1 中去, str1 再加一个结束0。,注意,4. 字符串比较函数 strcmp(字符串1,字符串2)功能: 比较字符串1与字符串2 即:自左至右逐个字符按ASCII码大小相比较 。比较结果:如果字符串1 = = 字符串2, 函数值为 0。如果字符串1 字符串2, 函数值为 一正整数。如果字符串1 字符串2,函数值为 一负整数。,例如:“A“A“, “computer“compare“, “these“th
28、at“ , “1“2“, 等等。,两个字符串比较不能用关系运算符,而只能用strcmp函数, 比较结果值 由strcmp 函数返回。例如:不能用以下形式if(str1= =str2)printf(“yes“) ;只能用以下形式:if(strcmp(str1,str2)=0)printf(“yes“) ;,注意,4. 测字符串长度函数 strlen(字符数组)功能: 测试字符串的实际长度,不包括0在内。例如: char str10=“China“ ; printf(“%d“, strlen(str) ;或 strlen(“China“) ;输出:5 (注意不是6,也不是10)。,可以是字符串常量
29、,5. 字符串大小写字母转换函数功能:将字符串中的大写字母转换成小写字母 strlwr(字符串)将字符串中的小写字母转换成大写字母 strupr(字符串)例如: char str10=“China“ ;strlwr(str) ; 或 strlwr(“China“) ;printf(“%s“,str) ;输出: chinastrupr(str) ;输出:CHINA,用以上所有函数,头上要加以下宏包含#include ,输入一行字符,统计其中的单词个数。单词之间用空格分隔。,7.3.7 字符数组应用举例,#include void main( ) char sting80 , c;int i ,
30、num=0 , word=0 ;gets(sting) ;for(i=0 ; (c=stringi) !=0 ; i+)if(c = ) /* 本次单词结束 */word=0 ; else if(word= =0) /* 新的单词开始 */ word=1 ; num+ ; printf(“There are %d words in the line.n“, num) ; ,例 7.8,不能用scanf( ) ?,有三个字符 串,要 找出三个字符串中最大的一个串.,#include #include void main( ) char string20, str320 ;int i;for(i=
31、0 ; i0) strcpy(string , str0);else strcpy(string , str1) ; /* 大的一个串存放在string中 */if(strcmp(str2 , string)0) strcpy(string , str2) ;printf(n The largest string is : n%sn , string); ,例 7.9,运行结果:输入: CHINAHOLLAND AMERICA,输出: The largest string is:HOLLAND,C H I N A 0,H O L L A N D 0,A M E R I C A 0,str0str1str2,习 题 五 (上 机 三),P141 7.3 , 7.5 , 7.6 , 7.11 , 7.13,