第七章 数组任课老师:台安返回下一页上一页第七章 数组第七章 数组
数组:数组是一组有序数据的集合,数组中每一个元素的类型相同。数组是构造类型,元素由基类型(整、实、字符)组成。用数组名和下标来唯一确定数组中的元素
7.1 一维数组的定义和引用
7.2 二维数组的定义和引用
7.3 字符数组返回下一页上一页第七章 数组要求:
1、数组名、数组元素的概念。
2、数组的初始化方法。
3、数组元素在内存中的存储顺序。
4、数据排序算法。
5、字符串的特点
6、字符串处理函数的应用。
返回下一页上一页第七章 数组
§ 7.1 一维数组的定义和引用
7.1.1 一维数组的定义
形式,类型说明符 数组名 [常量表达式 ]
如,int a[5]; float b[10];
说明:
1.命名规则:数组名是由合法的标识符组成。
2.数组名后的括号 [ ] 内是常量表达式
例,int a[10]
定义一个数组,数组名 a,有 10个元素,每个元素的类型均为 int。
这 10个元素分别是,a[0],a[1],a[2],a[3]、
a[4],....,a[8],a[9]。 注意:下标是从零开始。
返回下一页上一页第七章 数组例:
说明以下数组的定义是 否正确?
int a[2+3],b[5],c[?a?],_d[8]
int a(10),b[x],%[5],8[3],x-y[50],5x[100]
int i=5; int a[5+i]
3.数组的长度 int a[5]
a[0],a[1],a[2],a[3],a[4]
5个元素,下标从 0 ~ 4 。
返回下一页上一页第七章 数组例 7.1
main( )
{int i,a[5];
for(i=0;i<=4;i++)
{ a[i]= i+ 1 ;
printf (“a[%d]=%d\ n”,i,a[i]);
}
}
运行结果:
a[0]=1
a[1]=2
a[2]=3
a[3]=4
a[4]=5
返回下一页上一页第七章 数组
4.数组大小的定义只能是常量,而不能是变量或动态地定义。
例 7.2:
main( )
{ int n=5,a[n];
a[1]=100;
printf (“a[1]=%d\n”,a[1]);
}
编译时指出,constant
expression required in
function main ( 主函数中要求常量表达式)
注意:
( 1) C语言中,数组下标从 0开始,
( 2) C语言不允许对数组的大小做动态定义,如:
返回下一页上一页第七章 数组
7.1.2 一维数组元素的引用
引用规则:
1.先定义,后使用。
2.引用形式:数组名 [下标 ]
3.下标可以是整、字符型的常量、变量或表达式。
3.引用方法:对具体元素而不是整个数组。 如:
int a[10]
a[0]=a[?b? -?a?] + a[? b? -96] +a[3] - a[2*2]
相当于:
a[0]=a[1]+ a[2]+ a[3]- a[4]
返回下一页上一页第七章 数组例 7.3:对数组 a 顺序赋值,逆序输出
main( )
{ int i,a[5];
for(i=0; i<=4; i++)
a[i]=i;
for(i=4;i>=0;i- -)
printf(,a[%d]=%d\t”,i,a[i ]);
}
运行结果:
a[4]=4 a[3]=3 a[2]=2 a[1]=1 a[0]=0
返回下一页上一页第七章 数组
7.1.3 一维数组的初始化实现的方法有:
1.定义时对数组元素初始化如,static int a[5]={1,2,3,4,5};
2,初始化时只给部分元素赋值如,int a[5]={1,3,5}; 则只对前三个元素赋初值
3,初始化时给全部元素赋 0值如,static int a[5]={0,0,0,0,0};
或 static int a[5] (静态型数组自动赋初值零)
4,对全部元素赋初值时可以不指出长度 如:
static int a[5]={2,4,6,8,10};
或 static int a[ ]={2,4,6,8,10}; 效果一样。
错例,static int b[ ]; /*没有指出长度,为无效定义。 */
返回下一页上一页第七章 数组例 7.4:定义时对数组元素初始化
main( )
{ int i;
static int a[5]={2,4,6,8};
for(i=0;i<=4;i++)
printf(“%d\n”,a[i]+1);
}
运行结果:
3
5
7
8
1
返回下一页上一页第七章 数组
7.1.4 一维数组程序举例
例 7.5,求 Fibonacci 数列问题 关于菲波那契算法:
头两个数各为 1,以后的每个数皆为前两个数之和。
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]);
}
}
返回下一页上一页第七章 数组例 7.6用起泡法对 6个数排序
思路,将相邻两数两两比较,若小则调到前头,不小也要比较
n=6
设外层循环变量 j,(1~n-1)次
内层循环变量 i (1~n-j)次返回下一页上一页第七章 数组排序的过程示意
9
8
6
4
2
0
8
6
9
4
2
0
8
9
6
4
2
0
8
6
4
9
2
0
8
6
4
2
9
0
8
6
4
2
0
9
第一轮最大数沉底
J=1 I=1 to 5
6
8
4
2
0
9
6
4
8
2
0
9
6
4
2
8
0
9
6
4
2
0
8
9
第二轮的最大数沉底
8
6
4
2
0
9
J=2 I=1 to 4 第三轮的最大数沉底 J=3 I=1 to 3
4
6
2
0
8
9
4
2
6
0
8
9
4
2
0
6
8
9
4
2
0
6
8
9
2
4
0
6
8
9
2
0
4
6
8
9
J=4 I=1 to 2
第四轮的最大数沉底
2
0
4
6
8
9
0
2
4
6
8
9
J=5 I=1 to 1
第五轮的最大数沉底返回下一页上一页第七章 数组交换的过程示意返回下一页上一页第七章 数组例 7.6排序源程序
main( )
{ int a[7]; int i,j,t; /* 用 a[1]~ a[6],a[0]不用 */
printf (,input 6 numbers:\ n”) ; /* i,j作循环变量,t作两两比较的临时变量 */
for( i=1;i<=6;i++)
scanf(,%d”,&a[i ]) ; /* 输入 6个整数 */
printf (,\ n”) ;
for( j=1; j<=5; j++) /* 第 j趟比较 */
for( i=1; i<=6-j; i++) /* 第 j趟中两两比较 6-j次 */
if( a[i]>a[i+1])
{t=a[i]; a[i]=a[i+1]; a[i+1]=t;} /* 交换大小 */
printf (“the sorted numbers:\ n”);
for( i=1;i<7;i++) printf(,%d _ _”,a[i]) ;
}
返回下一页上一页第七章 数组
§ 7.2 二维数组的定义和引用
7.2.1 二维数组的定义
1.一般形式:
类型说明符 数组名 [常量表达式 ][常量表达式 ]
如,float a[3][4]
定义了数组 a具有三行四列的二维数组,
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
返回下一页上一页第七章 数组
2.二维数组各个元素在内存中的存放顺序
二维数组各个元素在内存中的存放顺序是,按先行后列的顺序依次存放
二维数组 a[3][4]理解为:有三个元素 a[0],a[1],a[2],
每一个元素是一个包含 4个元素的数组。
返回下一页上一页第七章 数组例 7.7输出二维数组每个元素的值
main( )
{ int i,j,a[2][3];
for(i=0; i<2; i++)
for(j=0; j<3; j++)
scanf(“%d”,&a[i][j]);
for(i=0; i<2;i++)
for(j=0;j<3;j++)
{ printf(“&a[%d][%d]=%x,,i,j,&a[i][j]);
printf (“a[%d][%d]=%d\n”,i,j,a[i][j]);
}
}
输入,1 3 5 7 9 11?
输出:
&a[0][0]=ffce a[0][0]=1
&a[0][1]=ffd0 a[0][1]=3
&a[0][2]=ffd2 a[0][2]=5
&a[1][0]=ffd4 a[1][0]=7
&a[1][1]=ffc6 a[1][1]=9
&a[1][2]=ffd8 a[1][2]=11
返回下一页上一页第七章 数组
3.多维数组的定义和在内存中的存放顺序
如 int a[2][3][4]; 共 24个元素,
在内存中排列的顺序是:
第三维变化最快,
然后是第二维,
第一维最慢。
a[0][0][0]→a[0][0] [1]→a[0][0] [2]→a[0][0] [3]→
a[0][1][0]→a[0][1][1]→a[0][1][2]→a[0][1][3]→
a[0][2][0]→a[0][2][1]→a[0][2][2]→a[0][2][3]→
a[1][0][0]→a[1][0][1]→a[1][0][2]→a[1][0][3]→
a[1][1][0]→a[1][1][1]→a[1][1][2]→a[1][1][3]→
a[1][2][0]→a[1][2][1]→a[1][2][2]→a[1][2][3]
返回下一页上一页第七章 数组
7.2.2 二维数组的引用
1.形式:数组名 [下标 ][下标 ]
float a[2][3]; 有 6个元素,按如下方式引用各元素:
a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2]
注意:数组 float a[2][3]中无元素 a[2][3]。( 下标从
0始)
2,使用数组元素时,应注意不要超出其定义的范围;
如,int a[2][3];
a[2][3]=5; /*将损坏内存中数组后面的数据 */
下标是整型或字符型的常量,变量或表达式。(定义时不能使用变量)
返回下一页上一页第七章 数组
7.2.3 二维数组的初始化
1.按行给二维数组赋初值
如,static int a[2][3]={{1,2,3},{4,5,6}};
2.按数组元素排列的顺序赋初值
如,static int a[2][3]={1,2,3,4,5,6};
3.对部分元素赋初值,按行赋值较直观
如,static int a[2][3]={{2,5},{3}};
4.全部元素赋值时,第一维下标可省略
如,static int a[ ][3]={1,2,3,4,5,6};
又如,static int a[ ][4]={{0,0,3},{0},{0,10}};
返回下一页上一页第七章 数组
7.2.4 二维数组程序举例
将一个二维数组的行和列元素互换,存到另一个二维数组中
算法,b[j][i] = a[i][j]
返回下一页上一页第七章 数组例 7.8 两数组行列互换
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(“%4d”,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(“%4d”,b[i][j]);
printf("\n")
}
}
返回下一页上一页第七章 数组例 7.9:有 3 X 4矩阵,求出其中最大元素所在的行号和列号
main( )
{ int i,j,r=0,c=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]; r=i;c=j;}
printf(“max=%d,row=%d,colum=%d\n”,max,r,c);
}
运行结果,max=10,row=2,colum=1
问题:在比较前为什么要把a[0][0]赋给 max?
随便送一个数给max行不行?
返回下一页上一页第七章 数组
7.3 字符数组
字符型数组:用于存放字符型数据。
一维字符数组:存放一个字符串(每个数组元素存放一个字符)
二维字符数组:存放多个字符串(行数是字符串的个数)
7.3.1 字符数组的定义
形式,char 数组名 [常量表达式 ]
char 数组名 [常量表达式 ][常量表达式 ]
例,char c1[10];
返回下一页上一页第七章 数组
7.3.2 字符数组的初始化
static char a[5]={?C?,?H?,?I?,?N?,?A?};
static char b[5]={?C?,?H?,?I?,?N?,?A?,?U?};
编译时将指出:初始化值太多
static char c[5]={?C?,?H?,?I?};
static char d[ ]={?C?,?H?,?I?,?N?,?A?}
系统自动确认其长度为 5
注意:
字符型与整型可以通用,但有区别:
char c[10]; /* 在内存中占 10字节 */
int c[10]; /* 在内存中占 20字节 */
返回下一页上一页第七章 数组
7.3.3 字符数组的引用
例 7.10,输出一个字符串,引用一个元素,得到一个字符。
main( )
{ static char c[10]=
{?I?,?_?,?a?,?m?,?_?,?h?,?a?,?p?,?p?,?y?};
int i;
for(i=0;i<10;i++)
printf(“%c”,c[i]);
print(“\ n”);
}
运行结果,I_am_happy
返回下一页上一页第七章 数组
[例 7.10b] 输出一个钻石图形
main()
{static 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 字符串和字符串结束标志
几点说明:
( 1)字符串:用双引号括起的若干字符,可将其存放在一维或两维字符型数组中。
char c1[ ]="I am happy";
( 2)字符串结束标志为:‘ \ 0 ’ (既无动作,又不显示 )
( 3)字符串的长度:指第一个‘ \ 0’以前字符的个数
( 4)在字符型数组或字符串中遇‘ \ 0’,即认为该字符结束;
( 5)用字符串可以对字符型数组初始化
如,static char c[ ]=,I_am_happy”;
系统自动在数组的最后加了‘ \ 0 ’,在内存中的存放长度为 11
static char c[] = {"China"};
static char c[5] = {“China”}; 字符串长度为 5,实际占用内存 6字节
static char c[10] = {“China”}; 字符串长度为 5,开辟内存空间 10字节返回下一页上一页第七章 数组例 7.11:
main( )
{ static char a[ ]={?a?,?b?,?\ 0?,?1?,?2?};
static char b[ ]=“ab\ 0cd” ;
printf (“%s\ n%s\ n”,a,b); }
运行结果:
a b
a b
返回下一页上一页第七章 数组
7.3.5 字符数组的输入输出
1.字符数组的输出:
%c:输出一个字符 以数组元素为单位
%s:输出一个字符串 以数组名为单位
例,
static char c[6];
scanf(“%c”,&c[0]); 输入一个字符给元素 c[0]
scanf(“%s”,c); 输入一个字符串给数组 c
printf(“%c”,c[0]); 输出元素 c[0]的值
printf(“%s”,c); 输出整个数组返回下一页上一页第七章 数组注意:
( 1)输出时,遇 '\0'结束,且输出字符中不包含 '\0'。
( 2),%s”格式输出字符串时,printf( )函数的输出项是字符数组名,而不是元素名。
(3),%s”格式输出时,即使数组长度大于字符串长度,遇 '\0'也结束。例、
static char c[10] = {"China"};
printf("%s",c); /*只输出 5个字符 */
( 4),%s”格式输出时,若数组中包含一个以上 '\0',遇第一个
'\0'时结束。
( 5)输入时,遇回车键结束,但获得的字符中不包含回车键本身( 0x0D,0x0A),而是在字符串末尾添‘ \0’。因此,定义的字符数组必须有足够的长度,以容纳所输入的字符。(如,输入
5个字符,定义的字符数组至少应有 6个元素)。
返回下一页上一页第七章 数组注意:
( 6)一个 scanf函数输入多个字符串,输入时以“空格”
键作为字符串间的分隔。例、
static char str1[5],str2[5],str3[5];
scanf("%s%s%s",str1,str2,str3);
输入数据,How are you?
str1,str2,str3获得的数据见下图返回下一页上一页第七章 数组注意:
( 7) C语言中,数组名代表该数组的起始地址,因此,scanf( )函数中 不需要 地址运算符 &。 (在 Turbo C中,加上 &运算符也可以 )。例、
static char str[13];
scanf("%s",str);
scanf(“%s”,&str);/*在 Turbo C中,加上 &运算符也可以 */
返回下一页上一页第七章 数组例 7_12,在一个输入函数中为多个字符型数组输入字符串
main( )
{ int i; static char a[10]=,CHINA” ;
static char b[18]=“CHINA\ 0CHINA\ 0CHINA” ;
for(i=0;i<10;i++)
printf(“%c”,a[i]);
printf (“\ n”);
printf (“%s\ n”,a);
for(i=0;i<18;i++)
printf (“%c”,b[i]);
printf(“\ n”);
printf (“%s\n”,b);
}
运行结果:
CHINA
CHINA
CHINA_CHINA_CHINA
CHINA
返回下一页上一页第七章 数组
2.字符数组的输入
如,char a[10]; scanf (,%s”,a);
其中,a:字符型的数组名,
字符数组名前不加地址运算符 &,
数组名代表数组的首地址返回下一页上一页第七章 数组示例 7_13
main( )
{ static char a1[5],a2[5],a3[5];
scanf (“%s%s%s”,a1,a2,a3);
printf(“a1=%s\ na2=%s\ na3=%s\ n”,a1,a2,a3);
/ * 输出数组的内容 */
printf (“&a1=%x\ n”,a1); /*输出数组 a1的首地址 */
printf (“&a2=%x\ n”,a2);
printf(“&a3=%x\n”,a3);
}
返回下一页上一页第七章 数组
6.3.6 字符串处理函数
1.字符串输出函数 形式:
puts(字符数组或字符串)
功能:输出一个字符串,且将‘ \ 0’换成‘ \
n? 。
例 7_14:
main( )
{ static char a1[ ]=“china\ nbeijing” ;
static char a2[ ]=“china\ 0beijing” ;
puts(a1); puts(a2); puts(“WUHAN” );
}
输出:
china
beijing
china
beijing
WUHAN
返回下一页上一页第七章 数组
2,字符串输入函数
形式,gets(字符数组)
功能,从键盘输入一个字符串到字符数组。
在输入过程中,遇,?” 结束,并将其转换为‘ \ 0’ 存入字符串尾部,对输入的空格,Tab键 作为有效字符存入字符型数组中。
返回下一页上一页第七章 数组例 7_15,gets 和 scanf 函数
用 gets 和 scanf 函数分别输入字符串,在
scanf 中遇‘ ’ 字符串便结束了,而
gets 中,却将‘ ’ 作为字符存入字符型数组中。
main( )
{ static char a1[15],a2[15] ;
gets(a1);
scanf(“%s”,a2);
printf (“a1=%s\ n”,a1);
printf (“a2=%s\ n”,a2);
}
输入:
china beijing?
china beijing?
输出:
a1=china beijing
a2=china
返回下一页上一页第七章 数组
3.字符串连接函数
形式,strcat(字符数组 1,字符数组 2)
功能:连接两个数组中的字符串。
操作:把字符数组 2中的内容(串 2)连接到字符数组 1的后面,结果是两串相加存放到字符数组 1中,使用时要考虑字符数组 1的容量要足够大。
例 7_16:
main( )
{ static char str1[30]={“People?s_Republic_of_” };
static char str2[ ]={“china” };
printf(“%s\ n”,strcat(str1,str2)); }
返回下一页上一页第七章 数组
4.字符串拷贝函数
形式,strcpy(字符数组 1,字符数组 2)
功能:将字符串 2(也可以是字符数组)拷贝到字符数组 1中,字符数组 1中原来的内容被覆盖。
例 7_17:
main( )
{ static char a1[8],a2[ ]=,china”,
a3[ ]=“wuhan” ;
strcpy(a1,a2);
strcpy(a2,a3);
strcpy(a3,,beijing” );
printf(“a1=%s\ na2=%s\ na3=%s\ n”,a1,a2,a3);
}
运行结果:
a1=china
a2=wuhan
a3=beijing
返回下一页上一页第七章 数组注意:
(1)字符串拷贝 不能 用赋值语句,=”,
错例,a1=a2;
(2)字符数组的元素可用赋值语句,
如,a1[1]=a2[1];
(3)字符数组初始化时可用,=”,其它地方对字符数组赋值时不能用,=”;
返回下一页上一页第七章 数组
5.字符串比较函数
形式,strcmp(字符串 1,字符串 2)
功能:两串按 Ascii码值从左向右逐个比较,直到出现不同字符或‘ \ 0’ 为止;
串 1 = 串 2 返回值为 0
串 1 > 串 2 返回值为正数 其值是
Ascii码的差值
串 1 < 串 2 返回值为负数 其值也是
Ascii码的差值返回下一页上一页第七章 数组例 7_18:
main( )
{ int i,j,k;
static char a1[ ]=“wuhan”,a2[ ]=“beijing” ;
i=strcmp(a1,a2); j=strcmp(“china”,“korea”);
k=strcmp(a2,“beijing” );
printf(“i=%d\ nj=%d\ nk=%d\ n”,i,j,k);
}
运行结果,i=21 i=w-b=119-98=21
j=-8 j=c-k=99-107=-8
k=0 k=b-b=98-98=0,e-e=101-
101=0….g -g=103-103=0
返回下一页上一页第七章 数组
6.求字符串长度函数
形式,strlen(字符数组 )
功能:检测字符串长度,返回字符串长度值,
不包括‘ \ 0’ ;
例 7_19:
main( )
{static char a1[10]=“china” ;
printf (“%d\n”,strlen(a1));
printf (“%d\n”,strlen(“beijing\ 0wuhan”));
}
运行结果,5 7
返回下一页上一页第七章 数组
7,大?小写字母转换函数,strlwr(字符串)
8,小?大写字母转换函数,strupr(字符串)
例 7_20:
main( )
{ static char a1[6]=“CHINA”,
a2[ ]=“wuhan” ;
printf (“%s\ n”,strlwr(a1));
printf (“%s\ n”,strupr(a2));
}
运行结果,china WUHAN
返回下一页上一页第七章 数组
7.7 字符数组应用举例
例 7_21:输入一行字符,统计其中有多少单词,
单词间用‘ _’ 分隔。
main( )
{ char s[81]; int i,n=0,w=0;
char c; gets(s);
for(i=0;(c=s[i])!=?\0? ; i++)
if(c= =?_? ) w=0;
else if(w= =0) {w=1; n++;}
printf(“There_are_%d words_in_the_line\ n”,n);
}
输入,I_am_a_boy,?
输出,There_are_4_word_in_the_line