420 likes | 508 Views
第七章 数组. 本章重点、难点: 1、 一维、多维数组的定义和引用 2.字符 数组的定义和引用 3. 冒泡法、字符串处理函数. 数组的概念. C 语言可以根据用户需要,用基本数据类型定义特殊性质的数 据类型,称为构造类型。构造类型有:数组、结构体、共同体。 数组:相同数据类型变量的有序集合。有序表现在数组元数在 内存中连续存放。 数组用一个名字作为标识。为区分各元素, 每个元素有一个用 整型表示的序号,称之为下标 。下标可以有多个,下标的个数称为 数组的维数。. 一个下标。.
E N D
第七章 数组 本章重点、难点: 1、一维、多维数组的定义和引用 2.字符数组的定义和引用 3. 冒泡法、字符串处理函数
数组的概念 C 语言可以根据用户需要,用基本数据类型定义特殊性质的数 据类型,称为构造类型。构造类型有:数组、结构体、共同体。 数组:相同数据类型变量的有序集合。有序表现在数组元数在 内存中连续存放。 数组用一个名字作为标识。为区分各元素,每个元素有一个用 整型表示的序号,称之为下标。下标可以有多个,下标的个数称为 数组的维数。 一个下标。 如:十个整型变量k[0],k[1], … k[9] 数组名。
数组必须先说明后使用。说明的目的如下: ⒈说明数组的名字。 ⒉说明数组的类型。 ⒊说明数组的维数。 ⒋确定各下标的变化范围。 编译系统将根据说明,开辟内存单元按特有的顺序和相应的类型为各元素分配内存单元。
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]
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!
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.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};
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。
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 ]); } } 说明数组。 循环输入各元素的值并累加。 循环判断条件,满足条件输出。 实例运行
7.1 一维数组 2) 排序的概念 排序是将一组随机排放的数按从大到小或从小到大重新排列。 9,7,6,5,4,1 降序 1 ,5,4,6,7,9 1,4,5,6,7,9 升序 3) 冒泡排序算法 用冒泡法的思路是(由小到大): 将相邻两个数比较,将小的调到前头。
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变化 比较交换 实例运行
7.2 多 维 数 组 在实际应用中,经常会遇到一些用多维索引的数据。如:四个 学生三门课的成绩。可以用下表表示: 列:代表某门课程。 行:代表某个学生。 显然,该表的每一项需要有两个索引项。表现为数组的两个下 标。超过一个下标的数组称为多维数组。
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!
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]; 数组元素的个数?
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]; 内存中的排列?
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语言不作下标检查,语法正确,但使用危险,可能造成程序的错误!
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};
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: • 将一个二维数组行和列元素互换,存到另一个二维数组中 • 要解决的关键问题: • 二维数组的初始化 • 二维数组的输出 • 行列互换 实例运行
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); } 实例运行
7.3 字 符 数 组 C语言没有字符串变量,可以定义字符数组,每个元素存放一个字符,从而达到存放字符串的目的。 ⒈字符数组的说明 char 数组名[下标]; char a[10],b[2][12]; ⒉字符数组的初始化 一维数组赋初值:用单个字符对每一个元数赋值。 char str1[5]={ ’h’, ’e’, ’l’, ’l’, ’o’}; 把5个字符分别赋给str1[0]~str[4]这5个元素
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,保证赋初值正确。
7.3 字 符 数 组 二维数组赋初值 二维数组的每一行可以存放一个字符串。 char str[3][6]={{‘w’,‘a’,‘n’,‘g’,} , {‘z’,‘h’,‘a’,‘n’,‘g’}, {‘l’,‘i’,‘u’}}; str数组在内存中存储形式
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"); } } 实例运行
7.3 字 符 数 组 4. 字符串和字符串结束标志 • 在C语言中,将字符串作为字符数组来处理。 • 有效字符串的长度:为测定字符串的实际长度,C语言有一个“字符串结束标志”(‘\0’) 。例:有一个字符串,其第10个字符为‘\0’,则此字符串的有效字符为9个。系统对字符串常量也自动加一个‘\0’作为结束符。 • 在定义字符数组时应估计实际字符串长度,使数组长度始终保证大于字符串实际长度。 char str1[6]={ ’h’, ’e’, ’l’, ’l’, ’o’}; • 系统对字符串常量也自动加一个’\0’来作为结束符 例: “program”共有7个字符,但内存中占8个字节,最后一个字节’\0’是由系统自动完成的
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’};
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'};
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); /*整个字符串一次输入*/
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); 输出的内容是 ?
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
使用scanf函数时要注意以下几点: ①由于系统把空格作为输入的字符串之间的分隔符,因此输入带空格的字符串,会造成输入不全。例: void main() {char a[20]; scanf("%s",a); printf("%s",a); } 输入:China Anhui Hefei 输出a的内容是:China
②scanf函数中的输入项如果是字符数组名,不要再加地址符,因为在C语言中数组名代表该数组的起始地址。②scanf函数中的输入项如果是字符数组名,不要再加地址符,因为在C语言中数组名代表该数组的起始地址。 char str[20]; scanf(“%s”,&str); error 例:以八进制形式输出数组的起始地址。 void main() {char str[20]; printf("%o",str); }
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)
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); } 判断字符串结束。 实例运行
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
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
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中的小写字母转换成大写字母。
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); } 实例运行
(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。
举例:统计三行文字中大写字母、小写字母及数字的个数。举例:统计三行文字中大写字母、小写字母及数字的个数。 #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); } 行循环 列循环 实例运行
例:输入一行字符,统计其中有多少个单词,各单词之间用空格分隔开。例:输入一行字符,统计其中有多少个单词,各单词之间用空格分隔开。 思路:单词的数目可以由空格出现的次数决定(连续若干个空格作为出现一次空格)。 设置一标志word表示是不是一个单词的开始,前面一个字符是否是空格可以从Word的值看出来,若word等于0,则表示前一个字符是空格;若word等于1,则表示前一个字符不是空格。 未出现新单词,num不累加,但应使word=0 Y 当前字符=空格 word=0(即前一字符为空格),新单词出现,num++,word=1 N word=1(前一字符为非空格),未出现新单词,word仍为1
#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
课堂作业 1.已知两整型数组 a1,a2,…,a10 b1,b2,…,b10 试计算s=a1*b1+a2*b2+…+a10*b10 2.求一维数组a[20]中的最大值,最小值,平均值,并输出所有大于平均值的数组元素。