42
第第第 第第 第第第第 第第 : 1 第第 第第第第第第第第第第 一、 2. 第第第第第第第第第第 3. 第第第 第第第第第第第

第七章 数组

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: 第七章    数组

第七章 数组本章重点、难点 :

1 、一维、多维数组的定义和引用

2. 字符数组的定义和引用

3. 冒泡法、字符串处理函数

Page 2: 第七章    数组

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

如:十个整型变量 k[0],k[1], … k[9]

一个下标。

数组名。

Page 3: 第七章    数组

数组必须先说明后使用。说明的目的如下:⒈ 说明数组的名字。⒉ 说明数组的类型。⒊ 说明数组的维数。⒋ 确定各下标的变化范围。

编译系统将根据说明,开辟内存单元按特有的顺序和相应的类型为各元素分配内存单元。

Page 4: 第七章    数组

7.1 一维数组⒈一维数组的说明

说明方式: type array1[ 常量表达式 ], …, arrayn[ 常量表达式 ] ;

类型说明符,说明数组的类型。数组名,用标识符命名。

数组的元素的个数,数组的下标从 0 变化到常量达式的值减一。

int id[5], iyear[10];float fScore[36];

当说明数组后,编译时系统会根据定义的类型分配连续的一段内存单元给数组的各元素。

id[0]

id[1]id[2]id[3]id[4]

系统为数组分配的连续内存单元,每个单元占两个 BYTE 。首地址用数组名表示。

Page 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!

Page 6: 第七章    数组

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 一维数组

Page 7: 第七章    数组

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 一维数组

Page 8: 第七章    数组

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 一维数组

Page 9: 第七章    数组

⒋ 举例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 一维数组

Page 10: 第七章    数组

2) 排序的概念 排序是将一组随机排放的数按从大到小或从小

到大重新排列。

1 , 5 , 4 , 6 , 7 , 9

9 , 7 , 6 , 5 , 4 , 1

1 , 4 , 5 , 6 , 7 , 9

降序

升序

3) 冒泡排序算法 用冒泡法的思路是 ( 由小到大 ):将相邻两个数比较,将小的调到前头。

7.1 一维数组

Page 11: 第七章    数组

冒泡排序程序如下: ( 由小到大)#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.1 一维数组

Page 12: 第七章    数组

7.2 多 维 数 组

在实际应用中,经常会遇到一些用多维索引的数据。如:四个学生三门课的成绩。可以用下表表示:

92.5 80.5 91.0

99.0 83.5 90.0

70.0 66.0 60.0

78.0 56.0 59.0

显然,该表的每一项需要有两个索引项。表现为数组的两个下标。超过一个下标的数组称为多维数组。

行:代表某个学生。

列:代表某门课程。

Page 13: 第七章    数组

⒈ 多维数组的说明说明方式: type array[ 常量表达式 1]…[ 常量表达式 n] ;

n 个 整 型 常 量 表 达 式

int a[3][4] ; 定义为 3X4( 3 行 4 列的数组)int b[5][10];定义为 5X10( 5 行 10列的数组)

7.2 多 维 数 组

注意:不能写成float a[3,4],b[5,10] ; ERROR!

Page 14: 第七章    数组

注意理解二维数组: 我们可以把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。例如,可以把 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 语言的这种处理方法在数组初始化和用指针表示时显得很方便,这在以后会介绍。

7.2 多 维 数 组

int b[2][3][4]; 数组元素的个数?

Page 15: 第七章    数组

⒉ 多维数组在内存中的顺序按行存放:即先顺序存放第一行的元素,再存放第二行的元素。

int a[2][3] ;二维结构:a[0][0] a[0][1] a[0][2]a[1][0] a[1][1] a[1][2]

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

下标为0的行

总原则:最后一个下标先变化,变化一个周期后,倒数第二个开始变化,…如此类推。

a 为数组在内存中的首地址。

int b[2][3][4];

内存中的排列?

7.2 多 维 数 组

Page 16: 第七章    数组

2. 二维数组的引用 二维数组元素的表示形式为: 数组名 [ 下标 ][ 下标 ]

例: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 多 维 数 组

a[2][3] 正确!

a[2,3] 错误!

Page 17: 第七章    数组

⒊二维数组赋初值⑴ 全部赋初值

int a[2][3]={{1,2,3},{4,5,6}}; 分行赋初值

下标为 0 的一行下标为 1 的一行

int b[2][3]={1,2,3,4,5,6} ;所有数组写在一个花括弧内

⑵ 部分赋初值int a[2][3]={ {1} , {2} } ;

0 行的 0 列的元素赋初值。其余值为 0 。

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 多 维 数 组

数组中各元素的值?

Page 18: 第七章    数组

例 1:将一个二维数组行和列元素互换,存到 另一个二维数组中要解决的关键问题:二维数组的初始化二维数组的输出行列互换

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. 举例

Page 19: 第七章    数组

4. 举例7.2 多 维 数 组

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); } 实例运行

2、有一个 3 X 4的矩阵,要求编程序求出其中最大值,以及最大值所在的行号和列号

Page 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 个元素

Page 21: 第七章    数组

7.3 字 符 数 组注意:如果花括弧中提供的初值个数(即字符个数)大于数组长度,则作语法错误处理。如: 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’};

h e l l oStr1在内存中的存放形式: 注:一般情况下,说明数组时,长度指定应至少比实

际长度大 1,保证赋初值正确。

Page 22: 第七章    数组

二维数组赋初值二维数组的每一行可以存放一个字符串。 char str[3][6]={{‘w’,‘a’,‘n’,‘g’,} , {‘z’,‘h’,‘a’,‘n’,‘g’},

{‘l’,‘i’,‘u’}};

w a n g \0 \0

z h a n g \0

l i u \0 \0 \0

str 数组在内存中存储形式

7.3 字 符 数 组

Page 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"); } }

实例运行

可以引用字符数组中的一个元素,得到一个字符。例:输出一个钻石图形。

* * ** * * * *

Page 24: 第七章    数组

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

Page 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’};

Page 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'};

Page 27: 第七章    数组

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 字 符 数 组

Page 28: 第七章    数组

5. 字符数组的输入输出7.3 字 符 数 组

注意以下几点:(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);

输出的内容是 ?

Page 29: 第七章    数组

5. 字符数组的输入输出7.3 字 符 数 组

(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

完成表格的填写 ?

Page 30: 第七章    数组

使用 scanf函数时要注意以下几点 : ①由于系统把空格作为输入的字符串之间的分隔符,因此输入带空格的字符串,会造成输入不全。例:

void main(){char a[20];scanf("%s",a);printf("%s",a);}

输入: China Anhui Hefei

输出 a 的内容是: China

Page 31: 第七章    数组

②scanf函数中的输入项如果是字符数组名,不要再加地址符,因为在 C 语言中数组名代表该数组的起始地址。 char str[20];

scanf(“%s”,&str); error

例:以八进制形式输出数组的起始地址。 void main()

{char str[20];

printf("%o",str);

}

Page 32: 第七章    数组

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 字 符 数 组

Page 33: 第七章    数组

说出以下程序实现的功能

#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 字 符 数 组

Page 34: 第七章    数组

(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. 字符串处理函数

C 语言还定义了一系列的字符处理函数用于字符串的处理,该类函数的原型定义在 string.h中。因此,在使用该类函数时,应在程序的开始处,加 #include <string.h>

Page 35: 第七章    数组

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

7.3 字 符 数 组6. 字符串处理函数

A n h u i \0 \0 \0 \0 \0 \0 \0 \0 \0

H e f e i \0

A n h u i H e f e i \0 \0 \0 \0

str1

str2

str1

Page 36: 第七章    数组

(5) 测试字符串长度函数 strlen(str)

作用:测试字符串的实际长度。函数运算得到整型值,该值是字符串的长度,不包含‘ \0’ 在内。

int iLenStr;char str[10 ]={“China”};iLenStr=strlen(str);printf(“%d”,iLenStr);

结果?

7.3 字 符 数 组6. 字符串处理函数

(6) strlwr(str) 将 str 中的大写字母转换成小写字 母。(7) strupr(str) 将 str 中的小写字母转换成大写字 母

Page 37: 第七章    数组

#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);} 实例运行

6. 字符串处理函数

Page 38: 第七章    数组

(8) 字符串的比较 strcmp ( str1 , str2 ) 作用:对 str1 和 str2 自左至右逐个字符比较(按Ascii码值大小比较),直到对应位字符能够确定关系或到串尾为止。返回整型比较结果。比较结果如下:

比较结果 strcmp 的值str1<str2 <0

str1==str2 ==0

str1>str2 >0

char str1[ ]={”abcd”};char str2[ ]={“abcd”};int iRe1,iRe2,iRe3;iRe1=strcmp(str1,”abdc”);iRe2=strcmp(str1,str2);iRe3=strcmp(”abcde”,str2);

abcd abdcc d

‘c’<’d’ 结果小于 0。

Page 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);}

行循

环 列循

实例运行

Page 40: 第七章    数组

例:输入一行字符,统计其中有多少个单词,各单词之间用空格分隔开。

思路:单词的数目可以由空格出现的次数决定(连续若干个空格作为出现一次空格)。设置一标志 word表示是不是一个单词的开始,前

面一个字符是否是空格可以从 Word的值看出来,若word等于 0 ,则表示前一个字符是空格;若 word等于 1 ,则表示前一个字符不是空格。

当前字符 = 空格Y

N

未出现新单词, num不累加,但应使 word=0

word=0(即前一字符为空格),新单词出现, num++,word=1

word=1(前一字符为非空格 ) ,未出现新单词, word仍为 1

Page 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

Page 42: 第七章    数组

课堂作业

1.已知两整型数组 a1, a2,… ,a10 b1, b2,… ,b10 试计算 s=a1*b1+a2*b2+…+a10*b10

2.求一维数组 a[20]中的最大值,最小值,平均值,并输出所有大于平均值的数组元素。