1 / 42

第七章 数组

第七章 数组. 本章重点、难点: 1、 一维、多维数组的定义和引用 2.字符 数组的定义和引用 3. 冒泡法、字符串处理函数. 数组的概念. C 语言可以根据用户需要,用基本数据类型定义特殊性质的数 据类型,称为构造类型。构造类型有:数组、结构体、共同体。 数组:相同数据类型变量的有序集合。有序表现在数组元数在 内存中连续存放。 数组用一个名字作为标识。为区分各元素, 每个元素有一个用 整型表示的序号,称之为下标 。下标可以有多个,下标的个数称为 数组的维数。. 一个下标。.

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. 第七章 数组 本章重点、难点: 1、一维、多维数组的定义和引用 2.字符数组的定义和引用 3. 冒泡法、字符串处理函数

  2. 数组的概念 C 语言可以根据用户需要,用基本数据类型定义特殊性质的数 据类型,称为构造类型。构造类型有:数组、结构体、共同体。 数组:相同数据类型变量的有序集合。有序表现在数组元数在 内存中连续存放。 数组用一个名字作为标识。为区分各元素,每个元素有一个用 整型表示的序号,称之为下标。下标可以有多个,下标的个数称为 数组的维数。 一个下标。 如:十个整型变量k[0],k[1], … k[9] 数组名。

  3. 数组必须先说明后使用。说明的目的如下: ⒈说明数组的名字。 ⒉说明数组的类型。 ⒊说明数组的维数。 ⒋确定各下标的变化范围。 编译系统将根据说明,开辟内存单元按特有的顺序和相应的类型为各元素分配内存单元。

  4. 7.1 一维数组 int id[5], iyear[10]; float fScore[36]; ⒈一维数组的说明 说明方式: type array1[常量表达式], …, arrayn[常量表达式]; 数组的元素的个数,数组的下标从0变化到常量达式的值减一。 数组名,用标识符命名。 类型说明符,说明数组的类型。 当说明数组后,编译时系统会根据定义的类型分配连续的一段 内存单元给数组的各元素。 id[0] 系统为数组分配的连续内存单元,每个单元占两个BYTE。首地址用数组名表示。 id[1] id[2] id[3] id[4]

  5. 7.1 一维数组 • 一维数组定义的几点说明: • 数组名命名规则和变量名相同,遵循标识符定名规则。 • 数组名后是用方括弧括起来的常量表达式,不能用圆括 弧. 如: int a (10); ERROR! • 常量表达式表示元素的个数,即数组长度。 如: a[10]有10个元素分别为: a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9];注意不能使用数组元素a[10]。 • 常量表达式中可以包括常量和符号常量,不能包含变量。也就是说,C语言不允许对数组的大小作动态定义。例如,下面这样定义数组是不行的: • int n; scanf("%d",&n); • int a[n]; ERROR!

  6. 7.1 一维数组 2. 数组的引用 原 则:只能引用数组元素,而不能引用整个数组。 引用方式:数组名[下标] 下标可以是整型常量或整型表达式。 每个数组元素,可以出现在简单变量能够出现的任何地方。 例: main () /* test1.c */ { int i,a[10]; for (i=0;i<=9;i++) a[i]=i; for(i=9;i>=0;i--) printf("%d",a[i]); } 实例运行

  7. 7.1 一维数组 3. 一维数组的初始化 • 对数组元素的初始化可以用以下方法实现: • 在定义数组时对数组元素赋以初值。例如 • int a[10]={0,1,2,3,4,5,6,7,8,9}; • 只给一部分元素赋值。例如 • int a[10]={0,1,2,3,4}; • 这表示只给前面5个元素赋初值,后5个元素值为0。 • 使一个数组中全部元素值为0 • int a[10]={0,0,0,0,0,0,0,0,0,0}; • 或 int a[10]={0}; • 不能写成:int a[10]={0*10};

  8. 7.1 一维数组 3. 一维数组的初始化 • 在对全部数组元素赋初值时,可以不指定数组长度。 例如: • int a[5]={1, 2,3,4,5}; • 可以写成: • int a[]={1,2,3,4,5}; • 如想定义数组长度为10,就不能省略数组长度的定义,而必须写成: • int a[10]={1,2,3,4 , 5}; • 只初始化前5个元素,后5个元素为0。

  9. 7.1 一维数组 ⒋举例 1) 求5个学生平均分,并输出低于平均成绩的分数。 #include <stdio.h> void main(void) { float fScore[5],aver=0; int i; for(i=0;i<5;i++) { printf(“input the score of %d :”,i+1); scanf(“%f”,&fScore[i]); aver+=fScore[i]; } aver/=5; printf(“the average=%f \n“,aver); for( i = 0; i < 5; i++) { if(fScore[ i ]<aver) printf(“num=%d,score=%f \n” ,i+1,fScore[ i ]); } } 说明数组。 循环输入各元素的值并累加。 循环判断条件,满足条件输出。 实例运行

  10. 7.1 一维数组 2) 排序的概念 排序是将一组随机排放的数按从大到小或从小到大重新排列。 9,7,6,5,4,1 降序 1 ,5,4,6,7,9 1,4,5,6,7,9 升序 3) 冒泡排序算法 用冒泡法的思路是(由小到大): 将相邻两个数比较,将小的调到前头。

  11. 7.1 一维数组 冒泡排序程序如下:(由小到大) #include <stdio.h> /* test3.c */ void main(void) { int i, j, a[10]={4,3,5,1,10,12,2,6,7,9}, iTemp; for(j=0; j<9 ;j++) for( i=0;i<9-j;i++) if(a[i]>a[i+1]) { iTemp=a[ i ]; a[ i ]=a[ i+1 ]; a[ i+1 ]=iTemp; } for(i=0;i<10; i++) printf(”%4d”,a[i]); } 外层循环i变化 内层循环j变化 比较交换 实例运行

  12. 7.2 多 维 数 组 在实际应用中,经常会遇到一些用多维索引的数据。如:四个 学生三门课的成绩。可以用下表表示: 列:代表某门课程。 行:代表某个学生。 显然,该表的每一项需要有两个索引项。表现为数组的两个下 标。超过一个下标的数组称为多维数组。

  13. 7.2 多 维 数 组 ⒈多维数组的说明 n个整型常量表达式 说明方式: type array[常量表达式1]…[常量表达式n] ; int a[3][4] ; 定义为3X4(3行4列的数组) int b[5][10];定义为5X10(5行10列的数组) 注意:不能写成 float a[3,4],b[5,10];ERROR!

  14. 7.2 多 维 数 组 注意理解二维数组: 我们可以把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。例如,可以把a[3][4]看作是一个一维数组,它有3个元素,每个元素又是一个包含4个元素的一维数组: a[0]a[0][0] a[0][1] a[0][2] a[0][3] 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] 上面定义的二维数组可以理解为定义了三个一维数组,即相当于 f1oat a[0][4],a[1][4],a[2][4] 此处把a[0],a[1],a[2]看作一维数组名。c语言的这种处理方法在数组初始化和用指针表示时显得很方便,这在以后会介绍。 int b[2][3][4]; 数组元素的个数?

  15. 7.2 多 维 数 组 ⒉多维数组在内存中的顺序 按行存放:即先顺序存放第一行的元素,再存放第二行的元素。 a为数组在内存中的首地址。 下 标 为 0 的 行 int a[2][3]; a[0][0] 二维结构: a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] a[0][1] a[0][2] a[1][0] a[1][1] 总原则:最后一个下标先变化,变化一个周 期后,倒数第二个开始变化,…如此类推。 a[1][2] int b[2][3][4]; 内存中的排列?

  16. 7.2 多 维 数 组 2. 二维数组的引用 二维数组元素的表示形式为: 数组名[下标][下标] a[2][3] 正确! a[2,3] 错误! 例: int a[10][10] ,y,i=2; a[i+2][6]=20; y=a[i+2][6]*100/30; a[10][11]=34; 对4行6列的元素赋值。 参加表达式运算。 C语言不作下标检查,语法正确,但使用危险,可能造成程序的错误!

  17. 7.2 多 维 数 组 ⒊二维数组赋初值 下标为0的一行 ⑴全部赋初值 下标为1的一行 int a[2][3]={{1,2,3},{4,5,6}}; 分行赋初值 int b[2][3]={1,2,3,4,5,6};所有数组写在一个花括弧内 ⑵部分赋初值 0行的0列的元素赋初值。其余值为0。 int a[2][3]={ {1} , {2} }; int a[2][3]={1,2}; int a[3][4]={{1},{5,6}}; int a[3][4]={{1},{ },{9}}; 数组中各元素的值? ⑶对全体数组元数赋初值,第一维下标可以省略。 int a[ ] [3]={1, 2, 3, 4, 5,6};

  18. 7.2 多 维 数 组 main() { int a[2][3]={{1,2,3},{4,5,6}}; 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"); } } 4. 举例 • 例1: • 将一个二维数组行和列元素互换,存到另一个二维数组中 • 要解决的关键问题: • 二维数组的初始化 • 二维数组的输出 • 行列互换 实例运行

  19. 7.2 多 维 数 组 4. 举例 2、有一个3 X 4的矩阵,要求编程序求出其中最大值,以及最大值所在的行号和列号 void 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<=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); } 实例运行

  20. 7.3 字 符 数 组 C语言没有字符串变量,可以定义字符数组,每个元素存放一个字符,从而达到存放字符串的目的。 ⒈字符数组的说明 char 数组名[下标]; char a[10],b[2][12]; ⒉字符数组的初始化 一维数组赋初值:用单个字符对每一个元数赋值。 char str1[5]={ ’h’, ’e’, ’l’, ’l’, ’o’}; 把5个字符分别赋给str1[0]~str[4]这5个元素

  21. 7.3 字 符 数 组 h e l l o 注意: • 如果花括弧中提供的初值个数(即字符个数)大于数组长度,则作语法错误处理。如: char str1[4]={ ’h’, ’e’, ’l’, ’l’, ’o’}; ERROR! • 如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自动为空字符(即‘\0’)。 char str1[10]={ ’h’, ’e’, ’l’, ’l’, ’o’}; • 如果初值个数与预定的数组长度相同,在定义时可以省略数组的长度,系统会自动根据初值个数确定数组长度。 • char str1[]={ ’h’ ,’e’ ,’l’ ,’l’, ’o’}; • 等价于:char str1[5]={ ’h’, ’e’, ’l’, ’l’, ’o’}; Str1在内存中的存放形式: 注:一般情况下,说明数组时,长度指定应至少比实际长度大1,保证赋初值正确。

  22. 7.3 字 符 数 组 二维数组赋初值 二维数组的每一行可以存放一个字符串。 char str[3][6]={{‘w’,‘a’,‘n’,‘g’,} , {‘z’,‘h’,‘a’,‘n’,‘g’}, {‘l’,‘i’,‘u’}}; str数组在内存中存储形式

  23. 7.3 字 符 数 组 3. 字符数组的引用 * * * * * * * * 可以引用字符数组中的一个元素,得到一个字符。 例:输出一个钻石图形。 main() { char diamond[][5]={{' ',' ', '*'},{' ','*',' ','*'}, {'*',' ',' ',' ','*'},{' ','*',' ','*'},{' ',' ','*'}}; int i,j; for(i=0;i<5;i++) { for(j=0;j<5;j++) printf("%c",diamond[i][j]); printf("\n"); } } 实例运行

  24. 7.3 字 符 数 组 4. 字符串和字符串结束标志 • 在C语言中,将字符串作为字符数组来处理。 • 有效字符串的长度:为测定字符串的实际长度,C语言有一个“字符串结束标志”(‘\0’) 。例:有一个字符串,其第10个字符为‘\0’,则此字符串的有效字符为9个。系统对字符串常量也自动加一个‘\0’作为结束符。 • 在定义字符数组时应估计实际字符串长度,使数组长度始终保证大于字符串实际长度。 char str1[6]={ ’h’, ’e’, ’l’, ’l’, ’o’}; • 系统对字符串常量也自动加一个’\0’来作为结束符 例: “program”共有7个字符,但内存中占8个字节,最后一个字节’\0’是由系统自动完成的

  25. 7.3 字 符 数 组 4. 字符串和字符串结束标志 • 可以用字符串常量来使字符数组初始化。例如: char c[ ]={"I am happy"}; 也可以省略花括号,直接写成: char c[ ]="I am happy"; 此时数组c的长度为多少? 注:数组的长度为11,而不是10,这是因为字符 串常量的最后由系统加上一个’\0’ 上面的初始化与下南的初始化等价: char c[ ]={’I’,’ ’,’a’,’m’,’ ’,’h’,’a’,’p’, ’p’,’y’,’\0’};

  26. 7.3 字 符 数 组 4. 字符串和字符串结束标志 需要说明的是: 1)字符数组并不要求它的最后一个字符为‘\0’,甚至可以不包含‘\0’。象以下这样写完全是合法的: charc[5]={'C','h','i','n','a'}; 是否需要加入‘\0’,,完全根据需要决定。但是只要用字符串常量就会自动加一个‘\0’。 2)人们为了使处理方法一致,便于测定字符串的实际长度以及在程序中作相应的处理,在字符数组中也常常人为地加上一个‘\0’。如: char c[6]={'C','h','i','n','a','\0'};

  27. 7.3 字 符 数 组 5. 字符数组的输入输出 ⑴输入输出函数有两种方法: 输出: for(i=0;i<STRLEN;i++) printf(“%c”,str[ i ]); /*逐个字符输入*/ printf(”%s”,str); /*整个字符串一次输出*/ 输入: for(i=0;i<STRLEN;i++) scanf(”%c”,&str[ i ]); /*逐个字符输入*/ scanf(”%s”,str); /*整个字符串一次输入*/

  28. 7.3 字 符 数 组 5. 字符数组的输入输出 注意以下几点: (1)输出字符不包括结束符‘\0’。 (2)用"%s"格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素名。 prinif("%s",c[0]);ERROR! (3)如果数组长度大于字符串实际长度,也只输出到遇‘\0’结束。 char c[10]={"China"}; printf("%s",c); (4)如果一个字符数组中包含一个以上‘\0’,则遇第一个‘\0,时输出就结束。 char a[10]={‘a’,’b’,’\0’,’d’,’k’,’\0’}; printf(“%s”,a); 输出的内容是 ?

  29. 7.3 字 符 数 组 5. 字符数组的输入输出 (5)可以用scanf函数输入一个字符串。 例如 : scanf(“%s”,c); /*输入项c是字符数组名*/ (6)如果利用一个scanf函数输入多个字符串,则以空格分隔。 例如:char str1[5],str2[5],str3[5]; scanf("%s%s%s",str1,str2,str3); 输入数据: How are you? Str1 完成表格的填写 ? Str2 Str3

  30. 使用scanf函数时要注意以下几点: ①由于系统把空格作为输入的字符串之间的分隔符,因此输入带空格的字符串,会造成输入不全。例: void main() {char a[20]; scanf("%s",a); printf("%s",a); } 输入:China Anhui Hefei 输出a的内容是:China

  31. ②scanf函数中的输入项如果是字符数组名,不要再加地址符,因为在C语言中数组名代表该数组的起始地址。②scanf函数中的输入项如果是字符数组名,不要再加地址符,因为在C语言中数组名代表该数组的起始地址。 char str[20]; scanf(“%s”,&str); error 例:以八进制形式输出数组的起始地址。 void main() {char str[20]; printf("%o",str); }

  32. 7.3 字 符 数 组 6. 字符串处理函数: C函数库中提供了一些用来处理字符串的函数 ⑴gets( )字符串输入函数 用法:读入一个以回车符为终结符的字符串到str中。(输入的字符串可带空格) char str [80]; gets(str); 数组名作为函数的参数。 ⑵puts( )字符串输出函数 用法: char string[ ]=”China”; puts(string); 作用:输出以‘\0’结尾的字符串,输完字符后自动换行。 数组名作为函数的参数。 注意:使用puts和gets函数只能输入或输出一个字符串。 不能写成: puts(str1,str2) 或 gets(str1,str2)

  33. 7.3 字 符 数 组 说出以下程序实现的功能 #include <stdio.h> void main(void) { char str[80]; int i; gets(str); for(i=0 ; str[ i ]!='\0'; i++) if(str[i]>='a'&&str[i]<='z') str[i] -=32; puts(str); } 判断字符串结束。 实例运行

  34. 7.3 字 符 数 组 6. 字符串处理函数 C语言还定义了一系列的字符处理函数用于字符串的处理,该类函数的原型定义在string.h中。因此,在使用该类函数时,应在程序的开始处,加#include <string.h> (3) 字符串拷贝函数strcpy(str1,str2) 作用:将str2拷贝到str1中。 char str1[10], str2[ ]={”Computer”}; strcpy(str1,str2); strcpy(str2,”Program”); 说明: • str1的长度要足够长; • str1只能是字符数组名,str2可以是字符数组或字符串常量。 • 拷贝时连同字符串后面的‘\0’一起拷贝到字符数组1中。 • 不能用赋值语句将一个字符串常量或字符数组直接赋给一个 字符数组。如: str1={“China”}; str2=str1; error

  35. 7.3 字 符 数 组 6. 字符串处理函数 (4) 字符串连接函数strcat(str1, str2) 作用:将str2连接到str1后(去掉str1的\0)。 用法: char str1[15]={“Anhui ”}, str2[ ]={”Hefei”}; strcat(str1,str2); puts(str1); /*输出结果为 Anhui Hefei */ 说明: ①str1的长度要足够长; ②str1只能是字符数组名,str2可以是字符数组或字符串常量。 str1 str2 str1

  36. 7.3 字 符 数 组 6. 字符串处理函数 (5) 测试字符串长度函数strlen(str) 作用:测试字符串的实际长度。函数运算得到整型值,该值是字符串的长度,不包含‘\0’在内。 int iLenStr; char str[10 ]={“China”}; iLenStr=strlen(str); printf(“%d”,iLenStr); 结果? • strlwr(str)将str中的大写字母转换成小写字母。 • (7) strupr(str)将str中的小写字母转换成大写字母。

  37. 6. 字符串处理函数 #include <stdio.h> /*test8.c*/ #include <string.h> void main(void) { char str1[ ]="c programming! 123", str2[ ]="Computer"; strlwr(str2); strupr(str1); puts(str1); puts(str2); } 实例运行

  38. (8) 字符串的比较 strcmp(str1,str2) 作用:对str1和str2 自左至右逐个字符比较(按Ascii码值大小比较),直到对应位字符能够确定关系或到串尾为止。返回整型比较结果。比较结果如下: abcd c abdc d char str1[ ]={”abcd”}; char str2[ ]={“abcd”}; int iRe1,iRe2,iRe3; iRe1=strcmp(str1,”abdc”); iRe2=strcmp(str1,str2); iRe3=strcmp(”abcde”,str2); ‘c’<’d’ 结果小于0。

  39. 举例:统计三行文字中大写字母、小写字母及数字的个数。举例:统计三行文字中大写字母、小写字母及数字的个数。 #include <stdio.h> /* test9.c */ #include <string.h> void main(void) { char str[3][20]; int i, j, iAnum=0, ianum=0,i0num=0; for(i=0; i<3 ; i++)gets(str[i]); for(i=0; i<3 ; i++) for(j=0; j<strlen(str[i]); j++) { if(str[i][j]>=‘A’&& str[i][j]<=‘Z’)iAnum++; if(str[i][j]>=‘a’&& str[i][j]<=‘z’)ianum++; if(str[i][j]>=‘0’&& str[i][j]<=‘9’)i0num++; } printf(“%6d,%6d,%6d”,iAnum,ianum,i0num); } 行循环 列循环 实例运行

  40. 例:输入一行字符,统计其中有多少个单词,各单词之间用空格分隔开。例:输入一行字符,统计其中有多少个单词,各单词之间用空格分隔开。 思路:单词的数目可以由空格出现的次数决定(连续若干个空格作为出现一次空格)。 设置一标志word表示是不是一个单词的开始,前面一个字符是否是空格可以从Word的值看出来,若word等于0,则表示前一个字符是空格;若word等于1,则表示前一个字符不是空格。 未出现新单词,num不累加,但应使word=0 Y 当前字符=空格 word=0(即前一字符为空格),新单词出现,num++,word=1 N word=1(前一字符为非空格),未出现新单词,word仍为1

  41. #include <stdio.h> main() {char ch[100],c; int i,num,word; word=0;num=0; gets(ch); for (i=0;(c=ch[i])!='\0';i++) {if (c==' ') word=0; else if (word==0) {num++; word=1; } } printf ("%d",num); } 自学:P151例7.9

  42. 课堂作业 1.已知两整型数组 a1,a2,…,a10 b1,b2,…,b10 试计算s=a1*b1+a2*b2+…+a10*b10 2.求一维数组a[20]中的最大值,最小值,平均值,并输出所有大于平均值的数组元素。

More Related