1 / 56

第七章 数组

第七章 数组. 前面所用到的数据均为基本类型 ( 整、实、字符 ) ,为了丰富数据类型 ,须提供强有力的数据表达方式。 C 语言提供了一种构造类型数据 ––– 由基本类型按某一规则组合在一起。. 其中数组:同一种 ( 基本 ) 类型按一定顺序组合在一起的数据类型。. §7.1 一维数组. 7.1.1 一维数组的定义. 形式 : 类型说明符 数组名 [ 常量表达式 ];. 例 : int a [20]; float x [100];. 1. 数组名的确定方法同变量名。. 2. C 语言用方括号 [ ] 表示数组元素个数。.

linnea
Download Presentation

第七章 数组

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第七章 数组 前面所用到的数据均为基本类型(整、实、字符),为了丰富数据类型 ,须提供强有力的数据表达方式。C语言提供了一种构造类型数据–––由基本类型按某一规则组合在一起。 其中数组:同一种(基本)类型按一定顺序组合在一起的数据类型。

  2. §7.1一维数组 7.1.1 一维数组的定义 形式: 类型说明符 数组名[常量表达式]; 例: int a [20]; float x [100]; 1. 数组名的确定方法同变量名。 2. C语言用方括号[ ]表示数组元素个数。

  3. 3. 常量表达式为常量和符号常量。不允许有变量,其表达式的值代表了元素的个数。 例: int a[20]; 表示有20个元素 且元素从0开始编排:a[0],a[1],…,a [19]

  4. 4. 可在定义时对静态数组和外部存储(全局)数组赋初值, 方法如下: 对全部元素赋初值 static int a[10]={10, 11, 12, 13, 14, 15, 16, 17, 18, 19,} 静态 对部分元素赋初值 static int a[10]={0,1,2,3,4}; 如此,只有前5个元素初值确定,后5个元素由系统设置。

  5.  如对数组元素赋同一初值,必须一一写出: static int a[10]={0,0,0,0,0,0,0,0,0,0}; 不可写成: static int a[{10*0}]; ×  若赋全部元素的初值,可省略常量表达式 …a [ ]={0,1,2,3}; 表示a[4],即只有4个元素。

  6. 7.1.2 一维数组的引用 1. 须象使用变量那样,先定义,后使用 2. 引用方式: 数组名[下标] 其中的下标为整型表达式,但不得越界。 数组引用代表了一个元素,等价一个同类型的变量。 例: a [0]5+a[1]  6 为正确的算术表达式 3. 一般地,一维数组各元素分配在连续的内存单元之中。

  7. 例7.1:给 a[0] ~ a[9] 赋值 0 ~9,然后按逆序输出。 main( ) { int i,a[10]; for (i=0;i<=9;i++) a[i]=i; for (i=9;i>=0;i--) printf(“%4d”,a[i]); printf(“\n”); }

  8. 7.1.3 一维数组的应用 例7.2:求Fibonacci 数列。  定义数组,并赋初值 static int f [20]={1,1}; 用循环for实现: for (i=2; i<20; i++) f [i]=f [i –2]+f [i –1]; 注意:下标界限问题:i =2且i<20

  9. 1 8 89 987 1 13 144 1597 2 21 133 1584 3 34 377 4181 5 55 610 6765 程序如下: main() { int i; static int f [20]={1, 1}; for (i=2; i<20; i++) f [i]=f [i–2]+f [i–1]; for (i=0; i<20; i++) { if (i%5 = =0) printf("\n"); printf("%12d",f [i] ) } } 运行结果如下:

  10.  打印: 每5个数换一行。 for (i=0; i<20; i++) { if (i%5= =0) printf(" \n "); printf (" %12d ", f [i]); }

  11. 例2:排序问题–––计算机处理数据的一个重要问题例2:排序问题–––计算机处理数据的一个重要问题 排序算法较多,一种最简单的算法–––选择排序法用得较多。基本思路: 设有n个数,需将它们从小到大顺序排列。则: 1. 从n个元素中,通过比较,找出最小元素,放在第一个位置上。 2. 在剩下的n –1个元素中,找出第二小的元素并把它放在第二个位置上。 3. 对上述过程重复,直至剩下一个元素。

  12. 例如: 8, 4, 20, 100, 28, 1, 第1次: 4, 8, 20, 100, 28, 1 1, 8, 20, 100, 28, 4 两次交换 第2次: 1, 4, 20, 100, 28, 8 –––一次交换 第3次: 1, 4, 8, 100, 28, 20 –––一次交换 第4次: 1, 4, 8, 28, 100, 20, 1, 4, 8, 20, 100, 28 两次交换 第5次: 1, 4, 8, 20, 28, 100 –––一次交换

  13. 初始化 输入n个元素a数组 i1 B ji+1 A No a[i]>a[j] Yes 交换a[i] a[j] 从以上例子可以看到: 用到两种循环,第一种循环––找第i小的元素,第二种循––对其后的元素的一一比较。 流程图:

  14. jj+1 内循环 No A j>n Yes ii+1 外循环 No B i> n–1 Yes 打印结果 结束

  15. 程序: main() { int a [11]; int i, j, t; printf (" please input 10 numbers:\n "); for (i=1; i<=10; i++) scanf("%d", &a[i]); printf(" \n "); for (i=1; i<=9; i++) for (j=i+1; j<=10; j++) if (a[i]>a[j]) { t=a[i]; a[i]=a[j]; a[j]=t;} printf (" the sorted numbers: \n "); for (i=1; i<=10; i++) printf(" %d ", a[i]); printf(" \n " ); } 思考:此算法还可改进!

  16. 程序: main() { int a [11]; int i, j, t,minj; printf (" please input 10 numbers:\n "); for (i=1; i<=10; i++) scanf("%d", &a[i]); printf(" \n "); for(i=1;i<=9;i++) {minj=i; for(j=i+1;j<=10;j++) if(a[j]<a[minj]) minj=j;if(minj!=i) {t=a[i];a[i]=a[minj];a[minj]=t;} }printf (" the sorted numbers: \n "); for (i=1; i<=10; i++) printf(" %d ", a[i]); printf(" \n " ); }

  17. (1)若a0>a1,则a0、a1交换;(使a1为a0,a1的大者)(2)若a1>a2,则a1、a2交换;(使a2为a1,a2的大者)…(i) 若ai-1>ai,则ai-1、ai交换;(使ai为ai-1,ai的大者)按照这种方法运算下去,数组中的最大元一定可以移动到最后一个下标位置! 另一种排序法:冒泡排序法(教材例7.3) 相邻元素比较大小,发生交换,使最大值(最小值)“浮出”到数组尽头:

  18. 冒泡排序举例: 初始序列为49,38,65,97,76,13,27,49’由小到大排序 第1趟冒泡:38 49 65 76 13 27 49’ [97] 第2趟冒泡:38 49 65 13 27 49’ [76 97] 第3趟冒泡:38 49 13 27 49’ [65 76 97] 第4趟冒泡:38 13 27 49 [49’ 65 76 97] 第5趟冒泡:13 27 38 [49 49’ 65 76 97] 第6趟冒泡:13 27 [38 49 49’ 65 76 97] 排序结果为:13 27 38 49 49’ 65 76 97

  19. 冒泡排序算法: N元数组a[0]~a[N-1]由小到大排序:第1步:找到a[0]~a[N-1]中的最大元浮动到a[N-1];第2步:找到a[0]~a[N-2]中的最大元浮动到a[N-2];第3步:找到a[0]~a[N-3]中的最大元浮动到a[N-3];…第i步:找到a[0]~a[N-i]中的最大元浮动到a[N-i];…第N-1步:找到a[0]~a[1]中的最大元浮动到a[1]。算法停止.

  20. #include “stdio.h”#define N 10 void main(){int a[N],i,j,t;printf(“Input %d int numbers:\n”,N); for(i=0;i<N;i++) scanf(“%d”,a+i);for(i=1;i<N;i++) for(j=0;j<N-i;j++) if(a[j]>a[j+1]) { t=a[j];a[j]=a[j+1];a[j+1]=t; }printf(“Reslut:”);for(i=0;i<N;i++) printf(“%6d”,a[i]);printf(“\n”);} 此处, a+i等价于&a[i]

  21. 顺序查找(一种查找方法) main() {int i, a[10],x; for (i=0;i<=9;i++) scanf(“%d”,&a[i]); scanf(“%d”,&x); for (i=0;i<=9;i++) if (a[i]==x) break; if (i<=9) printf (“%d is a [%d] ”,x,i); else printf (“not find %d” ,x); } 例:键盘输入10个数存于数组a[10]中,再输入一数x,查找x在a[10]中的位置。 程序如右:

  22. 折半查找(也称为对分查找) 算法: 设a[0]~a[N-1]已升序,待查找元素为x令起点下标 h=0; 终点下标 r=N-1;中点下标 m=(h+r)/2; @当h<=r时执行以下步骤: 若x==a[m]则表明查找成功,a[m]为所找元素;x<a[m],显然x在a[h]~a[m-1]之间,则h不变;r=m-1;m=(h+r)/2;转@ x>a[m],显然x在a[m+1]~a[r]之间,则 r不变;h=m+1;m=(h+r)/2;转@ 若h>r,则表明查找失败. 该算法仅适用于在已排序的数组中快速查找所需要的元素,具有效率高的突出优点。可以证明,当数组长度为n个元素时,该算法的平均比较次数不会超过log2n+1。

  23. /*升序数组a[N]中查找x,找到返回有效下标0~N-1, 查找失败返回-1*/main() {int a[10]={1,2,3,4,5,6,7,8,9,10}; int x,h,r,m;scanf(“%d”,&x);h=0;r=9;m=(h+r)/2; while(h<=r&&x!=a[m]) if(x<a[m]) {r=m-1;m=(h+r)/2;} else { h=m+1;m=(h+r)/2; }if(h>r) printf (“not find %d” ,x); else printf (“%d is a [%d] ”, x,i); }

  24. §7.2 二维数组 7.2.1 二维数组的定义 形式 类型说明符 数组名[常量表达式] [常量表达式] 例: int a[4] [10]; float x[8] [20]; 1. 不可将定义写为int a[4,10]。

  25. 2. 可将二维数组的元素看成为若干个特殊的一维数组。 如:int b[3] [4]; 则: 有三个特殊的一维数组b[0],b[1], b[2],每一个又有四个元素: b[0]: b[0][0], b[0][1], b[0][2], b[0][3], b[1]: b[1][0], b[1][1], b[1][2], b[1][3], b[2]: b[2][0], b[2][1], b[2][2], b[2][3],

  26. 3. 二维数组的存放方式为: 按行存放。由此可推广 至三维、n维数组的定义和存放。 即: 最右边的下标变化最快。 4. 初始化: 按行给二维数组赋初值: static int a[3][4]={{1,2,3,4}, {5,6,7,8,}, {9,10,11,12,}}; 可以去掉其中的{ }。

  27. 则相当于 1 2 0 0 3 0 0 0 8 0 0 0  可以对部分元素赋初值,但需表达清楚。如: static int a[3][4]={{1,2},{3},{8}}。 可通过赋初值决定数组大小。如为二维,则只可省略第一维的大小. static int a[ ][4]={1,2,3,…,12};

  28. 7.2.2 二维数组元素的引用 形式: 数组名[下标][下标] 其中的下标为整型表达式,但不得越界。 与一维数组元素一样,二维数组元素相当于同类型的简单变量。

  29. 1 4 2 5 3 6 1 2 3 4 5 6 a= b= 7.2.3 程序举例 例1将一个二维数组行和列元素互换,存到另一个二维数组中。例如: 程序如下:

  30. main() { static int a[2] [3]={{1, 2,3},{4, 5,6}}; static int b[3] [2], i, j; printf("array a: \n"); for (i=0; i<=1; i++) { for (j=0; j<=2; j++) {printf("%5d", a[i][j]); b[j][i]=a[i][j];} printf("\n"); } printf("array b:\n"); for (i=0; i<=2; i++) { for (j=0; j<=1; j++) printf("%5d", b[i]j]); printf("\n"); } }

  31. 运行结果如下: array a: 1 2 3 4 5 6 array b: 1 4 2 5 3 6  数组元素数据的输入必须以循环方式进行或者定义时置初值。

  32. max= a[0][0] 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  二维数组一般用二重循环 例2. 有一个3×4的矩阵,要求编程序求出其中值最大的那个元素的值,以及所在的行号和列号。 先用N-S流程图表示算法,见图7.6

  33. 据此写出以下程序: main() { int i,j, row=0, colum=0, max; static 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<=3; j++) if (a[i][j]>max){max=a[i][j]; row=i; colum=j;} printf( "max=%d,row=%d, colum=%d\n ", max, row, colum); } 输出结果为: max=10, row=2, colum=1

  34. §7.3 字符数组 用来存放字符数据。字符串–––用字符数组存放。 7.3.1字符数组的定义 char c[10]; 大小 数组名 类型名 1. 初始化:  直接给出字符串中的各字符 static char a[4]={' G ', ' o ', ' o ', ' d '}; 若字符多于元素个数,则语法错。

  35. 可以去掉定义时的大小设置,而通过自动赋值决定 长度(大小)可以去掉定义时的大小设置,而通过自动赋值决定 长度(大小) static char x[ ]={' I ', ' ', ' a ', ' m ', ' ', 'a', ' ', ' s ', ' t ', ' u ', ' d ', ' e ', ' n ', ' t '};  前面说过,字符串常量用“ ” 表示,且由‘ \0’结尾. static char x[ ]={"I am a student. "}; 则长度为15+1=16, 其中x[15]存放‘\0’,其中 { }亦可省略。 2. 字符数组的引用 每一个字符数组元素相当于一个字符变量。

  36. 7.3.2 字符数组的输入输出 格式符: %c –––逐个输入/输出字符。 %s ––– 整个串一次输入/输出。 1. 输出 (用%s) 用%s输出时,不输出‘\0’。 在printf中须直接写数组名. static char c[ ]={"I am a student"}; printf("%s", c);

  37.  若数组长度大于字符串长度,则遇到‘ \0’ 即停止输出 static char c[10]=" china"; printf(" %s", c);  输出时遇到第一个‘ \0’即结束。

  38. 2. 输入(用%s)  输入字符串时,系统自动加上‘ \0’  输入多个字符串,可用空格隔开。 Static char str1[5], str2[5], str3[5]; scanf(" %s%s%s", str1, str2,str3); 则:输入 How are you? str1: H o w \0 str2: a r e \0 str3: y o u \0

  39. str: H o w \0 …… 只能输入不包括空格、\t和\n的字符串 若: static char str[13]; scanf("%s", str); 输入: How are you  则只会将How输入,且存为  scanf中须用地址量,数组名表示地址量。

  40. 视C的版本而定 7.3.3 字符串处理函数 在使用1、2字符串函数时要包含头文件“stdio.h”。 在使用3-6字符串函数时要包含头文件“string.h”。 1. puts(字符数组名) 输出一个字符串 • 例:static char str[ ]={" China\nBeijing"}; • puts(str); • 输出:China Beijing • 字符串中可包含转义字符 • \0自动转换为\n

  41. 2. gets(字符数组名) 功能:输入一个字符串到字符数组 • 例:static char c[6]; • gets(c); • 输入:China↙ • 数组c在内存中实际存放情况为: 串长=5 C H I N A \0 c[0] c[1] c[2] c[3] c[4] c[5]

  42. x y ... z \0 a b c d e f g \0 3. strcat(字符数组名1,字符数组名2) 功能:连接两个字符数组中的字符串,串2接在串1的后面 str2 • 例:char str1[30]=“xyxyz”;char str2[]=“abcdefg”; printf(“%s”,strcat(str1,str2)); • 输出: xyxyzabcdefg • 字符数组1要足够长。 • 根据字符串1中 \0 的位置进行字符串连接。 • 关键:要用str2的第1个字符覆盖str1的串结束标记\0。 ... ... ... a b c d e f g \0 str1

  43. a b ... ... ... f g \0 4. strcpy(字符数组名1,字符串2) 功能:将字符串2复制到字符数组1中去 • 例:char str1[10] ;char str2[10]=“abcdefg”;strcpy(str1,str2); printf(“%s”,str1); • 输出: abcdefg 没有必要复制整个数组,根据字符串中 \0 的位置,只对\0前面的字符进行复制。 字符串2可以是字符串常量 例: strcpy(str1, "China"); str1 ... ... ... str2 a b ... ... ... f g \0

  44. 5. strcmp (字符串1,字符串2) 功能:比较字符串1和字符串2 确定字符串大小的基本规则:按照串中对应位置字符的ASCII码值的大小确定大小。 例如:”abc” < ”b”因为字符 a < b ”abc” > ”abadef”因为字符 c > a 例:strcmp(str1,str2); strcmp(“China”,”Korea”); strcmp(str1,”beijing”);

  45. 结果由函数值带回: 字符串1=字符串2,函数值为0;字符串1>字符串2,函数值为正;字符串1<字符串2,函数值为负; 例:当str1=str2时,打印输出“yes” if(str1==str2) printf(“yes”); × if(strcmp(str1,str2)==0) printf(“yes”); √

  46. 6. strlen(字符数组名) 功能:测试字符串长度 例:char str [10] =“China”;printf(“%d”,strlen(str)); 输出结果: 5

  47. 7.3.4 字符串数组举例 例:输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。 程序如下:

  48. # include "stdio.h" main ( ) {char string[81]; int i, num=0, word=0; char c; gets (string); for (i=0; (c=string[i])!= '\0 '; i++) if ( c= = ' ')word=0; else if (word = =0) {word=1; num++;} printf("There are %d words in the line \n ", num); }

  49. 运行情况如下: I am a boy. There are 4 words in the line

  50. length=0 length=1 length=2 a b c d e f g \0 串长 例:求字符串长度 • 根据字符串中 \0 的位置来计算字符串长度。 • 若:数组中第i 个元素为\0,则,串长=i。 • #include <stdio.h> • main ( ) • { intlength; • char line[100]; • gets(line); • length=0; • while( line[length] != ’\0’) • length++; • printf (”String length=%d”, length); • } length=7

More Related