? 第一章 C语言概述
? 第二章 数据类型、运算符与表达式
? 第三章 最简单的 C程序设计
? 第四章 逻辑运算和判断选取控制
? 第五章 循环控制
? 第六章 数组
? 第八章 编译预处理
? 第九章 指针
? 第十章 结构体与共用体
? 第十二章 文件的基本操作
? 第十三章 位运算
前面所用到的数据均为基本类型 (整, 实,
字符 ),为了丰富数据类型, 须提供强有力的
数据表达方式 。 C语言提供了一种构造类型数
据 –––由基本类型按某一规则组合在一起 。
其中数组:同一种 (基本 )类型按一定顺
序组合在一起的数据类型 。
§ 6.1 一维数组
6.1.1 一维数组的定义
1,数组名的确定方法同变量名。
2,C语言用方括号 [ ]表示数组元数个数。
形式, 类型说明符 数组名 [常量表达式 ];
例, int a [20];
float x [100];
3,常量表达式为常量和符号常量。不允许有变量,
其表达式的值代表了元素的个数。
例, int a[20];
表示有 20个元素
元素的下标从 0开始,a[0],a[1]…,a [19]
4,可在定义时对数组赋初值,方法如下,
? 对部分元素赋初值 (前面的连续元素 )
static int a[10]={0,1,2,3,4};
静态
? 对全部元素赋初值
static int a[10]={10,11,12,13,14,15,16,17,
18,19}
注意,不能只对 部分元素 或 后面的连续元素 赋初值。
语句, static int a[10]={,,,,,1,2,3,4,5};
static int a[10]={1,,3,,5,,7,,9,,}; 是错误的。
在此,只有前 5个元素初值确定,后 5个元素由系统设置。
? 如对数组元素赋同一初值,必须一一写出,
static int a[10]={2,2,2,2,2,2,2,2,2,2};
不可写成, static int a[{10*2}];
? 若赋全部元素的初值,可省略常量表达式
a [ ]={0,1,2,3};
表示 a[4],即只有 4个元素。
6.1.2 一维数组的引用
2,引用方式, 数组名 [下标 ]
代表了一个元素,等价一个同类型的变量。
3,一般地,一维数组各元素分配在连续地内存单元
之中。
1,必须象使用变量那样,先定义,后使用
例, a [0]?5+a[1] ? 6 为正确的算术表达式
6.1.3 数组作为函数的参数
一,数组元素作为函数的参数
使用方法,把数组元素作为函数的实参。
由于数组元素的性质与相同类型的简单变
量的性质完全相同,因此,把数组元素作为函
数的参数也和简单变量一样。
作用,传值。
6.1.4 一维数组的应用
? 用循环 for求数列的后 18项,
for (i=2; i<20; i++)
f [i]=f [i –1]+f [i –2];
例 1,求 Fibonacci 数列的前 20项。 fi=fi-1+fi-2, 且 f1 = f2= 1。
? 定义数组,并赋初值
static int f [20]={1,1}; /*定义数组的前两个元素 */
注意,下标越界问题, i =2且 i<20
程序如下,
#include <stdio.h>
mian ( )
{ int i;
static int f [20]={1,1};
for (i=2; i<20; i++)
f [i]=f [i–1]+f [i–2];
for (i=0; i<20; i++)
{ if (i%5 = =0) printf("\n");
printf("%12d",f [i] ); }
}
1
8
89
987
5
55
610
6765
运行结果如下,
1
13
144
1597
2
21
133
1584
3
34
377
4181
例 2,将数组元素作为函数的实参数
/*----pro10_1.c----*/
#include <stdio.h>
#include <conio.h>
main( )
{ float b[3];
float ave;
b[0]=21.3;
b[1]=b[0]/3;
b[2]=8.2;
printf(" b[0]=%4.1f\t b[1]=%4.1f\t
b[2]=%4.1f\n",b[0],b[1],b[2]);
float Expfun1(float a,float b,float c); /*函数说明 */
ave=Expfun1(b[0],b[1],b[2]); /*函数调用 */
printf(" ave=%4.1f\n",ave);
printf(" b[0]=%4.1f\t b[1]=%4.1f\t
b[2]=%4.1f\n",b[0],b[1],b[2]);
getch();
}
float Expfun1(float a,float b,float c) /*函数定义 */
{
float sum,aver;
sum=a+b+c;
a=a+5.5;
b=b+5.5;
c=c+5.5;
aver=sum/3.0;
printf(" a=%4.1f\t b=%4.1f\t c=%4.1f\n",a,b,c);
return (aver);
}
程序运行结果,
b[0]=21.3 b[1]= 7.1 b[2]= 8.2 /*调用前 */
a=26.8 b=12.6 c=13.7
ave=12.2
b[0]=21.3 b[1]= 7.1 b[2]= 8.2 /*调用后 */
例 3:设有两个同样大小的一维数组,a[10],b[10]将相
应元素比较,统计 a中大于 b中对应元素的个数,小
于的个数,相等时的个数。
程序如下,
main ( )
{
int a[10],b[10],i,n=0,m=0,k=0;
printf("enter array a:\n");
for (i=0; i<10; I++)
scanf (5,"d",&a[i]);
printf ("\n");
printf("enter array b:\n");
for (i=0; i<10; i++)
scanf ("%d",&b[i]);
printf ("\n");
for (i=0; i<10; i++)
{ if (large (a[i],b[i])= =1) n=n+1;
else if (large (a[i],b[i])= =0) m=m+1;
else k=k+1;}
printf ("a[i]>b[i] %d times\na[i]=b[i] %d
times\na[i]<b[i] %d times\n",n,m,k);
if (n>k) printf("array a is larger than array b\n");
else if (n<k) printf("array a is smaller than array b\n");
else printf("array a is equal to array b\n");
}
int large(x,y)
int x,y;
{int flag;
if (x>y) flag=1;
else if (x<y) flag= –1;
else flag=0;
return (flag);
}
运行情况如下,
enter array a,
1 3 5 7 9 8 6 4 2 0?
enter array b,
5 3 8 9 –1 –3 5 6 0 4?
a[i]>b[i] 4 times
a[i]=b[i] 1 times
a[i]<b[i] 5 times
array a is smaller than array b
二、数组名作为函参数
使用数组名作为函数的参数时,形参和实参
必须是同一类型的数组名,系统采用地址传送方
式进行数据传递,即实参的首地址传递给形参的
首地址,实参与形参共享相同的数据单元。
使用方法,函数的实参和形参都必须是数组名。
作用,传址。
/*pro10_2.c*/
#include <stdio.h>
#include <conio.h>
main( )
{ float Expfun2(float a[4]); /*函数说明 */
float s[4]={88.5,90.5,70,71};
float ave;
printf(" s[0]=%4.1f\t s[1]=%4.1f\t s[2]=%4.1f\t
s[3]=%4.1f\n",s[0],s[1],s[2],s[3]);
ave=Expfun2(s); /*函数调用 */
printf(" ave=%4.1f\n",ave);
printf(" s[0]=%4.1f\t s[1]=%4.1f\t s[2]=%4.1f\t
s[3]=%4.1f\n",s[0],s[1],s[2],s[3]);
getch();
}
例 3,将数组名作为函数的形参和实参
float Expfun2(float a[4]) /*函数定义 */
{
float sum,aver;
sum=a[0]+a[1]+a[2]+a[3];
aver=sum/3.0;
a[0]=a[0]/10;
a[1]=a[1]/10;
a[2]=a[2]/10;
a[3]=a[3]/10;
printf(" a[0]=%4.1f\t a[1]=%4.1f\t a[2]=%4.1f\t
a[3]=%4.1f\n",a[0],a[1],a[2],a[3]);
return (aver);
}
s[0]=88.5 s[1]=90.5 s[2]=70.0 s[3]=71.0 /*调用前 */
a[0]= 8.9 a[1]= 9.1 a[2]= 7.0 a[3]= 7.1 /*调用中 */
ave=106.7
s[0]= 8.9 s[1]= 9.1 s[2]= 7.0 s[3]= 7.1 /*调用后 */
程序运行结果,
显然,数组 s元素的值在调用前后生了变化,
数组 s和 a共用一段内存单元,
88.5
90.5
70.0
71.0
?
s[0]
s[1]
s[2]
s[3]
a[0]
a[1]
a[2]
a[3]
运行结果分析,
使用超过函数定义大小的数组,会
出现一些意料外的情况,产生一些严重
的后果。
容易出现的错误,
例 5,/*---exp91.c---*/
#include<stdio.h>
main ( )
{ int i,a[3];
for (i=0; i<3; i++)
a[i]=i+1;
for (i=0; i<6; i++)
printf("a[%d]=%d\n",i,a[i]);
}
运行结果,a[0]=1
a[1]=2
a[2]=3
a[3]=0
a[5]=1827
a[4]=320 已超出数组大小
例 6,/*---exp91q.c---*/
#include<stdio.h>
main ( )
{ char a[3];
for (i=0; i<3; i++)
a[i]=i+65;
for (i=0; i<6; i++)
printf("a[%d]=%c,a[%d]=%d\n",i,a[i],i,a[i]);
}
int i;
运行结果,a[0]=A,a[0]=65
a[1]=B,a[1]=66
a[2]=C,a[2]=67
a[3]=,a[3]=0
a[5]=,a[5]=0
a[4]=,a[4]=0 已超出数组大小
§ 6.2 二维数组
6.2.1 二维数组的定义
1,不可将定义写为 int a[4,10]。
形式,类型说明符 数组名 [常量表达式 1] [常量表达式 2]
例, int a[4] [10];
float x[8] [20];
注意,
2,可将二维数组的元素看成为若干个特殊的一维数
组。
如, int b[3] [4];
可看成,有三个特殊的一维数组 b[0],b[1],b[2],
每一个又有四个元素,
b[0][0],b[0][1],b[0][2],b[0][3],
b[1][0],b[1][1],b[1][2],b[1][3],
b[2][0],b[2][1],b[2][2],b[2][3],
3,二维数组的存放方式为, 按行优先。由此可推广
至三维,n维数组的定义和存放。
即, 最右边的下标变化最快。
4,初始化,
? 按行给二维数组赋初值,
static int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
或,
static int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
? 可以对部分元素赋初值,但需表达清楚。如,
static int a[3][4]={{1,2},{3},{8}}。
则相当于 1 2 3 8
0 0 0 0
0 0 0 0
?可通过赋初值决定数组大小。如为二维,则只
可省略第一维的大小。
static int a[ ][4]={1,2,3,…,12};
若,static int [3][4]={1,2,3,8}
则相当于 1 2 0 0
3 0 0 0
8 0 0 0
6.2.2 二维数组元素的引用
形式, 数组名 [下标 1][下标 2]
其中的下标为整型表达式,但不得越界。
与一维数组元素一样,二维数组元素相当于同
类型的简单变量。
6.2.3 程序举例
a=
1 2 3
4 5 6 b=
1 4
2 5
3 6
程序如下,#include <stdio.h>
main ( )
{ static int a[2] [3]={{1,2,3},{4,5,6}};
static int b[3] [2],i,j;
例 1,将一个二维数组行和列元素互换,存到另一
个二维数组中。例如,
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"); }
}
运行结果如下,
array a,
1 2 3
4 5 6
array b,
1 4
2 5
3 6
? 数组元素数据的输入必须以循环方式
进行或者定义时置初值。
? 二维数组一般用二重循环
注意,
例 2,有一个 3× 4的矩阵,要求编程序求出其中值
最大的那个元素的值,以及所在的行号和列号。
先用 N- S流程图表示算法,见图 6.6
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
真 假
程序如下,
#include <stdio.h>
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
注意,要将二维数组作为函
数组的参数,可以把
二维数组看成一维数
组,然后进行参数传
递。
注意, 二维数组的元素在内存中是按先行后到的
顺序存放的,因此可以将二维数组看作是一
维数组。
例, 有一个 3?4的矩阵如下,
?
?
?
?
?
?
?
?
?
?
?
?
21043
7831
13946
要求, ? 打印出所有元素的和 ;
? 打印出所有大于平均值的元素。
#include<stdio.h>
#include<conio.h>
int add_ave(int m,int n,int arr[ ]);
void prt_up(int m,int n,float average,int arr[ ]);
main( )
{
int A[3] [4]={{6,4,9,?13},{?1,3,8,7},{3,4,10,2}};
int i=3,j=4,sum;
float ave;
sum=add_ave(i,j,A[0]);
printf ("The number or sum=%d\n",sum);
ave=(float)((sum)/(i?j));
printf ("The number or average=%5.2f\n",ave);
prt_up (i,j,ave,A[0]);
}
int add_ave(int m,int n,int arr[ ]);
{
int i;
int total=0;
for (i=0; i<m?n; i++)
total=total+arr[i];
return (total);
}
void prt_up(int m,int n,float average,int arr[ ])
{
int i,j;
printf("The number of Bigger then average are:");
for (i=0; i<m; i++)
{ for (j=0; j<n; j++)
if (arr[i?n+j]>average)
printf("arr[%d][%d]=%d\t",i,j,arr[i?n+j]);
}
}
运行结果,
The number of sum=42
The number of average= 3.00
The number of Bigger then average are,
arr[0] [0]=6 arr[0] [1]=4 arr[0] [2]=9
arr[1] [2]=8 arr[1] [3]=7
arr[2] [1]=4 arr[2] [2]=10
二维数组与一维数组的对应关系,
6 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]
4
9
? 13
?1
3
8
7
3
4
12
2
A[0]
A[1]
A[2]
A[3]
A[4]
A[5]
A[6]
A[7]
A[8]
A[9]
A[10]
A[11]